Start Qt frontend

This commit is contained in:
Jeffrey Pfau 2014-01-28 06:53:38 -08:00
parent f0481d9413
commit 4659635fb5
10 changed files with 336 additions and 0 deletions

View File

@ -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()

View File

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

View File

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

27
src/platform/qt/Display.h Normal file
View File

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

View File

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

View File

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

View File

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

29
src/platform/qt/Window.h Normal file
View File

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

73
src/platform/qt/Window.ui Normal file
View File

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

10
src/platform/qt/main.cpp Normal file
View File

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