all repos — mgba @ a6ce525da1ed0f7e14e8db927871d2127681fc95

mGBA Game Boy Advance Emulator

Merge branch 'master' (early part) into medusa
Vicki Pfau vi@endrift.com
Fri, 28 Jun 2019 15:48:27 -0700
commit

a6ce525da1ed0f7e14e8db927871d2127681fc95

parent

1a0e44c014ad34bea30d237d27015d82d02cda4b

M README.mdREADME.md

@@ -10,7 +10,7 @@

Features -------- -- Near full Game Boy Advance hardware support[<sup>[1]</sup>](#missing). +- Highly accurate Game Boy Advance hardware support[<sup>[1]</sup>](#missing). - Partial DS hardware support[<sup>[1]</sup>](#missing). - Game Boy/Game Boy Color hardware support. - Fast emulation for Game Boy and Game Boy Advance. Known to run at full speed even on low end hardware, such as netbooks[<sup>[2]</sup>](#dscaveat).

@@ -19,6 +19,7 @@ - Local (same computer) link cable support.

- Save type detection, even for flash memory size[<sup>[3]</sup>](#flashdetect). - Support for cartridges with motion sensors and rumble (only usable with game controllers)[<sup>[2]</sup>](#dscaveat). - Real-time clock support, even without configuration. +- Solar sensor support for Boktai games. - Game Boy Camera and Game Boy Printer support. - A built-in GBA BIOS implementation, and ability to load external BIOS files. DS currently requires BIOS and firmware dumps[<sup>[2]</sup>](#dscaveat). - Turbo/fast-forward support by holding Tab.

@@ -36,6 +37,31 @@ - Configurable emulation rewinding.

- Support for loading and exporting GameShark and Action Replay snapshots. - Cores available for RetroArch/Libretro and OpenEmu. - Many, many smaller things. + +#### Game Boy mappers + +The following mappers are fully supported: + +- MBC1 +- MBC1M +- MBC2 +- MBC3 +- MBC3+RTC +- MBC5 +- MBC5+Rumble +- MBC7 + +The following mappers are partially supported: + +- Pocket Cam +- TAMA5 +- HuC-3 + +The following mappers are not currently supported: + +- MBC6 +- HuC-1 +- MMM01 ### Planned features

@@ -128,11 +154,11 @@ To build on Windows for development, using MSYS2 is recommended. Follow the installation steps found on their [website](https://msys2.github.io). Make sure you're running the 32-bit version ("MSYS2 MinGW 32-bit") (or the 64-bit version "MSYS2 MinGW 64-bit" if you want to build for x86_64) and run this additional command (including the braces) to install the needed dependencies (please note that this involves downloading over 1100MiB of packages, so it will take a long time):

For x86 (32 bit) builds: - pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libzip,pkg-config,qt5,SDL2,ntldd-git} + pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} For x86_64 (64 bit) builds: - pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libzip,pkg-config,qt5,SDL2,ntldd-git} + pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} Check out the source code by running this command:
M README_DE.mdREADME_DE.md

@@ -10,7 +10,7 @@

Features -------- -- Nahzu vollständige Unterstützung der Game Boy Advance-Hardware[<sup>[1]</sup>](#missing). +- Sehr genaue Unterstützung der Game Boy Advance-Hardware[<sup>[1]</sup>](#missing). - Unterstützung der Game Boy-/Game Boy Color-Hardware. - Schnelle Emulation. mGBA ist dafür bekannt, auch auf schwacher Hardware wie Netbooks mit voller Geschwindigkeit zu laufen. - Qt- und SDL-Portierungen für eine vollwertige und eine "leichtgewichtige" Benutzeroberfläche.

@@ -18,6 +18,7 @@ - Lokale (gleicher Computer) Unterstützung für Link-Kabel.

- Erkennung des Speichertypes, einschließlich der Größe des Flash-Speichers[<sup>[2]</sup>](#flashdetect). - Unterstützung für Spielmodule mit Bewegungssensoren und Rüttel-Effekten (nur verwendbar mit Spiele-Controllern). - Unterstützung für Echtzeituhren, selbst ohne Konfiguration. +- Unterstützung für den Lichtsensor in Boktai-Spielen - Unterstützung für Game Boy Printer und Game Boy Camera. - Eingebaute BIOS-Implementierung mit der Möglichkeit, externe BIOS-Dateien zu laden. - Turbo/Vorlauf-Unterstützung durch drücken der Tab-Taste.

@@ -35,6 +36,31 @@ - Einstellbare Rücklauf-Funktion.

- Unterstützung für das Laden und Exportieren von GameShark- und Action Replay-Abbildern. - Verfügbare Cores für RetroArch/Libretro und OpenEmu. - Viele, viele kleinere Dinge. + +### Game Boy-Mapper + +Die folgenden Mapper werden vollständig unterstützt: + +- MBC1 +- MBC1M +- MBC2 +- MBC3 +- MBC3+RTC (MBC3+Echtzeituhr) +- MBC5 +- MBC5+Rumble (MBC5+Rüttel-Modul) +- MBC7 + +Die folgenden Mapper werden teilweise unterstützt: + +- Pocket Cam +- TAMA5 +- HuC-3 + +Die folgenden Mapper werden derzeit nicht unterstützt: + +- MBC6 +- HuC-1 +- MMM01 ### Geplante Features

@@ -110,11 +136,11 @@ Um mGBA auf Windows zu kompilieren, wird MSYS2 empfohlen. Befolge die Installationsschritte auf der [MSYS2-Website](https://msys2.github.io). Stelle sicher, dass Du die 32-Bit-Version ("MSYS2 MinGW 32-bit") (oder die 64-Bit-Version "MSYS2 MinGW 64-bit", wenn Du mGBA für x86_64 kompilieren willst) verwendest und führe folgendes Kommando (einschließlich der Klammern) aus, um alle benötigten Abhängigkeiten zu installieren. Bitte beachte, dass dafür über 1100MiB an Paketen heruntergeladen werden, was eine Weile dauern kann:

Für x86 (32 Bit): - pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libzip,pkg-config,qt5,SDL2,ntldd-git} + pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} Für x86_64 (64 Bit): - pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libzip,pkg-config,qt5,SDL2,ntldd-git} + pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} Lade den aktuellen mGBA-Quellcode mithilfe des folgenden Kommandos herunter:
M include/mgba/core/core.hinclude/mgba/core/core.h

@@ -203,7 +203,9 @@

#ifdef USE_ELF struct ELF; bool mCoreLoadELF(struct mCore* core, struct ELF* elf); +#ifdef USE_DEBUGGERS void mCoreLoadELFSymbols(struct mDebuggerSymbols* symbols, struct ELF*); +#endif #endif CXX_GUARD_END
M src/core/core.csrc/core/core.c

@@ -357,6 +357,7 @@ }

return true; } +#ifdef USE_DEBUGGERS void mCoreLoadELFSymbols(struct mDebuggerSymbols* symbols, struct ELF* elf) { size_t symIndex = ELFFindSection(elf, ".symtab"); size_t names = ELFFindSection(elf, ".strtab");

@@ -376,5 +377,5 @@ }

mDebuggerSymbolAdd(symbols, name, syms[i].st_value, -1); } } - +#endif #endif
M src/gb/gb.csrc/gb/gb.c

@@ -612,6 +612,7 @@

void GBUpdateIRQs(struct GB* gb) { int irqs = gb->memory.ie & gb->memory.io[REG_IF]; if (!irqs) { + gb->cpu->irqPending = false; return; } gb->cpu->halted = false;
M src/gba/core.csrc/gba/core.c

@@ -738,7 +738,9 @@ return;

} struct ELF* elf = ELFOpen(vf); if (elf) { +#ifdef USE_DEBUGGERS mCoreLoadELFSymbols(core->symbolTable, elf); +#endif ELFClose(elf); } if (closeAfter) {
M src/gba/memory.csrc/gba/memory.c

@@ -1629,7 +1629,7 @@ void _pristineCow(struct GBA* gba) {

if (!gba->isPristine) { return; } -#ifndef FIXED_ROM_BUFFER +#if !defined(FIXED_ROM_BUFFER) && !defined(__wii__) void* newRom = anonymousMemoryMap(SIZE_CART0); memcpy(newRom, gba->memory.rom, gba->memory.romSize); memset(((uint8_t*) newRom) + gba->memory.romSize, 0xFF, SIZE_CART0 - gba->memory.romSize);
M src/platform/libretro/libretro.csrc/platform/libretro/libretro.c

@@ -76,6 +76,16 @@ if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {

opts.skipBios = strcmp(var.value, "ON") == 0; } + var.key = "mgba_sgb_borders"; + var.value = 0; + if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (strcmp(var.value, "ON") == 0) { + mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", true); + } else { + mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", false); + } + } + var.key = "mgba_idle_optimization"; var.value = 0; if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {

@@ -111,6 +121,7 @@ { "mgba_solar_sensor_level", "Solar sensor level; 0|1|2|3|4|5|6|7|8|9|10" },

{ "mgba_allow_opposing_directions", "Allow opposing directional input; OFF|ON" }, { "mgba_use_bios", "Use BIOS file if found (requires restart); ON|OFF" }, { "mgba_skip_bios", "Skip BIOS intro (requires restart); OFF|ON" }, + { "mgba_sgb_borders", "Use Super Game Boy borders (requires restart); ON|OFF" }, { "mgba_idle_optimization", "Idle loop removal; Remove Known|Detect and Remove|Don't Remove" }, { "mgba_frameskip", "Frameskip; 0|1|2|3|4|5|6|7|8|9|10" }, { 0, 0 }
M src/platform/python/engine.csrc/platform/python/engine.c

@@ -83,10 +83,12 @@

void mPythonScriptEngineRun(struct mScriptEngine* se) { struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se; +#ifdef USE_DEBUGGERS struct mDebugger* debugger = mScriptBridgeGetDebugger(engine->sb); if (debugger) { mPythonSetDebugger(debugger); } +#endif mPythonRunPending(); }
M src/platform/qt/Display.cppsrc/platform/qt/Display.cpp

@@ -8,12 +8,6 @@

#include "DisplayGL.h" #include "DisplayQt.h" -#ifdef M_CORE_GB -#include <mgba/internal/gb/video.h> -#elif defined(M_CORE_GBA) -#include <mgba/internal/gba/video.h> -#endif - using namespace QGBA; #if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)

@@ -55,11 +49,6 @@ Display::Display(QWidget* parent)

: QWidget(parent) { setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); -#ifdef M_CORE_GB - setMinimumSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS); -#elif defined(M_CORE_GBA) - setMinimumSize(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); -#endif connect(&m_mouseTimer, &QTimer::timeout, this, &Display::hideCursor); m_mouseTimer.setSingleShot(true); m_mouseTimer.setInterval(MOUSE_DISAPPEAR_TIMER);
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -458,7 +458,9 @@ connect(settingsWindow, &SettingsView::audioDriverChanged, this, &Window::reloadAudioDriver);

connect(settingsWindow, &SettingsView::cameraDriverChanged, this, &Window::mustRestart); connect(settingsWindow, &SettingsView::languageChanged, this, &Window::mustRestart); connect(settingsWindow, &SettingsView::pathsChanged, this, &Window::reloadConfig); +#ifdef USE_SQLITE3 connect(settingsWindow, &SettingsView::libraryCleared, m_libraryView, &LibraryController::clear); +#endif openView(settingsWindow); }

@@ -723,8 +725,6 @@ #endif

multiplayerChanged(); updateTitle(); QSize size = m_controller->screenDimensions(); - m_display->setMinimumSize(size); - m_screenWidget->setMinimumSize(m_display->minimumSize()); m_screenWidget->setDimensions(size.width(), size.height()); m_config->updateOption("lockIntegerScaling"); m_config->updateOption("lockAspectRatio");

@@ -733,6 +733,7 @@ resizeFrame(size * m_savedScale);

} attachWidget(m_display.get()); setMouseTracking(true); + m_display->setMinimumSize(size); #ifndef Q_OS_MAC if (isFullScreen()) {

@@ -805,7 +806,6 @@ m_display->setMinimumSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS);

#elif defined(M_CORE_GBA) m_display->setMinimumSize(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); #endif - m_screenWidget->setMinimumSize(m_display->minimumSize()); setMouseTracking(false); m_videoLayers->clear();

@@ -858,8 +858,7 @@ #if defined(BUILD_GL) || defined(BUILD_GLES2)

m_shaderView.reset(); m_shaderView = std::make_unique<ShaderSelector>(m_display.get(), m_config); #endif - m_screenWidget->setMinimumSize(m_display->minimumSize()); - m_screenWidget->setSizePolicy(m_display->sizePolicy()); + connect(this, &Window::shutdown, m_display.get(), &Display::stopDrawing); connect(m_display.get(), &Display::hideCursor, [this]() { if (static_cast<QStackedLayout*>(m_screenWidget->layout())->currentWidget() == m_display.get()) {

@@ -885,6 +884,7 @@ }

#endif if (m_controller) { + m_display->setMinimumSize(m_controller->screenDimensions()); connect(m_controller.get(), &CoreController::stopping, m_display.get(), &Display::stopDrawing); connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::forceDraw); connect(m_controller.get(), &CoreController::rewound, m_display.get(), &Display::forceDraw);

@@ -895,6 +895,12 @@ connect(m_controller.get(), &CoreController::statusPosted, m_display.get(), &Display::showMessage);

attachWidget(m_display.get()); m_display->startDrawing(m_controller); + } else { +#ifdef M_CORE_GB + m_display->setMinimumSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS); +#elif defined(M_CORE_GBA) + m_display->setMinimumSize(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); +#endif } }

@@ -1018,6 +1024,7 @@ });

} m_stateWindow->setAttribute(Qt::WA_DeleteOnClose); m_stateWindow->setMode(ls); + updateFrame(); attachWidget(m_stateWindow); }

@@ -1757,6 +1764,16 @@ m_controller->setPaused(true);

} } +void Window::updateFrame() { + QSize size = m_controller->screenDimensions(); + QImage currentImage(reinterpret_cast<const uchar*>(m_controller->drawContext()), size.width(), size.height(), + size.width() * BYTES_PER_PIXEL, QImage::Format_RGBX8888); + QPixmap pixmap; + pixmap.convertFromImage(currentImage); + m_screenWidget->setPixmap(pixmap); + emit paused(true); +} + void Window::setController(CoreController* controller, const QString& fname) { if (!controller) { return;

@@ -1793,15 +1810,7 @@ m_controller.reset();

}); } connect(m_controller.get(), &CoreController::stopping, &m_inputController, &InputController::resumeScreensaver); - connect(m_controller.get(), &CoreController::paused, [this]() { - QSize size = m_controller->screenDimensions(); - QImage currentImage(reinterpret_cast<const uchar*>(m_controller->drawContext()), size.width(), size.height(), - size.width() * BYTES_PER_PIXEL, QImage::Format_RGBX8888); - QPixmap pixmap; - pixmap.convertFromImage(currentImage); - m_screenWidget->setPixmap(pixmap); - emit paused(true); - }); + connect(m_controller.get(), &CoreController::paused, this, &Window::updateFrame); #ifndef Q_OS_MAC connect(m_controller.get(), &CoreController::paused, menuBar(), &QWidget::show);

@@ -1831,13 +1840,17 @@ connect(m_controller.get(), &CoreController::crashed, this, &Window::gameCrashed);

connect(m_controller.get(), &CoreController::failed, this, &Window::gameFailed); connect(m_controller.get(), &CoreController::unimplementedBiosCall, this, &Window::unimplementedBiosCall); +#ifdef USE_GDB_STUB if (m_gdbController) { m_gdbController->setController(m_controller); } +#endif +#ifdef USE_DEBUGGERS if (m_console) { m_console->setController(m_controller); } +#endif #ifdef USE_MAGICK if (m_gifView) {

@@ -1869,11 +1882,15 @@ m_controller->start();

} WindowBackground::WindowBackground(QWidget* parent) - : QLabel(parent) + : QWidget(parent) { setLayout(new QStackedLayout()); layout()->setContentsMargins(0, 0, 0, 0); - setAlignment(Qt::AlignCenter); +} + +void WindowBackground::setPixmap(const QPixmap& pmap) { + m_pixmap = pmap; + update(); } void WindowBackground::setSizeHint(const QSize& hint) {

@@ -1904,11 +1921,9 @@ m_centered = false;

m_lockAspectRatio = lock; } -void WindowBackground::paintEvent(QPaintEvent*) { - const QPixmap* logo = pixmap(); - if (!logo) { - return; - } +void WindowBackground::paintEvent(QPaintEvent* event) { + QWidget::paintEvent(event); + const QPixmap& logo = pixmap(); QPainter painter(this); painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.fillRect(QRect(QPoint(), size()), Qt::black);

@@ -1933,5 +1948,5 @@ ds.setHeight(ds.height() - ds.height() % m_aspectHeight);

} QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2); QRect full(origin, ds); - painter.drawPixmap(full, *logo); + painter.drawPixmap(full, logo); }
M src/platform/qt/Window.hsrc/platform/qt/Window.h

@@ -133,6 +133,8 @@ void recordFrame();

void showFPS(); void focusCheck(); + void updateFrame(); + private: static const int FPS_TIMER_INTERVAL = 2000; static const int FRAME_LIST_SIZE = 120;

@@ -218,12 +220,13 @@ LibraryController* m_libraryView;

#endif }; -class WindowBackground : public QLabel { +class WindowBackground : public QWidget { Q_OBJECT public: WindowBackground(QWidget* parent = 0); + void setPixmap(const QPixmap& pixmap); void setSizeHint(const QSize& size); virtual QSize sizeHint() const override; void setDimensions(int width, int height);

@@ -231,10 +234,13 @@ void setCenteredAspectRatio(int width, int height);

void setLockIntegerScaling(bool lock); void setLockAspectRatio(bool lock); + const QPixmap& pixmap() const { return m_pixmap; } + protected: virtual void paintEvent(QPaintEvent*) override; private: + QPixmap m_pixmap; QSize m_sizeHint; bool m_centered; int m_aspectWidth;