all repos — mgba @ a6dcfcc338ce99f8839860d5ecb069b927370062

mGBA Game Boy Advance Emulator

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

a6dcfcc338ce99f8839860d5ecb069b927370062

parent

3304a448ede6b4699d78c6816e65382c05f78e5e

M .travis-deps.sh.travis-deps.sh

@@ -2,19 +2,4 @@ #!/bin/sh

if [ $TRAVIS_OS_NAME = "osx" ]; then brew update brew install qt5 ffmpeg imagemagick sdl2 libedit libelf libpng libzip -else - sudo apt-get clean - sudo add-apt-repository -y ppa:beineri/opt-qt542-trusty - sudo add-apt-repository -y ppa:george-edison55/cmake-3.x - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - sudo apt-get update - sudo apt-get install -y -q cmake libedit-dev libelf-dev libmagickwand-dev \ - libpng-dev libsdl2-dev libzip-dev qt54base qt54multimedia \ - libavcodec-dev libavutil-dev libavformat-dev libavresample-dev \ - libswscale-dev - if [ "$CC" == "gcc" ]; then - sudo apt-get install -y -q gcc-5 g++-5 - export CC=gcc-5 - export CXX=g++-5 - fi fi
M .travis.yml.travis.yml

@@ -1,14 +1,30 @@

+if: type = pull_request OR NOT branch =~ /^(master$|optimization)/ OR fork language: c sudo: required +services: +- docker +os: linux +env: +- DOCKER_TAG=ubuntu:xenial +- DOCKER_TAG=ubuntu:artful +- DOCKER_TAG=ubuntu:bionic +- DOCKER_TAG=3ds +- DOCKER_TAG=wii +- DOCKER_TAG=vita +- DOCKER_TAG=windows:w32 +- DOCKER_TAG=windows:w64 + matrix: include: - - os: linux - dist: trusty - compiler: gcc - - os: osx - compiler: clang + - os: osx + compiler: clang + env: DOCKER_TAG= before_install: - - source ./.travis-deps.sh +- '[ -z "$DOCKER_TAG" ] || docker pull mgba/$DOCKER_TAG' +- '[ "$TRAVIS_OS_NAME" != "osx" ] || . ./.travis-deps.sh' +- 'mkdir build && chmod 777 build' -script: mkdir build && cd build && cmake -DCMAKE_PREFIX_PATH='/usr/local/opt/qt5;/opt/qt54' .. && make -j2 +script: +- '[ -z "$DOCKER_TAG" ] || docker run -e BUILD_DIR=build -e MAKEFLAGS=-j2 -v $PWD:/home/mgba/src mgba/$DOCKER_TAG' +- '[ "$TRAVIS_OS_NAME" != "osx" ] || (cd build && cmake -DCMAKE_PREFIX_PATH="/usr/local/opt/qt5" .. && make -j2)'
M CHANGESCHANGES

@@ -86,6 +86,8 @@ - Qt: Add load alternate save option

- GB Audio: Improved audio quality - GB, GBA Audio: Increase max audio volume - GB: Fix VRAM/palette locking (fixes mgba.io/i/1109) + - GB Video: Darken colors in GBA mode + - FFmpeg: Support libswresample (fixes mgba.io/i/1120, mgba.io/b/123) 0.6.3: (2017-04-14) Bugfixes:
M CMakeLists.txtCMakeLists.txt

@@ -443,7 +443,7 @@ set(WANT_LIBZIP ${USE_LIBZIP})

set(WANT_SQLITE3 ${USE_SQLITE3}) set(USE_CMOCKA ${BUILD_SUITE}) -find_feature(USE_FFMPEG "libavcodec;libavformat;libavresample;libavutil;libswscale") +find_feature(USE_FFMPEG "libavcodec;libavformat;libavutil;libswscale") find_feature(USE_ZLIB "ZLIB") find_feature(USE_MINIZIP "minizip") find_feature(USE_PNG "PNG")

@@ -454,6 +454,13 @@ find_feature(USE_CMOCKA "cmocka")

find_feature(USE_SQLITE3 "sqlite3") find_feature(USE_ELF "libelf") find_feature(ENABLE_PYTHON "PythonLibs") + +if(USE_FFMPEG) + set(USE_LIBAVRESAMPLE ON) + set(USE_LIBSWRESAMPLE ON) + find_feature(USE_LIBAVRESAMPLE "libavresample") + find_feature(USE_LIBSWRESAMPLE "libswresample") +endif() # Features set(DEBUGGER_SRC

@@ -503,22 +510,30 @@ source_group("Debugger" FILES ${DEBUGGER_SRC})

if(USE_FFMPEG) list(APPEND FEATURES FFMPEG) - pkg_search_module(LIBSWRESAMPLE QUIET libswresample) - if(NOT LIBSWRESAMPLE_FOUND) + if(USE_LIBSWRESAMPLE) + list(APPEND FEATURES LIBSWRESAMPLE) + else() + list(APPEND FEATURES LIBAVRESAMPLE) list(APPEND FEATURES LIBAV) endif() - include_directories(AFTER ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS}) - link_directories(${LIBAVCODEC_LIBRARY_DIRS} ${LIBAVFORMAT_LIBRARY_DIRS} ${LIBAVRESAMPLE_LIBRARY_DIRS} ${LIBAVUTIL_LIBRARY_DIRS} ${LIBSWSCALE_LIBRARY_DIRS}) + include_directories(AFTER ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS} ${LIBSWRESAMPLE_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS}) + link_directories(${LIBAVCODEC_LIBRARY_DIRS} ${LIBAVFORMAT_LIBRARY_DIRS} ${LIBAVRESAMPLE_LIBRARY_DIRS} ${LIBAVUTIL_LIBRARY_DIRS} ${LIBSWRESAMPLE_LIBRARY_DIRS} ${LIBSWSCALE_LIBRARY_DIRS}) list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-encoder.c") string(REGEX MATCH "^[0-9]+" LIBAVCODEC_VERSION_MAJOR ${libavcodec_VERSION}) string(REGEX MATCH "^[0-9]+" LIBAVFORMAT_VERSION_MAJOR ${libavformat_VERSION}) string(REGEX MATCH "^[0-9]+" LIBAVRESAMPLE_VERSION_MAJOR ${libavresample_VERSION}) string(REGEX MATCH "^[0-9]+" LIBAVUTIL_VERSION_MAJOR ${libavutil_VERSION}) + string(REGEX MATCH "^[0-9]+" LIBSWRESAMPLE_VERSION_MAJOR ${libswresample_VERSION}) string(REGEX MATCH "^[0-9]+" LIBSWSCALE_VERSION_MAJOR ${libswscale_VERSION}) - list(APPEND DEPENDENCY_LIB ${LIBAVCODEC_LIBRARIES} ${LIBAVFORMAT_LIBRARIES} ${LIBAVRESAMPLE_LIBRARIES} ${LIBAVUTIL_LIBRARIES} ${LIBSWSCALE_LIBRARIES}) + math(EXPR LIBSWRESAMPLE_VERSION_DEBIAN "${LIBSWRESAMPLE_VERSION_MAJOR} - 1") + list(APPEND DEPENDENCY_LIB ${LIBAVCODEC_LIBRARIES} ${LIBAVFORMAT_LIBRARIES} ${LIBAVRESAMPLE_LIBRARIES} ${LIBAVUTIL_LIBRARIES} ${LIBSWSCALE_LIBRARIES} ${LIBSWRESAMPLE_LIBRARIES}) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavcodec${LIBAVCODEC_VERSION_MAJOR}|libavcodec-extra-${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}") set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavformat${LIBAVFORMAT_VERSION_MAJOR}|libavformat-ffmpeg${LIBAVFORMAT_VERSION_MAJOR}") - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavresample${LIBAVRESAMPLE_VERSION_MAJOR}|libavresample-ffmpeg${LIBAVRESAMPLE_VERSION_MAJOR}") + if(USE_LIBSWRESAMPLE) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswresample${LIBSWRESAMPLE_VERSION_DEBIAN}|libswresample-ffmpeg${LIBSWRESAMPLE_VERSION_DEBIAN}") + else() + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavresample${LIBAVRESAMPLE_VERSION_MAJOR}|libavresample-ffmpeg${LIBAVRESAMPLE_VERSION_MAJOR}") + endif() set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavutil${LIBAVUTIL_VERSION_MAJOR}|libavutil-ffmpeg${LIBAVUTIL_VERSION_MAJOR}") set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswscale${LIBSWSCALE_VERSION_MAJOR}|libswscale-ffmpeg${LIBSWSCALE_VERSION_MAJOR}") set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libavcodec-extra|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}")
M src/feature/ffmpeg/ffmpeg-encoder.csrc/feature/ffmpeg/ffmpeg-encoder.c

@@ -19,7 +19,11 @@ #include <libavutil/imgutils.h>

#include <libavutil/mathematics.h> #include <libavutil/opt.h> +#ifdef USE_LIBAVRESAMPLE #include <libavresample/avresample.h> +#else +#include <libswresample/swresample.h> +#endif #include <libswscale/swscale.h> static void _ffmpegPostVideoFrame(struct mAVStream*, const color_t* pixels, size_t stride);

@@ -254,6 +258,7 @@ }

encoder->audioFrame->nb_samples = encoder->audio->frame_size; encoder->audioFrame->format = encoder->audio->sample_fmt; encoder->audioFrame->pts = 0; +#ifdef USE_LIBAVRESAMPLE encoder->resampleContext = avresample_alloc_context(); av_opt_set_int(encoder->resampleContext, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(encoder->resampleContext, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);

@@ -262,6 +267,11 @@ av_opt_set_int(encoder->resampleContext, "out_sample_rate", encoder->sampleRate, 0);

av_opt_set_int(encoder->resampleContext, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int(encoder->resampleContext, "out_sample_fmt", encoder->sampleFormat, 0); avresample_open(encoder->resampleContext); +#else + encoder->resampleContext = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, encoder->sampleFormat, encoder->sampleRate, + AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, PREFERRED_SAMPLE_RATE, 0, NULL); + swr_init(encoder->resampleContext); +#endif encoder->audioBufferSize = (encoder->audioFrame->nb_samples * PREFERRED_SAMPLE_RATE / encoder->sampleRate) * 4; encoder->audioBuffer = av_malloc(encoder->audioBufferSize); encoder->postaudioBufferSize = av_samples_get_buffer_size(0, encoder->audio->channels, encoder->audio->frame_size, encoder->audio->sample_fmt, 0);

@@ -370,7 +380,11 @@ avcodec_close(encoder->audio);

encoder->audio = NULL; if (encoder->resampleContext) { +#ifdef USE_LIBAVRESAMPLE avresample_close(encoder->resampleContext); +#else + swr_free(&encoder->resampleContext); +#endif } if (encoder->absf) {

@@ -423,10 +437,11 @@ return;

} int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt); + encoder->currentAudioSample = 0; +#ifdef USE_LIBAVRESAMPLE avresample_convert(encoder->resampleContext, 0, 0, 0, (uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4); - encoder->currentAudioSample = 0; if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) { return; }

@@ -434,6 +449,17 @@ #if LIBAVCODEC_VERSION_MAJOR >= 55

av_frame_make_writable(encoder->audioFrame); #endif int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize); +#else +#if LIBAVCODEC_VERSION_MAJOR >= 55 + av_frame_make_writable(encoder->audioFrame); +#endif + if (swr_get_out_samples(encoder->resampleContext, encoder->audioBufferSize / 4) < encoder->audioFrame->nb_samples) { + swr_convert(encoder->resampleContext, NULL, 0, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4); + return; + } + int samples = swr_convert(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize, + (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4); +#endif encoder->audioFrame->pts = av_rescale_q(encoder->currentAudioFrame, encoder->audio->time_base, encoder->audioStream->time_base); encoder->currentAudioFrame += samples;
M src/feature/ffmpeg/ffmpeg-encoder.hsrc/feature/ffmpeg/ffmpeg-encoder.h

@@ -57,7 +57,11 @@ AVFrame* audioFrame;

size_t currentAudioSample; int64_t currentAudioFrame; int64_t nextAudioPts; // TODO (0.6): Remove +#ifdef USE_LIBAVRESAMPLE struct AVAudioResampleContext* resampleContext; +#else + struct SwrContext* resampleContext; +#endif #ifdef FFMPEG_USE_NEW_BSF struct AVBSFContext* absf; // Needed for AAC in MP4 #else
M src/feature/video-logger.csrc/feature/video-logger.c

@@ -682,6 +682,18 @@ }

if (context->initialState) { mappedMemoryFree(context->initialState, context->initialStateSize); } + + size_t i; + for (i = 0; i < context->nChannels; ++i) { + CircleBufferDeinit(&context->channels[i].buffer); +#ifdef USE_ZLIB + if (context->channels[i].inflating) { + inflateEnd(&context->channels[i].inflateStream); + context->channels[i].inflating = false; + } +#endif + } + free(context); }
M src/gb/renderers/software.csrc/gb/renderers/software.c

@@ -437,10 +437,29 @@ } else if (index >= 0x40 && !(index & 0xF)) {

color = softwareRenderer->palette[0]; } } - softwareRenderer->palette[index] = color; if (renderer->cache) { mCacheSetWritePalette(renderer->cache, index, color); } + if (softwareRenderer->model == GB_MODEL_AGB) { + unsigned r = M_R5(value); + unsigned g = M_G5(value); + unsigned b = M_B5(value); + r = r * r; + g = g * g; + b = b * b; +#ifdef COLOR_16_BIT + r /= 31; + g /= 31; + b /= 31; + color = mColorFrom555(r | (g << 5) | (b << 10)); +#else + r >>= 2; + g >>= 2; + b >>= 2; + color = r | (g << 8) | (b << 16); +#endif + } + softwareRenderer->palette[index] = color; if (softwareRenderer->model == GB_MODEL_SGB && !index && GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) { renderer->writePalette(renderer, 0x04, value);
M src/gba/bios.csrc/gba/bios.c

@@ -251,7 +251,7 @@ gba->memory.activeRegion = REGION_BIOS;

uint32_t key = cpu->memory.load32(cpu, cpu->gprs[0] + 4, 0); gba->memory.activeRegion = oldRegion; - cpu->gprs[0] = key / powf(2, (180.f - cpu->gprs[1] - cpu->gprs[2] / 256.f) / 12.f); + cpu->gprs[0] = key / exp2f((180.f - cpu->gprs[1] - cpu->gprs[2] / 256.f) / 12.f); } static void _Div(struct GBA* gba, int32_t num, int32_t denom) {
M src/gba/gba.csrc/gba/gba.c

@@ -398,6 +398,7 @@ memcpy(newRom, gba->memory.rom, gba->pristineRomSize);

gba->memory.rom = newRom; #endif gba->memory.romSize = SIZE_CART0; + gba->memory.romMask = SIZE_CART0 - 1; gba->isPristine = false; } if (gba->cpu && gba->memory.activeRegion >= REGION_CART0) {
M src/platform/qt/DisplayGL.cppsrc/platform/qt/DisplayGL.cpp

@@ -29,8 +29,11 @@ using namespace QGBA;

DisplayGL::DisplayGL(const QGLFormat& format, QWidget* parent) : Display(parent) - , m_gl(new EmptyGLWidget(format, this)) + , m_gl(nullptr) { + // This can spontaneously re-enter into this->resizeEvent before creation is done, so we + // need to make sure it's initialized to nullptr before we assign the new object to it + m_gl = new EmptyGLWidget(format, this); m_painter = new PainterGL(format.majorVersion() < 2 ? 1 : m_gl->format().majorVersion(), m_gl); m_gl->setMouseTracking(true); m_gl->setAttribute(Qt::WA_TransparentForMouseEvents); // This doesn't seem to work?

@@ -166,7 +169,9 @@ resizePainter();

} void DisplayGL::resizePainter() { - m_gl->resize(size()); + if (m_gl) { + m_gl->resize(size()); + } if (m_drawThread) { QMetaObject::invokeMethod(m_painter, "resize", Qt::BlockingQueuedConnection, Q_ARG(QSize, size())); }

@@ -184,7 +189,7 @@ #endif

#if !defined(_WIN32) || defined(USE_EPOXY) if (majorVersion >= 2) { - gl2Backend = new mGLES2Context; + gl2Backend = static_cast<mGLES2Context*>(malloc(sizeof(mGLES2Context))); mGLES2ContextCreate(gl2Backend); m_backend = &gl2Backend->d; m_supportsShaders = true;

@@ -193,7 +198,7 @@ #endif

#ifdef BUILD_GL if (!m_backend) { - glBackend = new mGLContext; + glBackend = static_cast<mGLContext*>(malloc(sizeof(mGLContext))); mGLContextCreate(glBackend); m_backend = &glBackend->d; m_supportsShaders = false;

@@ -243,7 +248,7 @@ }

#endif m_backend->deinit(m_backend); m_gl->doneCurrent(); - delete m_backend; + free(m_backend); m_backend = nullptr; }
M src/platform/qt/LogController.cppsrc/platform/qt/LogController.cpp

@@ -25,6 +25,10 @@ connect(this, &LogController::levelsDisabled, &s_global, &LogController::disableLevels);

} } +LogController::~LogController() { + mLogFilterDeinit(&m_filter); +} + LogController::Stream LogController::operator()(int category, int level) { return Stream(this, category, level); }
M src/platform/qt/LogController.hsrc/platform/qt/LogController.h

@@ -35,6 +35,7 @@ };

public: LogController(int levels, QObject* parent = nullptr); + ~LogController(); int levels() const { return m_filter.defaultLevels; } mLogFilter* filter() { return &m_filter; }
M src/platform/qt/library/LibraryController.cppsrc/platform/qt/library/LibraryController.cpp

@@ -45,10 +45,10 @@ }

mLibraryAttachGameDB(m_library.get(), GBAApp::app()->gameDB()); - m_libraryTree = new LibraryTree(this); + m_libraryTree = std::make_unique<LibraryTree>(this); addWidget(m_libraryTree->widget()); - m_libraryGrid = new LibraryGrid(this); + m_libraryGrid = std::make_unique<LibraryGrid>(this); addWidget(m_libraryGrid->widget()); setViewStyle(LibraryStyle::STYLE_LIST);

@@ -67,9 +67,9 @@ m_currentStyle = newStyle;

AbstractGameList* newCurrentList = nullptr; if (newStyle == LibraryStyle::STYLE_LIST || newStyle == LibraryStyle::STYLE_TREE) { - newCurrentList = m_libraryTree; + newCurrentList = m_libraryTree.get(); } else { - newCurrentList = m_libraryGrid; + newCurrentList = m_libraryGrid.get(); } newCurrentList->selectEntry(selectedEntry()); newCurrentList->setViewStyle(newStyle);
M src/platform/qt/library/LibraryController.hsrc/platform/qt/library/LibraryController.h

@@ -107,8 +107,8 @@

LibraryStyle m_currentStyle; AbstractGameList* m_currentList = nullptr; - LibraryGrid* m_libraryGrid = nullptr; - LibraryTree* m_libraryTree = nullptr; + std::unique_ptr<LibraryGrid> m_libraryGrid; + std::unique_ptr<LibraryTree> m_libraryTree; }; }
M src/platform/qt/library/LibraryTree.cppsrc/platform/qt/library/LibraryTree.cpp

@@ -62,6 +62,12 @@ }

}); } +LibraryTree::~LibraryTree() { + for (QTreeWidgetItem* i : m_items.values()) { + delete i; + } +} + void LibraryTree::resizeAllCols() { for (int i = 0; i < m_widget->columnCount(); i++) { m_widget->resizeColumnToContents(i);