mirror of https://github.com/mgba-emu/mgba.git
Start Qt frontend
This commit is contained in:
parent
f0481d9413
commit
4659635fb5
|
@ -4,6 +4,7 @@ set(BINARY_NAME gbac CACHE INTERNAL "Name of output binaries")
|
|||
set(CMAKE_C_FLAGS_DEBUG "-g -Wall -Wextra -Wno-error=type-limits --std=gnu99")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -Wall -Wextra --std=gnu99")
|
||||
set(USE_DEBUGGER ON CACHE BOOL "Whether or not to enable the ARM debugger")
|
||||
set(BUILD_QT ON CACHE BOOL "Build Qt frontend")
|
||||
set(EXTRA_LIB "")
|
||||
file(GLOB ARM_SRC ${CMAKE_SOURCE_DIR}/src/arm/*.c)
|
||||
file(GLOB GBA_SRC ${CMAKE_SOURCE_DIR}/src/gba/*.c)
|
||||
|
@ -67,3 +68,7 @@ target_link_libraries(${BINARY_NAME} m ${DEBUGGER_LIB} ${PLATFORM_LIBRARY} ${OPE
|
|||
add_executable(${BINARY_NAME}-bin WIN32 ${MAIN_SRC})
|
||||
target_link_libraries(${BINARY_NAME}-bin ${BINARY_NAME})
|
||||
set_target_properties(${BINARY_NAME}-bin PROPERTIES OUTPUT_NAME ${BINARY_NAME})
|
||||
|
||||
if(BUILD_QT)
|
||||
add_subdirectory(src/platform/qt)
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
cmake_minimum_required(VERSION 2.8.8)
|
||||
project(QGBAc)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra --std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall -Wextra --std=c++11")
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_PREFIX_PATH "/usr/local/opt/qt5") # Temporary stopgap measure
|
||||
endif()
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
|
||||
set(UI_FILES Window.ui)
|
||||
set(SOURCE_FILES Display.cpp GameController.cpp Window.cpp)
|
||||
|
||||
qt5_wrap_ui(UI_HEADERS ${UI_FILES})
|
||||
|
||||
add_executable(QGBAc WIN32 MACOSX_BUNDLE ${UI_FILES} ${UI_HEADERS} main.cpp ${SOURCE_FILES})
|
||||
|
||||
qt5_use_modules(QGBAc Widgets OpenGL)
|
||||
target_link_libraries(QGBAc ${OPENGL_LIBRARY} ${BINARY_NAME})
|
|
@ -0,0 +1,56 @@
|
|||
#include "Display.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
static const GLint _glVertices[] = {
|
||||
0, 0,
|
||||
256, 0,
|
||||
256, 256,
|
||||
0, 256
|
||||
};
|
||||
|
||||
static const GLint _glTexCoords[] = {
|
||||
0, 0,
|
||||
1, 0,
|
||||
1, 1,
|
||||
0, 1
|
||||
};
|
||||
|
||||
Display::Display(QWidget* parent) : QGLWidget(QGLFormat(QGL::Rgba | QGL::DoubleBuffer), parent) {
|
||||
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
||||
QTimer* timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
|
||||
timer->setInterval(0);
|
||||
timer->start();
|
||||
}
|
||||
|
||||
void Display::initializeGL() {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glGenTextures(1, &m_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, m_tex);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
void Display::draw(const QImage& image) {
|
||||
makeCurrent();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, m_tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits());
|
||||
}
|
||||
|
||||
void Display::paintGL() {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_INT, 0, _glVertices);
|
||||
glTexCoordPointer(2, GL_INT, 0, _glTexCoords);
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 240, 160, 0, 0, 1);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, m_tex);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef QGBA_DISPLAY
|
||||
#define QGBA_DISPLAY
|
||||
|
||||
#include <QGLWidget>
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class Display : public QGLWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Display(QWidget* parent = 0);
|
||||
|
||||
protected:
|
||||
virtual void initializeGL();
|
||||
|
||||
public slots:
|
||||
void draw(const QImage& image);
|
||||
void paintGL();
|
||||
|
||||
private:
|
||||
GLuint m_tex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
#include "GameController.h"
|
||||
|
||||
extern "C" {
|
||||
#include "renderers/video-software.h"
|
||||
}
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
GameController::GameController(QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_drawContext(256, 256, QImage::Format_RGB32)
|
||||
{
|
||||
m_renderer = new GBAVideoSoftwareRenderer;
|
||||
GBAVideoSoftwareRendererCreate(m_renderer);
|
||||
m_renderer->outputBuffer = (color_t*) m_drawContext.bits();
|
||||
m_renderer->outputBufferStride = m_drawContext.bytesPerLine() / 4;
|
||||
m_threadContext.useDebugger = 0;
|
||||
m_threadContext.frameskip = 0;
|
||||
m_threadContext.renderer = &m_renderer->d;
|
||||
m_threadContext.frameskip = 0;
|
||||
m_threadContext.sync.videoFrameWait = 0;
|
||||
m_threadContext.sync.audioWait = 0;
|
||||
m_threadContext.startCallback = 0;
|
||||
m_threadContext.cleanCallback = 0;
|
||||
m_threadContext.frameCallback = [] (GBAThread* context) {
|
||||
GameController* controller = (GameController*) context->userData;
|
||||
controller->frameAvailable(controller->m_drawContext);
|
||||
};
|
||||
m_threadContext.userData = this;
|
||||
m_threadContext.rewindBufferCapacity = 0;
|
||||
}
|
||||
|
||||
GameController::~GameController() {
|
||||
delete m_renderer;
|
||||
}
|
||||
|
||||
bool GameController::loadGame(const QString& path) {
|
||||
m_rom = new QFile(path);
|
||||
if (!m_rom->open(QIODevice::ReadOnly)) {
|
||||
delete m_rom;
|
||||
m_rom = 0;
|
||||
return false;
|
||||
}
|
||||
m_threadContext.fd = m_rom->handle();
|
||||
m_threadContext.fname = path.toLocal8Bit().constData();
|
||||
GBAThreadStart(&m_threadContext);
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef QGBA_GAME_CONTROLLER
|
||||
#define QGBA_GAME_CONTROLLER
|
||||
|
||||
#include <QFile>
|
||||
#include <QImage>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
extern "C" {
|
||||
#include "gba-thread.h"
|
||||
}
|
||||
|
||||
struct GBAVideoSoftwareRenderer;
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class GameController : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GameController(QObject* parent = 0);
|
||||
~GameController();
|
||||
|
||||
signals:
|
||||
void frameAvailable(const QImage&);
|
||||
|
||||
public slots:
|
||||
bool loadGame(const QString& path);
|
||||
|
||||
private:
|
||||
QImage m_drawContext;
|
||||
GBAThread m_threadContext;
|
||||
GBAVideoSoftwareRenderer* m_renderer;
|
||||
|
||||
QFile* m_rom;
|
||||
QFile* m_bios;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#include "Window.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
Window::Window(QWidget* parent) : QMainWindow(parent) {
|
||||
setupUi(this);
|
||||
|
||||
m_controller = new GameController(this);
|
||||
m_display = new Display(this);
|
||||
setCentralWidget(m_display);
|
||||
connect(m_controller, SIGNAL(frameAvailable(const QImage&)), m_display, SLOT(draw(const QImage&)));
|
||||
|
||||
connect(actionOpen, SIGNAL(triggered()), this, SLOT(selectROM()));
|
||||
}
|
||||
|
||||
void Window::selectROM() {
|
||||
QString filename = QFileDialog::getOpenFileName(this, tr("Select ROM"));
|
||||
if (!filename.isEmpty()) {
|
||||
m_controller->loadGame(filename);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef QGBA_WINDOW
|
||||
#define QGBA_WINDOW
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "GameController.h"
|
||||
#include "Display.h"
|
||||
|
||||
#include "ui_Window.h"
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class Window : public QMainWindow, Ui::GBAWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Window(QWidget* parent = 0);
|
||||
|
||||
public slots:
|
||||
void selectROM();
|
||||
|
||||
private:
|
||||
GameController* m_controller;
|
||||
Display* m_display;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GBAWindow</class>
|
||||
<widget class="QMainWindow" name="GBAWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>240</width>
|
||||
<height>160</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>240</width>
|
||||
<height>160</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>GBA</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>240</width>
|
||||
<height>160</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>240</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="defaultUp">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionOpen"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
</widget>
|
||||
<action name="actionOpen">
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,10 @@
|
|||
#include <QApplication>
|
||||
#include "Window.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
QApplication application(argc, argv);
|
||||
QGBA::Window window;
|
||||
window.show();
|
||||
|
||||
return application.exec();
|
||||
}
|
Loading…
Reference in New Issue