QTBoi WIP, first steps
authorslack <slack@codemaniacs.com>
Thu, 12 Mar 2009 02:40:14 +0000 (03:40 +0100)
committerslack <slack@codemaniacs.com>
Thu, 12 Mar 2009 02:40:14 +0000 (03:40 +0100)
qtboi/CMakeLists.txt [new file with mode: 0644]
qtboi/QtBoiEmuThread.cc [new file with mode: 0644]
qtboi/QtBoiEmuThread.h [new file with mode: 0644]
qtboi/QtBoiMainWindow.cc [new file with mode: 0644]
qtboi/QtBoiMainWindow.h [new file with mode: 0644]
qtboi/qtboi.cc [new file with mode: 0644]
qtboi/qtboi.h [new file with mode: 0644]

diff --git a/qtboi/CMakeLists.txt b/qtboi/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b6c045c
--- /dev/null
@@ -0,0 +1,19 @@
+FIND_PACKAGE(Qt4 REQUIRED)
+INCLUDE( ${QT_USE_FILE} )
+
+SET(QTBOI_MOC_HDRS
+  QtBoiMainWindow.h
+  QtBoiEmuThread.h
+)
+
+SET(QTBOI_SOURCES
+  qtboi.cc
+  QtBoiMainWindow.cc
+  QtBoiEmuThread.cc
+)
+
+QT4_WRAP_CPP(QTBOI_MOC_SRCS ${QTBOI_MOC_HDRS})
+ADD_EXECUTABLE(qtboi ${QTBOI_SOURCES} ${QTBOI_MOC_SRCS})
+
+TARGET_LINK_LIBRARIES(qtboi ${QT_LIBRARIES} wenboicore)
+
diff --git a/qtboi/QtBoiEmuThread.cc b/qtboi/QtBoiEmuThread.cc
new file mode 100644 (file)
index 0000000..260ba91
--- /dev/null
@@ -0,0 +1,126 @@
+#include "QtBoiEmuThread.h"
+#include <iostream>
+
+using std::cout;
+using std::endl;
+
+void print_run_result(GameBoy &gb, int status)
+{
+
+       if (status == GameBoy::BREAKPOINT)
+       {
+               cout << "Breakpoint reached " << endl;
+               cout << gb.status_string() << endl;
+       }
+       else if (status == GameBoy::WATCHPOINT)
+       {
+               cout << "Watchpoint reached" << endl;
+               
+               cout << "Watchpoint 0x" << std::hex << std::setw(4) << std::setfill('0') <<
+                       int(gb.memory.watchpoint_addr) << " hit at 0x" << gb.regs.PC;
+               
+               // FIXME: Move/expose this things somewhere
+               if (gb.memory.watchpoint_newvalue == 0xFFFF)
+               {
+                       cout << " (READ)" << endl << 
+                               "value = " << int(gb.memory.watchpoint_oldvalue) << endl;
+               }
+               else
+               {
+                       cout << " (WRITE)" << endl <<
+                               "old = " << int(gb.memory.watchpoint_oldvalue) << 
+                               " new = " << int(gb.memory.watchpoint_newvalue) << endl;
+               }
+       }
+       else
+       {
+               cout << "run returned with status " << status << endl;
+               cout << gb.status_string() << endl;
+       }
+}
+
+
+QtBoiEmuThread::QtBoiEmuThread(QObject *parent, QString romName)
+       :QThread(parent)
+{
+       gb = new GameBoy(romName.toStdString());
+       isPaused = true;
+       quitRequested = false;
+       frameCount = 0;
+}
+
+QtBoiEmuThread::~QtBoiEmuThread()
+{
+       stop();
+       wait();
+       delete gb;
+}
+
+void QtBoiEmuThread::toggle_paused()
+{
+       isPaused = !isPaused;
+}
+
+void QtBoiEmuThread::cont()
+{
+       status = GameBoy::NORMAL;
+       runningMode = RUN;
+       isPaused = false;
+}
+
+void QtBoiEmuThread::stop()
+{
+       quitRequested = true;
+       isPaused      = true;
+}
+
+void QtBoiEmuThread::step()
+{
+       runningMode = STEP;
+       isPaused = false;
+}
+
+void QtBoiEmuThread::run()
+{
+       cout << "Running! \\o/" << endl;
+       while(!quitRequested)
+       {
+               if(isPaused)
+                       usleep(100);
+               else {
+                       switch (runningMode)
+                       {
+                               case RUN:
+                                       while (!isPaused && 
+                                                       (status == GameBoy::NORMAL || status == GameBoy::WAIT))
+                                       {
+                                               status = gb->run_cycle();
+                                               if (gb->video.get_frames_rendered() > frameCount)
+                                               {
+                                                       frameCount = gb->video.get_frames_rendered();
+                                                       emit redraw(gb->video.get_screen_buffer());
+                                               }
+                                       }
+                                       break;
+                               case STEP:
+                                       do
+                                       {
+                                               status = gb->run_cycle();
+                                               if (gb->video.get_frames_rendered() > frameCount)
+                                               {
+                                                       frameCount = gb->video.get_frames_rendered();
+                                                       emit redraw(gb->video.get_screen_buffer());
+                                               }
+                                       } while(status == GameBoy::WAIT); // do nothing
+                                       
+                                       break;
+                       }
+
+                       print_run_result(*gb, status);
+                       isPaused=true;
+                       emit emulationPaused(); 
+               }
+       }
+}
+
+
diff --git a/qtboi/QtBoiEmuThread.h b/qtboi/QtBoiEmuThread.h
new file mode 100644 (file)
index 0000000..cb5e804
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef QTBOIEMUTHREAD_H
+#define QTBOIEMUTHREAD_H
+
+#include <QThread>
+#include <QString>
+#include "../core/GameBoy.h"
+
+class QtBoiEmuThread: public QThread
+{
+  Q_OBJECT
+
+  public:
+    GameBoy::run_status status;
+    bool isPaused;
+    int frameCount;
+    QtBoiEmuThread(QObject *parent, QString romName);
+    ~QtBoiEmuThread();
+  public slots:
+    void run();
+    void stop();
+    void toggle_paused();
+    void cont();
+    void step();
+  
+  signals:
+    void emulationPaused();
+    void redraw(const uchar *buffer);
+
+  private:
+    enum RunningMode { RUN, STEP };
+    GameBoy *gb;
+    RunningMode runningMode;
+    bool quitRequested;
+};
+
+
+
+#endif
+
+
diff --git a/qtboi/QtBoiMainWindow.cc b/qtboi/QtBoiMainWindow.cc
new file mode 100644 (file)
index 0000000..d54e075
--- /dev/null
@@ -0,0 +1,104 @@
+#include "QtBoiMainWindow.h"
+
+#include <QMenu>
+#include <QMenuBar>
+#include <QString>
+#include <QFileDialog>
+#include <QPushButton>
+#include <QColor>
+#include <QPainter>
+#include <iostream>
+
+QtBoiMainWindow::QtBoiMainWindow(QWidget *parent)
+  :QMainWindow(parent), emuThread(0)
+{
+  screen = new QImage(160, 144, QImage::Format_Indexed8);
+  screen->setNumColors(8);
+  screen->setColor(7, qRgb(0,0,0));
+  screen->setColor(6, qRgb(36,36,36));
+  screen->setColor(5, qRgb(73,73,73));
+  screen->setColor(4, qRgb(109,109,109));
+  screen->setColor(3, qRgb(146,146,146));
+  screen->setColor(2, qRgb(182,182,182));
+  screen->setColor(1, qRgb(219,219,219));
+  screen->setColor(0, qRgb(255,255,255));
+
+  createMenu();
+  resize(640,480);
+  centralWindow = new QLabel(this);
+  setCentralWidget(centralWindow);
+
+
+}
+
+QtBoiMainWindow::~QtBoiMainWindow()
+{
+  if (emuThread) {
+    emuThread->stop();
+    delete emuThread;
+  }
+}
+
+void QtBoiMainWindow::createMenu()
+{
+  loadROM       = new QAction("&Load ROM...", this);
+  quit          = new QAction("&Quit", this);
+  emulatorPause = new QAction("&Toggle pause", this);
+  emulatorCont  = new QAction("&Go", this);
+  emulatorStop  = new QAction("&Stop", this);
+  emulatorStep  = new QAction("St&ep", this);
+
+  QMenu *file;
+  file = menuBar()->addMenu("&File");
+  file->addAction(loadROM);
+  file->addAction(quit);
+
+  QMenu *emulator;
+  emulator = menuBar()->addMenu("&Emulator");
+  emulator->addAction(emulatorCont);
+  emulator->addAction(emulatorPause);
+  emulator->addAction(emulatorStop);
+
+  QMenu *debug;
+  debug = menuBar()->addMenu("&Debug");
+  debug->addAction(emulatorStep);
+
+  connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));
+  connect(loadROM, SIGNAL(triggered()), this, SLOT(onLoadROM()));
+}
+
+void QtBoiMainWindow::onLoadROM()
+{
+  QString filename = QFileDialog::getOpenFileName(this, tr("Load ROM"), "../roms", tr("GameBoy ROMs (*.gb *.gbc)"));
+  if (filename == "") return;
+
+  std::cout << filename.toStdString() << std::endl;
+  
+  if (emuThread) {
+    emuThread->stop();
+    emuThread->wait();
+    delete emuThread;
+  }
+
+  emuThread = new QtBoiEmuThread(0, filename);
+  
+  connect(emulatorCont, SIGNAL(triggered()), emuThread, SLOT(cont()), Qt::DirectConnection);
+  connect(emulatorStop, SIGNAL(triggered()), emuThread, SLOT(stop()), Qt::DirectConnection);
+  connect(emulatorPause, SIGNAL(triggered()), emuThread, SLOT(toggle_paused()), Qt::DirectConnection);
+  connect(emulatorStep, SIGNAL(triggered()), emuThread, SLOT(step()), Qt::DirectConnection);
+  connect(emuThread, SIGNAL(redraw(const uchar*)), this, SLOT(onRedraw(const uchar*)));
+
+  emuThread->start();
+}
+
+void QtBoiMainWindow::onRedraw(const uchar *buffer)
+{
+  uchar *pixels = screen->bits();
+  memcpy(pixels, buffer, 160*144);
+  //centralWindow->setPixmap(QPixmap::fromImage(screen->scaled(320,288)));
+  centralWindow->setPixmap(QPixmap::fromImage(*screen));
+}
+
+
+
+
diff --git a/qtboi/QtBoiMainWindow.h b/qtboi/QtBoiMainWindow.h
new file mode 100644 (file)
index 0000000..8794aea
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef QTBOIMAINWINDOW_H
+#define QTBOIMAINWINDOW_H
+
+#include <QApplication>
+#include <QMainWindow>
+#include <QPushButton>
+#include <QImage>
+#include <QLabel>
+#include "QtBoiEmuThread.h"
+
+class QtBoiMainWindow: public QMainWindow
+{
+  Q_OBJECT
+
+  public:
+    QtBoiMainWindow(QWidget *parent=0);
+    ~QtBoiMainWindow();
+
+  public slots:
+    void onLoadROM();
+    void onRedraw(const uchar *buffer);
+
+  private:
+    void createMenu();
+    QtBoiEmuThread *emuThread;
+
+    QLabel *centralWindow;
+    QImage *screen;
+
+    QAction *loadROM;
+    QAction *quit;
+    QAction *emulatorPause;
+    QAction *emulatorCont;
+    QAction *emulatorStop;
+    QAction *emulatorStep;
+};
+
+
+#endif
+
+
diff --git a/qtboi/qtboi.cc b/qtboi/qtboi.cc
new file mode 100644 (file)
index 0000000..0cf133f
--- /dev/null
@@ -0,0 +1,11 @@
+#include <QApplication>
+#include "QtBoiMainWindow.h"
+#include "../core/GameBoy.h"
+
+int main(int argc, char *argv[])
+{
+  QApplication app(argc, argv);
+  QtBoiMainWindow mainwindow;
+  mainwindow.show();
+  return app.exec();
+}
diff --git a/qtboi/qtboi.h b/qtboi/qtboi.h
new file mode 100644 (file)
index 0000000..e69de29