BREAKPOINT,
WATCHPOINT,
TRACEPOINT,
+ STEP,
PAUSED,
QUIT,
WAIT,
IRQ_JOYPAD = 0x10,
};
- // Constructors
- GameBoy(std::string rom_name, GameBoyType type=GAMEBOY);
+ // Constructors / destructors
+ GameBoy(GameBoyType type=GAMEBOY);
+ ~GameBoy();
+
+ void load_ROM(std::string rom_name);
// running control methods
void irq(InterruptRequest i) { memory.write(0xFF0F, memory.read(0xFF0F) | i); }
Instruction disassemble_opcode(u16 addr);
static std::string get_port_name(int port);
- private:
friend class GBMemory;
friend class GBVideo;
GBMemory memory;
} regs;
+ void set_flag (Flag f) { regs.flags |= f; }
+ void reset_flag(Flag f) { regs.flags &= (~f); }
+ int check_flag(Flag f) const { return ((regs.flags & f) != 0 ? 1 : 0); }
+
u8 IME; // Interrupt master enable flag
u8 HALT; // Is the CPU halted waiting for an interrupt?
u8 divider_count; // resets every 256 cycles, so we don't need a cmp
u32 timer_count;
static const u32 CYCLE_STEP = 4;
-
+
+ private:
inline void do_call(u16 addr)
{
logger.debug("do_call(0x", std::hex, std::setw(4), std::setfill('0'), addr, ")");
regs.PC = addr;
}
- void set_flag (Flag f) { regs.flags |= f; }
- void reset_flag(Flag f) { regs.flags &= (~f); }
- int check_flag(Flag f) const { return ((regs.flags & f) != 0 ? 1 : 0); }
-
// prevent object copying
GameBoy(const GameBoy&);
GameBoy operator=(const GameBoy&);
// update JOYP register when controls are pushed/released
void update_JOYP();
+
+ // free ROM (used in destructor and load_rom)
+ void free_ROM();
// debug things
struct Breakpoint {
}
-QtBoiEmuThread::QtBoiEmuThread(QObject *parent, QString romName)
- :QThread(parent)
+QtBoiEmuThread::QtBoiEmuThread(QObject *parent)
+ :QThread(parent),
+ status(GameBoy::NORMAL),
+ isPaused(true),
+ frameCount(0),
+ romName(),
+ runningMode(RUN),
+ quitRequested(false),
+ resetRequested(false),
+ romLoaded(false)
{
- gb = new GameBoy(romName.toStdString());
- isPaused = true;
- quitRequested = false;
- frameCount = 0;
}
QtBoiEmuThread::~QtBoiEmuThread()
{
- stop();
- wait();
- delete gb;
}
-void QtBoiEmuThread::toggle_paused()
+void QtBoiEmuThread::loadROM(QString name)
+{
+ romName=name;
+ reset();
+ romLoaded=true;
+}
+
+void QtBoiEmuThread::reset()
{
- isPaused = !isPaused;
+ resetRequested=true;
+}
+
+void QtBoiEmuThread::pause()
+{
+ isPaused = true;
}
void QtBoiEmuThread::cont()
void QtBoiEmuThread::run()
{
- cout << "Running! \\o/" << endl;
+ GameBoy gb;
+ cout << "GB created, emu thread running" << endl;
+
+ // wait until ROM is loaded
+ while(!romLoaded)
+ msleep(500);
+
while(!quitRequested)
{
+ if(resetRequested)
+ {
+ resetRequested = false;
+ gb.load_ROM(romName.toStdString());
+ cout << "Loaded ROM " << romName.toStdString() << endl;
+ }
+
if(isPaused)
- usleep(100);
- else {
+ msleep(10);
+ else
+ {
switch (runningMode)
{
case RUN:
- while (!isPaused &&
- (status == GameBoy::NORMAL || status == GameBoy::WAIT))
+ while (!isPaused && !resetRequested &&
+ (status == GameBoy::NORMAL || status == GameBoy::WAIT))
{
- status = gb->run_cycle();
- if (gb->video.get_frames_rendered() > frameCount)
+ status = gb.run_cycle();
+ if (gb.video.get_frames_rendered() > frameCount)
{
- frameCount = gb->video.get_frames_rendered();
- emit redraw(gb->video.get_screen_buffer());
+ 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)
+ status = gb.run_cycle();
+ if (gb.video.get_frames_rendered() > frameCount)
{
- frameCount = gb->video.get_frames_rendered();
- emit redraw(gb->video.get_screen_buffer());
+ frameCount = gb.video.get_frames_rendered();
+ emit redraw(gb.video.get_screen_buffer());
}
} while(status == GameBoy::WAIT); // do nothing
+ isPaused = true;
break;
}
- print_run_result(*gb, status);
- isPaused=true;
- emit emulationPaused();
+ print_run_result(gb, status);
+ if (isPaused)
+ {
+ emit emulationPaused();
+ }
}
}
+
+ cout << "Exiting emulation thread" << endl;
+
}
#include <iostream>
QtBoiMainWindow::QtBoiMainWindow(QWidget *parent)
- :QMainWindow(parent), emuThread(0)
+ :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);
-
+ screen = new QImage(160, 144, QImage::Format_Indexed8);
+ screen->setNumColors(7);
+ screen->setColor(6, qRgb(0,0,0));
+ screen->setColor(5, qRgb(42,42,42));
+ screen->setColor(4, qRgb(85,85,85));
+ screen->setColor(3, qRgb(127,127,127));
+ screen->setColor(2, qRgb(170,170,170));
+ screen->setColor(1, qRgb(212,212,212));
+ screen->setColor(0, qRgb(255,255,255));
+
+ createMenu();
+ resize(640,480);
+ centralWindow = new QLabel(this);
+ setCentralWidget(centralWindow);
+
+ emuThread = new QtBoiEmuThread(this);
+ emuThread->start();
+
+ connect(emulatorCont, SIGNAL(triggered()), emuThread, SLOT(cont()));
+ connect(emulatorStop, SIGNAL(triggered()), emuThread, SLOT(stop()));
+ connect(emulatorPause, SIGNAL(triggered()), emuThread, SLOT(pause()));
+ connect(emulatorStep, SIGNAL(triggered()), emuThread, SLOT(step()));
+ connect(emulatorReset, SIGNAL(triggered()), emuThread, SLOT(reset()));
+ connect(emuThread, SIGNAL(redraw(const uchar*)), this, SLOT(onRedraw(const uchar*)));
}
QtBoiMainWindow::~QtBoiMainWindow()
{
- if (emuThread) {
- emuThread->stop();
- delete emuThread;
- }
+ if (emuThread) {
+ emuThread->stop();
+ emuThread->wait();
+ 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()));
+ loadROM = new QAction("&Load ROM...", this);
+ quit = new QAction("&Quit", this);
+ emulatorPause = new QAction("&Pause", this);
+ emulatorCont = new QAction("&Go", this);
+ emulatorStop = new QAction("&Stop", this);
+ emulatorStep = new QAction("St&ep", this);
+ emulatorReset = new QAction("&Reset", 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);
+ emulator->addAction(emulatorReset);
+
+ 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();
+ QString filename = QFileDialog::getOpenFileName(this, tr("Load ROM"), "../roms", tr("GameBoy ROMs (*.gb *.gbc)"));
+ if (filename == "") return;
+
+ emuThread->loadROM(filename);
+
}
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));
+ uchar *pixels = screen->bits();
+ memcpy(pixels, buffer, 160*144);
+ centralWindow->setPixmap(QPixmap::fromImage(screen->scaled(320,288)));
}