mirror of
https://github.com/libretro/gambatte-libretro.git
synced 2025-03-03 13:59:01 +00:00
Add support for DMG palette customization.
git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@93 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
parent
6439c65c8a
commit
635d90090e
@ -29,6 +29,7 @@
|
||||
#include "videodialog.h"
|
||||
#include "inputdialog.h"
|
||||
#include "sounddialog.h"
|
||||
#include "palettedialog.h"
|
||||
#include "blittercontainer.h"
|
||||
|
||||
#include "addaudioengines.h"
|
||||
@ -173,6 +174,16 @@ GambatteQt::GambatteQt(const int argc, const char *const argv[]) :
|
||||
QSettings iniSettings(QSettings::IniFormat, QSettings::UserScope, "gambatte", "gambatte_qt");
|
||||
QString savepath = iniSettings.fileName();
|
||||
savepath.truncate(iniSettings.fileName().lastIndexOf("/") + 1);
|
||||
|
||||
{
|
||||
QString palpath = savepath + "palettes";
|
||||
QDir::root().mkpath(palpath);
|
||||
globalPaletteDialog = new PaletteDialog(palpath, 0, this);
|
||||
romPaletteDialog = new PaletteDialog(palpath, globalPaletteDialog, this);
|
||||
connect(globalPaletteDialog, SIGNAL(accepted()), this, SLOT(globalPaletteChange()));
|
||||
connect(romPaletteDialog, SIGNAL(accepted()), this, SLOT(romPaletteChange()));
|
||||
}
|
||||
|
||||
savepath += "saves";
|
||||
QDir::root().mkpath(savepath);
|
||||
gambatte.set_savedir(savepath.toAscii().data());
|
||||
@ -376,6 +387,22 @@ void GambatteQt::videoSettingsChange() {
|
||||
resetVideoBuffer();
|
||||
}
|
||||
|
||||
void GambatteQt::globalPaletteChange() {
|
||||
romPaletteDialog->externalChange();
|
||||
setDmgPaletteColors();
|
||||
}
|
||||
|
||||
void GambatteQt::romPaletteChange() {
|
||||
globalPaletteDialog->externalChange();
|
||||
setDmgPaletteColors();
|
||||
}
|
||||
|
||||
void GambatteQt::setDmgPaletteColors() {
|
||||
for (unsigned palnum = 0; palnum < 3; ++palnum)
|
||||
for (unsigned colornum = 0; colornum < 4; ++colornum)
|
||||
gambatte.setDmgPaletteColor(palnum, colornum, romPaletteDialog->getColor(palnum, colornum));
|
||||
}
|
||||
|
||||
void GambatteQt::createActions() {
|
||||
exitAct = new QAction(tr("E&xit"), this);
|
||||
exitAct->setShortcut(tr("Ctrl+Q"));
|
||||
@ -387,7 +414,7 @@ void GambatteQt::createActions() {
|
||||
hideMenuAct->setShortcut(tr("Esc"));
|
||||
connect(hideMenuAct, SIGNAL(triggered()), this, SLOT(toggleMenuHidden()));
|
||||
|
||||
fsAct = new QAction(tr("&Full screen"), this);
|
||||
fsAct = new QAction(tr("&Full Screen"), this);
|
||||
fsAct->setShortcut(tr("Ctrl+F"));
|
||||
fsAct->setCheckable(true);
|
||||
connect(fsAct, SIGNAL(triggered()), this, SLOT(toggleFullScreen()));
|
||||
@ -445,6 +472,24 @@ void GambatteQt::createMenus() {
|
||||
settingsm->addAction(act);
|
||||
}
|
||||
|
||||
settingsm->addSeparator();
|
||||
|
||||
{
|
||||
QMenu *const palm = settingsm->addMenu(tr("DMG &Palette"));
|
||||
|
||||
{
|
||||
QAction *act = new QAction(tr("&Global..."), this);
|
||||
connect(act, SIGNAL(triggered()), this, SLOT(execGlobalPaletteDialog()));
|
||||
palm->addAction(act);
|
||||
}
|
||||
|
||||
romPaletteAct = new QAction(tr("Current &ROM..."), this);
|
||||
romPaletteAct->setEnabled(false);
|
||||
connect(romPaletteAct, SIGNAL(triggered()), this, SLOT(execRomPaletteDialog()));
|
||||
palm->addAction(romPaletteAct);
|
||||
}
|
||||
|
||||
settingsm->addSeparator();
|
||||
settingsm->addAction(fsAct);
|
||||
settingsm->addAction(hideMenuAct);
|
||||
|
||||
@ -464,6 +509,13 @@ void GambatteQt::loadFile(const QString &fileName) {
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gambatte.isCgb()) {
|
||||
romPaletteDialog->setSettingsFile(QFileInfo(fileName).completeBaseName() + ".pal");
|
||||
setDmgPaletteColors();
|
||||
}
|
||||
|
||||
romPaletteAct->setEnabled(!gambatte.isCgb());
|
||||
|
||||
setCurrentFile(fileName);
|
||||
|
||||
@ -488,6 +540,14 @@ void GambatteQt::execSoundDialog() {
|
||||
execDialog(soundDialog);
|
||||
}
|
||||
|
||||
void GambatteQt::execGlobalPaletteDialog() {
|
||||
execDialog(globalPaletteDialog);
|
||||
}
|
||||
|
||||
void GambatteQt::execRomPaletteDialog() {
|
||||
execDialog(romPaletteDialog);
|
||||
}
|
||||
|
||||
void GambatteQt::setSamplesPrFrame() {
|
||||
const BlitterWidget::Rational r = blitter->frameTime();
|
||||
const unsigned old = samplesPrFrame;
|
||||
@ -628,7 +688,7 @@ void GambatteQt::setCurrentFile(const QString &fileName) {
|
||||
if (curFile.isEmpty())
|
||||
setWindowTitle(tr("Gambatte"));
|
||||
else
|
||||
setWindowTitle(tr("%1 - %2").arg(strippedName(curFile)) .arg(tr("Gambatte")));
|
||||
setWindowTitle(tr("%1 - %2").arg(strippedName(curFile)).arg(tr("Gambatte")));
|
||||
|
||||
QSettings settings;
|
||||
QStringList files = settings.value("recentFileList").toStringList();
|
||||
|
@ -41,6 +41,7 @@ class BlitterWidget;
|
||||
class VideoDialog;
|
||||
class InputDialog;
|
||||
class SoundDialog;
|
||||
class PaletteDialog;
|
||||
class FullResToggler;
|
||||
class BlitterContainer;
|
||||
class JoyObserver;
|
||||
@ -109,9 +110,12 @@ class GambatteQt : public QMainWindow {
|
||||
QAction *fsAct;
|
||||
QAction *hideMenuAct;
|
||||
QAction *resetAct;
|
||||
QAction *romPaletteAct;
|
||||
InputDialog *inputDialog;
|
||||
SoundDialog *soundDialog;
|
||||
VideoDialog *videoDialog;
|
||||
PaletteDialog *globalPaletteDialog;
|
||||
PaletteDialog *romPaletteDialog;
|
||||
BlitterWidget *blitter;
|
||||
const std::auto_ptr<FullResToggler> fullResToggler;
|
||||
|
||||
@ -142,6 +146,7 @@ class GambatteQt : public QMainWindow {
|
||||
void unpause();
|
||||
void setSamplesPrFrame();
|
||||
void setCurrentFile(const QString &fileName);
|
||||
void setDmgPaletteColors();
|
||||
void soundEngineFailure();
|
||||
void updateRecentFileActions();
|
||||
QString strippedName(const QString &fullFileName);
|
||||
@ -160,9 +165,13 @@ private slots:
|
||||
void inputSettingsChange();
|
||||
void soundSettingsChange();
|
||||
void videoSettingsChange();
|
||||
void globalPaletteChange();
|
||||
void romPaletteChange();
|
||||
void execVideoDialog();
|
||||
void execInputDialog();
|
||||
void execSoundDialog();
|
||||
void execGlobalPaletteDialog();
|
||||
void execRomPaletteDialog();
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
439
gambatte_qt/src/palettedialog.cpp
Normal file
439
gambatte_qt/src/palettedialog.cpp
Normal file
@ -0,0 +1,439 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include "palettedialog.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QPalette>
|
||||
#include <QColorDialog>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QApplication>
|
||||
#include <QDropEvent>
|
||||
#include <QDragEnterEvent>
|
||||
#include <QMimeData>
|
||||
#include <QByteArray>
|
||||
#include <QDataStream>
|
||||
#include <QListView>
|
||||
#include <QStringListModel>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
ColorPicker::ColorPicker(QRgb color, QWidget *parent)
|
||||
: QFrame(parent), w(new QWidget)
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
w->setAutoFillBackground(true);
|
||||
|
||||
setLayout(new QVBoxLayout);
|
||||
layout()->setMargin(0);
|
||||
layout()->addWidget(w);
|
||||
|
||||
setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
|
||||
setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setColor(color);
|
||||
}
|
||||
|
||||
const QColor& ColorPicker::getQColor() const {
|
||||
return w->palette().color(QPalette::Background);
|
||||
}
|
||||
|
||||
void ColorPicker::requestColor() {
|
||||
QColor c = QColorDialog::getColor(QColor(getColor()), this);
|
||||
|
||||
if (c.isValid()) {
|
||||
setColor(c);
|
||||
emit colorChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void ColorPicker::setColor(const QColor &color) {
|
||||
QPalette p(w->palette());
|
||||
p.setColor(QPalette::Background, color);
|
||||
w->setPalette(p);
|
||||
}
|
||||
|
||||
void ColorPicker::dragEnterEvent(QDragEnterEvent *e) {
|
||||
if (e->mimeData()->hasColor() && e->source() != this)
|
||||
e->acceptProposedAction();
|
||||
}
|
||||
|
||||
void ColorPicker::dropEvent(QDropEvent *e) {
|
||||
e->setDropAction(Qt::CopyAction);
|
||||
e->accept();
|
||||
setColor(qvariant_cast<QColor>(e->mimeData()->colorData()));
|
||||
emit colorChanged();
|
||||
}
|
||||
|
||||
void ColorPicker::mousePressEvent(QMouseEvent *e) {
|
||||
dragStartPosition = e->pos();
|
||||
}
|
||||
|
||||
void ColorPicker::mouseMoveEvent(QMouseEvent *e) {
|
||||
if ((e->pos() - dragStartPosition).manhattanLength() < QApplication::startDragDistance())
|
||||
return;
|
||||
|
||||
QDrag *const drag = new QDrag(this);
|
||||
QMimeData *const mimeData = new QMimeData;
|
||||
mimeData->setColorData(getQColor());
|
||||
drag->setMimeData(mimeData);
|
||||
drag->exec(Qt::CopyAction);
|
||||
}
|
||||
|
||||
void ColorPicker::mouseReleaseEvent(QMouseEvent *e) {
|
||||
e->ignore();
|
||||
|
||||
if (e->x() <= width() && e->y() <= height()) {
|
||||
e->accept();
|
||||
requestColor();
|
||||
}
|
||||
}
|
||||
|
||||
void ColorPicker::keyReleaseEvent(QKeyEvent *e) {
|
||||
e->ignore();
|
||||
|
||||
if (e->key() == Qt::Key_Space) {
|
||||
e->accept();
|
||||
requestColor();
|
||||
}
|
||||
}
|
||||
|
||||
QRgb ColorPicker::getColor() const {
|
||||
return getQColor().rgb() & 0xFFFFFF;
|
||||
}
|
||||
|
||||
void ColorPicker::setColor(QRgb rgb32) {
|
||||
setColor(QColor(rgb32));
|
||||
}
|
||||
|
||||
ColorQuad::ColorQuad(const QString &label, QWidget *parent)
|
||||
: QGroupBox(label, parent)
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
setLayout(new QHBoxLayout);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
layout()->addWidget(picker[i] = new ColorPicker);
|
||||
connect(picker[i], SIGNAL(colorChanged()), this, SLOT(pickerChanged()));
|
||||
}
|
||||
|
||||
// setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
}
|
||||
|
||||
void ColorQuad::pickerChanged() {
|
||||
emit colorChanged();
|
||||
}
|
||||
|
||||
void ColorQuad::dragEnterEvent(QDragEnterEvent *e) {
|
||||
if (e->mimeData()->hasFormat("application/x-colorquad") && e->source() != this)
|
||||
e->acceptProposedAction();
|
||||
}
|
||||
|
||||
void ColorQuad::dropEvent(QDropEvent *e) {
|
||||
e->setDropAction(Qt::CopyAction);
|
||||
e->accept();
|
||||
|
||||
QDataStream dataStream(e->mimeData()->data("application/x-colorquad"));
|
||||
QRgb color;
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
dataStream >> color;
|
||||
setColor(i, color);
|
||||
}
|
||||
|
||||
pickerChanged();
|
||||
}
|
||||
|
||||
void ColorQuad::mousePressEvent(QMouseEvent */*e*/) {
|
||||
QByteArray itemData;
|
||||
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
dataStream << getColor(i);
|
||||
|
||||
QMimeData *const mimeData = new QMimeData;
|
||||
mimeData->setData("application/x-colorquad", itemData);
|
||||
|
||||
QDrag *const drag = new QDrag(this);
|
||||
drag->setMimeData(mimeData);
|
||||
drag->exec(Qt::CopyAction);
|
||||
}
|
||||
|
||||
class ImmutableStringListModel : public QStringListModel {
|
||||
public:
|
||||
ImmutableStringListModel(QObject *parent = 0) : QStringListModel(parent) {}
|
||||
ImmutableStringListModel(const QStringList &strings, QObject *parent = 0) : QStringListModel(strings, parent) {}
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const { return QStringListModel::flags(index) & ~Qt::ItemIsEditable; }
|
||||
};
|
||||
|
||||
static void setSchemeList(const QString &savedir, const bool hasGlobal, QStringListModel *const model) {
|
||||
QDir dir(savedir, "*.pal", QDir::Name | QDir::IgnoreCase, QDir::Files | QDir::Readable);
|
||||
QStringList dirlisting(dir.entryList());
|
||||
|
||||
for (QStringList::iterator it = dirlisting.begin(); it != dirlisting.end(); ++it)
|
||||
it->chop(4);
|
||||
|
||||
model->setStringList((hasGlobal ? QStringList("Global Palette") : QStringList()) + QStringList("Current Scheme") + QStringList("Default Grey") + dirlisting);
|
||||
}
|
||||
|
||||
static const QModelIndex schemeIndexOf(const QAbstractItemModel *const model, const QString &schemeStr) {
|
||||
const int rows = model->rowCount();
|
||||
|
||||
for (int i = 0; i < rows; ++i) {
|
||||
if (model->index(i, 0).data().toString() == schemeStr)
|
||||
return model->index(i, 0);
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
PaletteDialog::PaletteDialog(const QString &savepath, const PaletteDialog *global, QWidget *parent)
|
||||
: QDialog(parent), global(global), listView(new QListView), rmSchemeButton(new QPushButton("Remove Scheme"))
|
||||
{
|
||||
setWindowTitle(global ? "Current ROM Palette" : "Global Palette");
|
||||
|
||||
QBoxLayout *const mainLayout = new QVBoxLayout;
|
||||
|
||||
{
|
||||
QBoxLayout *const topLayout = new QHBoxLayout;
|
||||
|
||||
{
|
||||
QGroupBox *const lframe = new QGroupBox("Scheme");
|
||||
QBoxLayout *const frameLayout = new QVBoxLayout;
|
||||
savedir = savepath + "/";
|
||||
QDir::root().mkpath(savedir + "stored/");
|
||||
listView->setModel(new ImmutableStringListModel);
|
||||
setSchemeList(savedir + "stored/", global, reinterpret_cast<QStringListModel*>(listView->model()));
|
||||
frameLayout->addWidget(listView);
|
||||
|
||||
{
|
||||
QPushButton *const saveButton = new QPushButton("Save Scheme...");
|
||||
connect(saveButton, SIGNAL(clicked()), this, SLOT(saveScheme()));
|
||||
frameLayout->addWidget(saveButton);
|
||||
}
|
||||
|
||||
connect(rmSchemeButton, SIGNAL(clicked()), this, SLOT(rmScheme()));
|
||||
frameLayout->addWidget(rmSchemeButton);
|
||||
|
||||
lframe->setLayout(frameLayout);
|
||||
topLayout->addWidget(lframe);
|
||||
}
|
||||
|
||||
{
|
||||
QBoxLayout *const vLayout = new QVBoxLayout;
|
||||
vLayout->addWidget(quads[0] = new ColorQuad("Background"));
|
||||
vLayout->addWidget(quads[1] = new ColorQuad("Sprite 1"));
|
||||
vLayout->addWidget(quads[2] = new ColorQuad("Sprite 2"));
|
||||
topLayout->addLayout(vLayout);
|
||||
// topLayout->setAlignment(vLayout, Qt::AlignTop);
|
||||
}
|
||||
|
||||
mainLayout->addLayout(topLayout);
|
||||
}
|
||||
|
||||
{
|
||||
QPushButton *const okButton = new QPushButton(tr("OK"));
|
||||
QPushButton *const cancelButton = new QPushButton(tr("Cancel"));
|
||||
|
||||
okButton->setDefault(true);
|
||||
|
||||
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
|
||||
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||
|
||||
QBoxLayout *const hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(okButton);
|
||||
hLayout->addWidget(cancelButton);
|
||||
mainLayout->addLayout(hLayout);
|
||||
mainLayout->setAlignment(hLayout, Qt::AlignBottom | Qt::AlignRight);
|
||||
}
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
connect(quads[i], SIGNAL(colorChanged()), listView->selectionModel(), SLOT(clear()));
|
||||
|
||||
connect(listView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(schemeChanged(const QModelIndex&, const QModelIndex&)));
|
||||
|
||||
if (global) {
|
||||
schemeIndex = schemeIndexOf(listView->model(), "Global Palette");
|
||||
restore();
|
||||
store();
|
||||
} else {
|
||||
QSettings settings;
|
||||
settings.beginGroup("palette");
|
||||
loadSettings(settings);
|
||||
settings.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
PaletteDialog::~PaletteDialog() {
|
||||
if (global) {
|
||||
saveToSettingsFile();
|
||||
} else {
|
||||
QSettings settings;
|
||||
settings.beginGroup("palette");
|
||||
saveSettings(settings);
|
||||
settings.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteDialog::saveSettings(QSettings &settings) {
|
||||
settings.setValue("slectedScheme", schemeIndex.data());
|
||||
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
for (unsigned j = 0; j < 4; ++j)
|
||||
settings.setValue(quads[i]->title() + QString::number(j), currentColors[i][j]);
|
||||
}
|
||||
|
||||
void PaletteDialog::loadSettings(QSettings &settings) {
|
||||
schemeIndex = schemeIndexOf(listView->model(), settings.value("slectedScheme", global ? "Global Palette" : "Default Grey").toString());
|
||||
|
||||
if (!schemeIndex.isValid())
|
||||
schemeIndex = schemeIndexOf(listView->model(), "Current Scheme");
|
||||
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
for (unsigned j = 0; j < 4; ++j)
|
||||
currentColors[i][j] = qvariant_cast<QRgb>(settings.value(quads[i]->title() + QString::number(j), (3 - (j & 3)) * 85 * 0x010101));
|
||||
|
||||
restore();
|
||||
store();
|
||||
}
|
||||
|
||||
void PaletteDialog::saveToSettingsFile() {
|
||||
if (!settingsFile.isEmpty()) {
|
||||
if (schemeIndex.data().toString() == "Global Palette") {
|
||||
QDir(savedir).remove(settingsFile);
|
||||
} else {
|
||||
QSettings settings(savedir + settingsFile, QSettings::IniFormat);
|
||||
saveSettings(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteDialog::rmScheme() {
|
||||
{
|
||||
QDir(savedir + "stored/").remove(listView->currentIndex().data().toString() + ".pal");
|
||||
}
|
||||
|
||||
listView->selectionModel()->clear();
|
||||
setSchemeList(savedir + "stored/", global, reinterpret_cast<QStringListModel*>(listView->model()));
|
||||
}
|
||||
|
||||
void PaletteDialog::saveScheme() {
|
||||
bool ok;
|
||||
const QString &text = QInputDialog::getText(this, "Save Scheme", "Scheme name:",
|
||||
QLineEdit::Normal, QString(), &ok);
|
||||
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
if (text.isEmpty() || "Global Palette" == text || "Current Scheme" == text || "Default Grey" == text || text.contains('/')) {
|
||||
QMessageBox::information(this, "Invalid scheme name", "Invalid scheme name.");
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
QSettings settings(savedir + "stored/" + text + ".pal", QSettings::IniFormat);
|
||||
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
for (unsigned j = 0; j < 4; ++j)
|
||||
settings.setValue(quads[i]->title() + QString::number(j), quads[i]->getColor(j));
|
||||
}
|
||||
|
||||
setSchemeList(savedir + "stored/", global, reinterpret_cast<QStringListModel*>(listView->model()));
|
||||
|
||||
listView->setCurrentIndex(schemeIndexOf(listView->model(), text));
|
||||
}
|
||||
|
||||
void PaletteDialog::schemeChanged(const QModelIndex ¤t, const QModelIndex &/*previous*/) {
|
||||
rmSchemeButton->setEnabled(false);
|
||||
|
||||
if (!current.isValid())
|
||||
return;
|
||||
|
||||
const QString &str = current.data().toString();
|
||||
|
||||
if ("Global Palette" == str) {
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
for (unsigned j = 0; j < 4; ++j)
|
||||
quads[i]->setColor(j, global->getColor(i, j));
|
||||
} else if ("Current Scheme" == str) {
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
for (unsigned j = 0; j < 4; ++j)
|
||||
quads[i]->setColor(j, currentColors[i][j]);
|
||||
} else if("Default Grey" == str) {
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
for (unsigned j = 0; j < 4; ++j)
|
||||
quads[i]->setColor(j, (3 - (j & 3)) * 85 * 0x010101);
|
||||
} else {
|
||||
QSettings settings(savedir + "stored/" + str + ".pal", QSettings::IniFormat);
|
||||
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
for (unsigned j = 0; j < 4; ++j)
|
||||
quads[i]->setColor(j, qvariant_cast<QRgb>(settings.value(quads[i]->title() + QString::number(j), 0)));
|
||||
|
||||
rmSchemeButton->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteDialog::store() {
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
for (unsigned j = 0; j < 4; ++j)
|
||||
currentColors[i][j] = quads[i]->getColor(j);
|
||||
|
||||
if (!listView->currentIndex().isValid())
|
||||
listView->setCurrentIndex(schemeIndexOf(listView->model(), "Current Scheme")); //obs: will emit currentChanged()
|
||||
|
||||
schemeIndex = listView->currentIndex();
|
||||
}
|
||||
|
||||
void PaletteDialog::restore() {
|
||||
listView->setCurrentIndex(schemeIndex);
|
||||
}
|
||||
|
||||
void PaletteDialog::externalChange() {
|
||||
const QString &str = schemeIndex.data().toString();
|
||||
setSchemeList(savedir + "stored/", global, reinterpret_cast<QStringListModel*>(listView->model()));
|
||||
listView->setCurrentIndex(schemeIndexOf(listView->model(), str));
|
||||
store();
|
||||
}
|
||||
|
||||
void PaletteDialog::setSettingsFile(const QString &filename) {
|
||||
saveToSettingsFile();
|
||||
|
||||
settingsFile = filename;
|
||||
|
||||
QSettings settings(savedir + settingsFile, QSettings::IniFormat);
|
||||
loadSettings(settings);
|
||||
}
|
||||
|
||||
void PaletteDialog::accept() {
|
||||
store();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void PaletteDialog::reject() {
|
||||
restore();
|
||||
QDialog::reject();
|
||||
}
|
120
gambatte_qt/src/palettedialog.h
Normal file
120
gambatte_qt/src/palettedialog.h
Normal file
@ -0,0 +1,120 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef PALETTEDIALOG_H
|
||||
#define PALETTEDIALOG_H
|
||||
|
||||
class QListView;
|
||||
class QPushButton;
|
||||
class QSettings;
|
||||
|
||||
#include <QDialog>
|
||||
#include <QColor>
|
||||
#include <QFrame>
|
||||
#include <QPoint>
|
||||
#include <QSize>
|
||||
#include <QGroupBox>
|
||||
#include <QModelIndex>
|
||||
#include <QString>
|
||||
|
||||
class ColorPicker : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
QWidget *const w;
|
||||
QPoint dragStartPosition;
|
||||
|
||||
const QColor& getQColor() const;
|
||||
void requestColor();
|
||||
void setColor(const QColor &color);
|
||||
|
||||
protected:
|
||||
void dragEnterEvent(QDragEnterEvent *e);
|
||||
void dropEvent(QDropEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void mouseReleaseEvent(QMouseEvent *e);
|
||||
void keyReleaseEvent(QKeyEvent *e);
|
||||
|
||||
public:
|
||||
ColorPicker(QRgb color = 0xFFFFFF, QWidget *parent = 0);
|
||||
QRgb getColor() const;
|
||||
void setColor(QRgb rgb32);
|
||||
QSize sizeHint() const { return QSize(4*6, 3*6); }
|
||||
|
||||
signals:
|
||||
void colorChanged();
|
||||
};
|
||||
|
||||
class ColorQuad : public QGroupBox {
|
||||
Q_OBJECT
|
||||
|
||||
ColorPicker* picker[4];
|
||||
|
||||
private slots:
|
||||
void pickerChanged();
|
||||
|
||||
protected:
|
||||
void dragEnterEvent(QDragEnterEvent *e);
|
||||
void dropEvent(QDropEvent *e);
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
|
||||
public:
|
||||
ColorQuad(const QString &label, QWidget *parent = 0);
|
||||
QRgb getColor(unsigned index) const { return picker[index & 3]->getColor(); }
|
||||
void setColor(unsigned index, QRgb color) { picker[index & 3]->setColor(color); }
|
||||
|
||||
signals:
|
||||
void colorChanged();
|
||||
};
|
||||
|
||||
class PaletteDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
const PaletteDialog *const global;
|
||||
QListView *const listView;
|
||||
QPushButton *const rmSchemeButton;
|
||||
ColorQuad *quads[3];
|
||||
QRgb currentColors[3][4];
|
||||
QModelIndex schemeIndex;
|
||||
QString savedir;
|
||||
QString settingsFile;
|
||||
|
||||
void saveSettings(QSettings &settings);
|
||||
void loadSettings(QSettings &settings);
|
||||
void saveToSettingsFile();
|
||||
void store();
|
||||
void restore();
|
||||
|
||||
private slots:
|
||||
void rmScheme();
|
||||
void saveScheme();
|
||||
void schemeChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
|
||||
public:
|
||||
PaletteDialog(const QString &savepath, const PaletteDialog *global = 0, QWidget *parent = 0);
|
||||
~PaletteDialog();
|
||||
QRgb getColor(unsigned palnum, unsigned colornum) const { return currentColors[palnum < 3 ? palnum : 2][colornum & 3]; }
|
||||
void externalChange();
|
||||
void setSettingsFile(const QString &filename);
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
void reject();
|
||||
};
|
||||
|
||||
#endif
|
@ -13,7 +13,8 @@ SOURCES += gambatte_qt.cpp \
|
||||
SDL_Joystick/src/SDL_joystick.c \
|
||||
SDL_Joystick/src/SDL_string.c \
|
||||
sounddialog.cpp \
|
||||
audioengines/customdevconf.cpp
|
||||
audioengines/customdevconf.cpp \
|
||||
palettedialog.cpp
|
||||
|
||||
HEADERS += gambatte_qt.h \
|
||||
blitterwidget.h \
|
||||
@ -42,7 +43,8 @@ SDL_Joystick/src/SDL_joystick_c.h \
|
||||
SDL_Joystick/src/SDL_sysjoystick.h \
|
||||
sounddialog.h \
|
||||
audioengines/nullaudioengine.h \
|
||||
audioengines/customdevconf.h
|
||||
audioengines/customdevconf.h \
|
||||
palettedialog.h
|
||||
|
||||
TEMPLATE = app
|
||||
CONFIG += warn_on \
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
void videoBufferChange();
|
||||
unsigned int videoWidth() const;
|
||||
unsigned int videoHeight() const;
|
||||
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32);
|
||||
|
||||
void setVideoFilter(unsigned int n);
|
||||
std::vector<const FilterInfo*> filterInfo() const;
|
||||
@ -48,6 +49,7 @@ public:
|
||||
void fill_buffer(uint16_t *stream, unsigned samples);
|
||||
|
||||
void set_savedir(const char *sdir);
|
||||
bool isCgb() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -88,6 +88,12 @@ public:
|
||||
void sound_fill_buffer(uint16_t *const stream, const unsigned samples) {
|
||||
memory.sound_fill_buffer(stream, samples, cycleCounter_);
|
||||
}
|
||||
|
||||
bool isCgb() const { return memory.isCgb(); }
|
||||
|
||||
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) {
|
||||
memory.setDmgPaletteColor(palNum, colorNum, rgb32, cycleCounter_);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -73,3 +73,11 @@ bool Gambatte::load(const char* romfile) {
|
||||
void Gambatte::fill_buffer(uint16_t *const stream, const unsigned samples) {
|
||||
z80->sound_fill_buffer(stream, samples);
|
||||
}
|
||||
|
||||
bool Gambatte::isCgb() const {
|
||||
return z80->isCgb();
|
||||
}
|
||||
|
||||
void Gambatte::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) {
|
||||
z80->setDmgPaletteColor(palNum, colorNum, rgb32);
|
||||
}
|
||||
|
@ -1981,6 +1981,11 @@ void Memory::setVideoFilter(const unsigned int n, const unsigned cycleCounter) {
|
||||
refreshPalettes(cycleCounter);
|
||||
}
|
||||
|
||||
void Memory::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32, unsigned cycleCounter) {
|
||||
display.setDmgPaletteColor(palNum, colorNum, rgb32);
|
||||
refreshPalettes(cycleCounter);
|
||||
}
|
||||
|
||||
Memory::~Memory() {
|
||||
if (battery)
|
||||
saveram();
|
||||
|
@ -181,6 +181,8 @@ public:
|
||||
std::vector<const FilterInfo*> filterInfo() const {
|
||||
return display.filterInfo();
|
||||
}
|
||||
|
||||
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32, unsigned cycleCounter);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "video/basic_add_event.h"
|
||||
|
||||
/*
|
||||
const uint32_t LCD::dmgColorsRgb32[4] = { 3 * 85 * 0x010101, 2 * 85 * 0x010101, 1 * 85 * 0x010101, 0 * 85 * 0x010101 };
|
||||
const uint32_t LCD::dmgColorsRgb16[4] = { 3 * 10 * 0x0841, 2 * 10 * 0x0841, 1 * 10 * 0x0841, 0 * 10 * 0x0841 };
|
||||
|
||||
@ -43,6 +44,7 @@ const uint32_t LCD::dmgColorsUyvy[4] = {
|
||||
0x00800080 | (16 + 73 * 1) * 0x01000100U,
|
||||
0x00800080 | (16 + 73 * 0) * 0x01000100U };
|
||||
#endif
|
||||
*/
|
||||
|
||||
void LCD::setDmgPalette(uint32_t *const palette, const uint32_t *const dmgColors, const unsigned data) {
|
||||
palette[0] = dmgColors[data & 3];
|
||||
@ -113,6 +115,10 @@ LCD::LCD(const uint8_t *const oamram, const uint8_t *const vram_in) :
|
||||
pb.format = PixelBuffer::RGB32;
|
||||
pb.pitch = 0;
|
||||
|
||||
for (unsigned i = 0; i < sizeof(dmgColorsRgb32) / sizeof(uint32_t); ++i) {
|
||||
setDmgPaletteColor(i, (3 - (i & 3)) * 85 * 0x010101);
|
||||
}
|
||||
|
||||
filters.push_back(NULL);
|
||||
filters.push_back(new Catrom2x);
|
||||
filters.push_back(new Catrom3x);
|
||||
@ -983,6 +989,19 @@ void LCD::setDBuffer() {
|
||||
draw = &LCD::null_draw;
|
||||
}
|
||||
|
||||
void LCD::setDmgPaletteColor(const unsigned index, const unsigned rgb32) {
|
||||
dmgColorsRgb32[index] = rgb32;
|
||||
dmgColorsRgb16[index] = Rgb16Putter::toRgb16(rgb32);
|
||||
dmgColorsUyvy[index] = UyvyPutter::toUyvy(rgb32);
|
||||
}
|
||||
|
||||
void LCD::setDmgPaletteColor(const unsigned palNum, const unsigned colorNum, const unsigned rgb32) {
|
||||
if (palNum > 2 || colorNum > 3)
|
||||
return;
|
||||
|
||||
setDmgPaletteColor(palNum * 4 | colorNum, rgb32);
|
||||
}
|
||||
|
||||
void LCD::null_draw(unsigned /*xpos*/, const unsigned ypos, const unsigned endX) {
|
||||
const bool enableWindow = (weMasterChecker.weMaster() || ypos == wyReg.value()) && we.value() && wyReg.value() <= ypos && wxReader.wx() < 0xA7;
|
||||
|
||||
|
@ -51,9 +51,9 @@ class Filter;
|
||||
|
||||
class LCD {
|
||||
//static const uint8_t xflipt[0x100];
|
||||
static const uint32_t dmgColorsRgb32[4];
|
||||
static const uint32_t dmgColorsRgb16[4];
|
||||
static const uint32_t dmgColorsUyvy[4];
|
||||
uint32_t dmgColorsRgb32[3 * 4];
|
||||
uint32_t dmgColorsRgb16[3 * 4];
|
||||
uint32_t dmgColorsUyvy[3 * 4];
|
||||
|
||||
uint32_t bgPalette[8 * 4];
|
||||
uint32_t spPalette[8 * 4];
|
||||
@ -120,6 +120,7 @@ class LCD {
|
||||
bool spriteEnable;
|
||||
|
||||
static void setDmgPalette(uint32_t *palette, const uint32_t *dmgColors, unsigned data);
|
||||
void setDmgPaletteColor(unsigned index, unsigned rgb32);
|
||||
static unsigned gbcToRgb32(unsigned bgr15);
|
||||
static unsigned gbcToRgb16(unsigned bgr15);
|
||||
static unsigned gbcToUyvy(unsigned bgr15);
|
||||
@ -160,6 +161,7 @@ public:
|
||||
std::vector<const FilterInfo*> filterInfo() const;
|
||||
unsigned int videoWidth() const;
|
||||
unsigned int videoHeight() const;
|
||||
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32);
|
||||
|
||||
void wdTileMapSelectChange(bool newValue, unsigned cycleCounter);
|
||||
void bgTileMapSelectChange(bool newValue, unsigned cycleCounter);
|
||||
@ -174,12 +176,12 @@ public:
|
||||
|
||||
void dmgSpPalette1Change(const unsigned data, const unsigned cycleCounter) {
|
||||
update(cycleCounter);
|
||||
setDmgPalette(spPalette, dmgColors, data);
|
||||
setDmgPalette(spPalette, dmgColors + 4, data);
|
||||
}
|
||||
|
||||
void dmgSpPalette2Change(const unsigned data, const unsigned cycleCounter) {
|
||||
update(cycleCounter);
|
||||
setDmgPalette(spPalette + 4, dmgColors, data);
|
||||
setDmgPalette(spPalette + 4, dmgColors + 8, data);
|
||||
}
|
||||
|
||||
void cgbBgColorChange(const unsigned index, const unsigned bgr15, const unsigned cycleCounter) {
|
||||
|
@ -34,26 +34,43 @@ class Rgb16Putter {
|
||||
public:
|
||||
typedef uint16_t pixel_t;
|
||||
|
||||
static unsigned toRgb16(const unsigned rgb32) {
|
||||
return rgb32 >> 8 & 0xF800 | rgb32 >> 5 & 0x07E0 | rgb32 >> 3 & 0x001F;
|
||||
}
|
||||
|
||||
void operator()(pixel_t *const dest, const unsigned rgb32) {
|
||||
// const unsigned tmp = (rgb32 & 0xFCFEFC) + 0x040204;
|
||||
const unsigned tmp = rgb32;
|
||||
|
||||
*dest = tmp >> 8 & 0xF800 | tmp >> 5 & 0x07E0 | tmp >> 3 & 0x001F;
|
||||
*dest = toRgb16(rgb32);
|
||||
}
|
||||
};
|
||||
|
||||
class UyvyPutter {
|
||||
public:
|
||||
typedef uint32_t pixel_t;
|
||||
|
||||
void operator()(pixel_t *const dest, const unsigned rgb32) {
|
||||
static void convert(unsigned &y, unsigned &u, unsigned &v, const unsigned rgb32) {
|
||||
const unsigned r = rgb32 >> 16;
|
||||
const unsigned g = rgb32 >> 8 & 0xFF;
|
||||
const unsigned b = rgb32 & 0xFF;
|
||||
|
||||
const unsigned y = r * 66 + g * 129 + b * 25 + 16 * 256 + 128 >> 8;
|
||||
const unsigned u = b * 112 - r * 38 - g * 74 + 128 * 256 + 128 >> 8;
|
||||
const unsigned v = r * 112 - g * 94 - b * 18 + 128 * 256 + 128 >> 8;
|
||||
y = r * 66 + g * 129 + b * 25 + 16 * 256 + 128 >> 8;
|
||||
u = b * 112 - r * 38 - g * 74 + 128 * 256 + 128 >> 8;
|
||||
v = r * 112 - g * 94 - b * 18 + 128 * 256 + 128 >> 8;
|
||||
}
|
||||
|
||||
public:
|
||||
typedef uint32_t pixel_t;
|
||||
|
||||
static unsigned toUyvy(const unsigned rgb32) {
|
||||
unsigned y, u, v;
|
||||
convert(y, u, v, rgb32);
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
return u << 24 | y << 16 | v << 8 | y;
|
||||
#else
|
||||
return y << 24 | v << 16 | y << 8 | u;
|
||||
#endif
|
||||
}
|
||||
|
||||
void operator()(pixel_t *const dest, const unsigned rgb32) {
|
||||
unsigned y, u, v;
|
||||
convert(y, u, v, rgb32);
|
||||
|
||||
uint8_t * d = reinterpret_cast<uint8_t*>(dest);
|
||||
*d++ = u;
|
||||
|
Loading…
x
Reference in New Issue
Block a user