diff --git a/.travis-deps.sh b/.travis-deps.sh index b249cefee..64e45cc98 100755 --- a/.travis-deps.sh +++ b/.travis-deps.sh @@ -1,16 +1,17 @@ #!/bin/sh if [ $TRAVIS_OS_NAME = "osx" ]; then brew update - brew install qt5 ffmpeg imagemagick sdl2 libzip libpng + 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 libmagickwand-dev \ - libpng-dev libsdl2-dev libzip-dev qtbase5-dev \ - libqt5opengl5-dev qtmultimedia5-dev libavcodec-dev \ - libavutil-dev libavformat-dev libavresample-dev libswscale-dev + 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 diff --git a/.travis.yml b/.travis.yml index 3f3e6077c..17bcaca87 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,4 +11,4 @@ matrix: before_install: - source ./.travis-deps.sh -script: mkdir build && cd build && cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 .. && make -j2 +script: mkdir build && cd build && cmake -DCMAKE_PREFIX_PATH='/usr/local/opt/qt5;/opt/qt54' .. && make -j2 diff --git a/CHANGES b/CHANGES index d1bcbec94..9643e60e9 100644 --- a/CHANGES +++ b/CHANGES @@ -59,6 +59,8 @@ Bugfixes: - GBA Serialize: Fix loading channel 3 volume (fixes mgba.io/i/1107) - GBA SIO: Fix unconnected SIOCNT for multi mode (fixes mgba.io/i/1105) - GBA BIOS: Fix BitUnPack final byte + - GB I/O: DMA register is R/W + - GB Video: Fix SCX timing Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dc9de01b..b6ddf8d04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -316,11 +316,13 @@ if(DEFINED 3DS) endif() include(CheckFunctionExists) +include(CheckIncludeFiles) check_function_exists(strdup HAVE_STRDUP) check_function_exists(strndup HAVE_STRNDUP) if(NOT DEFINED PSP2) check_function_exists(localtime_r HAVE_LOCALTIME_R) endif() +check_include_files("xlocale.h" HAVE_XLOCALE) if(NOT CMAKE_SYSTEM_NAME STREQUAL "Generic") check_function_exists(snprintf_l HAVE_SNPRINTF_L) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") @@ -378,9 +380,6 @@ endif() if(HAVE_NEWLOCALE AND HAVE_FREELOCALE AND HAVE_USELOCALE OR APPLE) list(APPEND FUNCTION_DEFINES HAVE_LOCALE) - if (HAVE_STRTOF_L) - list(APPEND FUNCTION_DEFINES HAVE_STRTOF_L) - endif() if (HAVE_SNPRINTF_L) list(APPEND FUNCTION_DEFINES HAVE_SNPRINTF_L) endif() @@ -390,6 +389,14 @@ if(HAVE_SETLOCALE) list(APPEND FUNCTION_DEFINES HAVE_SETLOCALE) endif() +if (HAVE_STRTOF_L) + list(APPEND FUNCTION_DEFINES HAVE_STRTOF_L) +endif() + +if(HAVE_XLOCALE) + list(APPEND FUNCTION_DEFINES HAVE_XLOCALE) +endif() + if(HAVE_CHMOD) list(APPEND FUNCTION_DEFINES HAVE_CHMOD) endif() diff --git a/include/mgba-util/formatting.h b/include/mgba-util/formatting.h index 4395879aa..6eb01ffaf 100644 --- a/include/mgba-util/formatting.h +++ b/include/mgba-util/formatting.h @@ -12,8 +12,8 @@ CXX_GUARD_START #include "locale.h" -#if defined(__APPLE__) || defined(__FreeBSD__) -#include "xlocale.h" +#ifdef HAVE_XLOCALE +#include #elif !defined(HAVE_LOCALE) typedef const char* locale_t; #endif diff --git a/include/mgba/internal/gb/video.h b/include/mgba/internal/gb/video.h index ec7409af9..3f33e9383 100644 --- a/include/mgba/internal/gb/video.h +++ b/include/mgba/internal/gb/video.h @@ -128,7 +128,7 @@ struct GBVideo { struct mTimingEvent modeEvent; struct mTimingEvent frameEvent; - uint32_t dotClock; + int32_t dotClock; uint8_t* vram; uint8_t* vramBank; diff --git a/src/core/thread.c b/src/core/thread.c index 7584f711f..69183d072 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -269,6 +269,9 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { } core->clearCoreCallbacks(core); + if (threadContext->logger.d.filter == &filter) { + mLogFilterDeinit(&filter); + } threadContext->logger.d.filter = NULL; return 0; diff --git a/src/gb/audio.c b/src/gb/audio.c index 4b098230c..a84aad3a8 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -143,22 +143,13 @@ void GBAudioReset(struct GBAudio* audio) { audio->capLeft = 0; audio->capRight = 0; audio->clock = 0; - audio->volumeRight = 0; - audio->volumeLeft = 0; - audio->ch1Right = false; - audio->ch2Right = false; - audio->ch3Right = false; - audio->ch4Right = false; - audio->ch1Left = false; - audio->ch2Left = false; - audio->ch3Left = false; - audio->ch4Left = false; audio->playingCh1 = false; audio->playingCh2 = false; audio->playingCh3 = false; audio->playingCh4 = false; - if (audio->p && (audio->p->model == GB_MODEL_DMG || audio->p->model == GB_MODEL_CGB)) { + if (audio->p && audio->p->model != GB_MODEL_SGB) { audio->playingCh1 = true; + audio->enable = true; *audio->nr52 |= 0x01; } } diff --git a/src/gb/gb.c b/src/gb/gb.c index d308dc977..cce40b5ce 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -547,6 +547,8 @@ void GBSkipBIOS(struct GB* gb) { mTimingDeschedule(&gb->timing, &gb->timer.event); mTimingSchedule(&gb->timing, &gb->timer.event, 0); + GBIOWrite(gb, REG_LCDC, 0x91); + if (gb->biosVf) { GBUnmapBIOS(gb); } diff --git a/src/gb/io.c b/src/gb/io.c index 75a292235..d24576333 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -182,10 +182,15 @@ void GBIOReset(struct GB* gb) { GBIOWrite(gb, REG_NR43, 0x00); GBIOWrite(gb, REG_NR50, 0x77); GBIOWrite(gb, REG_NR51, 0xF3); - GBIOWrite(gb, REG_LCDC, 0x91); + if (!gb->biosVf) { + GBIOWrite(gb, REG_LCDC, 0x91); + } else { + GBIOWrite(gb, REG_LCDC, 0x00); + } GBIOWrite(gb, REG_SCY, 0x00); GBIOWrite(gb, REG_SCX, 0x00); GBIOWrite(gb, REG_LYC, 0x00); + GBIOWrite(gb, REG_DMA, 0xFF); GBIOWrite(gb, REG_BGP, 0xFC); if (gb->model < GB_MODEL_CGB) { GBIOWrite(gb, REG_OBP0, 0xFF); @@ -614,6 +619,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) { case REG_SCX: case REG_LY: case REG_LYC: + case REG_DMA: case REG_BGP: case REG_OBP0: case REG_OBP1: @@ -638,9 +644,6 @@ uint8_t GBIORead(struct GB* gb, unsigned address) { case REG_SVBK: // Handled transparently by the registers goto success; - case REG_DMA: - mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address); - return 0; default: break; } diff --git a/src/gb/video.c b/src/gb/video.c index 26c1f25da..958088b3f 100644 --- a/src/gb/video.c +++ b/src/gb/video.c @@ -224,8 +224,7 @@ void _endMode0(struct mTiming* timing, void* context, uint32_t cyclesLate) { GBRegisterSTAT oldStat = video->stat; video->stat = GBRegisterSTATSetLYC(video->stat, lyc == video->ly); if (video->ly < GB_VIDEO_VERTICAL_PIXELS) { - // TODO: Cache SCX & 7 in case it changes during mode 2 - next = GB_VIDEO_MODE_2_LENGTH + (video->p->memory.io[REG_SCX] & 7); + next = GB_VIDEO_MODE_2_LENGTH; video->mode = 2; video->modeEvent.callback = _endMode2; } else { @@ -262,7 +261,7 @@ void _endMode1(struct mTiming* timing, void* context, uint32_t cyclesLate) { if (video->ly == GB_VIDEO_VERTICAL_TOTAL_PIXELS + 1) { video->ly = 0; video->p->memory.io[REG_LY] = video->ly; - next = GB_VIDEO_MODE_2_LENGTH + (video->p->memory.io[REG_SCX] & 7); + next = GB_VIDEO_MODE_2_LENGTH; video->mode = 2; video->modeEvent.callback = _endMode2; } else if (video->ly == GB_VIDEO_VERTICAL_TOTAL_PIXELS) { @@ -290,9 +289,9 @@ void _endMode1(struct mTiming* timing, void* context, uint32_t cyclesLate) { void _endMode2(struct mTiming* timing, void* context, uint32_t cyclesLate) { struct GBVideo* video = context; _cleanOAM(video, video->ly); - video->x = 0; - video->dotClock = mTimingCurrentTime(timing) - cyclesLate; - int32_t next = GB_VIDEO_MODE_3_LENGTH_BASE + video->objMax * 6 - (video->p->memory.io[REG_SCX] & 7); + video->x = -(video->p->memory.io[REG_SCX] & 7); + video->dotClock = mTimingCurrentTime(timing) - cyclesLate + 5 - (video->x << video->p->doubleSpeed); + int32_t next = GB_VIDEO_MODE_3_LENGTH_BASE + video->objMax * 6 - video->x; video->mode = 3; video->modeEvent.callback = _endMode3; GBRegisterSTAT oldStat = video->stat; @@ -323,7 +322,8 @@ void _endMode3(struct mTiming* timing, void* context, uint32_t cyclesLate) { GBUpdateIRQs(video->p); } video->p->memory.io[REG_STAT] = video->stat; - int32_t next = GB_VIDEO_MODE_0_LENGTH_BASE - video->objMax * 6; + // TODO: Cache SCX & 7 in case it changes + int32_t next = GB_VIDEO_MODE_0_LENGTH_BASE - video->objMax * 6 - (video->p->memory.io[REG_SCX] & 7); mTimingSchedule(timing, &video->modeEvent, (next << video->p->doubleSpeed) - cyclesLate); } @@ -402,12 +402,14 @@ void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate) { return; } int oldX = video->x; - video->x = (mTimingCurrentTime(&video->p->timing) - video->dotClock - cyclesLate) >> video->p->doubleSpeed; + video->x = (int32_t) (mTimingCurrentTime(&video->p->timing) - cyclesLate - video->dotClock) >> video->p->doubleSpeed; if (video->x > GB_VIDEO_HORIZONTAL_PIXELS) { video->x = GB_VIDEO_HORIZONTAL_PIXELS; } else if (video->x < 0) { - mLOG(GB, FATAL, "Video dot clock went negative!"); - video->x = oldX; + return; + } + if (oldX < 0) { + oldX = 0; } if (video->frameskipCounter <= 0) { video->renderer->drawRange(video->renderer, oldX, video->x, video->ly, video->objThisLine, video->objMax); @@ -419,6 +421,7 @@ void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) { video->mode = 2; video->modeEvent.callback = _endMode2; int32_t next = GB_VIDEO_MODE_2_LENGTH - 5; // TODO: Why is this fudge factor needed? Might be related to T-cycles for load/store differing + mTimingDeschedule(&video->p->timing, &video->modeEvent); mTimingSchedule(&video->p->timing, &video->modeEvent, next << video->p->doubleSpeed); video->ly = 0; @@ -445,6 +448,7 @@ void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) { video->renderer->writePalette(video->renderer, 0, video->dmgPalette[0]); mTimingDeschedule(&video->p->timing, &video->modeEvent); + mTimingDeschedule(&video->p->timing, &video->frameEvent); mTimingSchedule(&video->p->timing, &video->frameEvent, GB_VIDEO_TOTAL_LENGTH); } video->p->memory.io[REG_STAT] = video->stat; diff --git a/src/gba/cheats/parv3.c b/src/gba/cheats/parv3.c index a49333568..0d74aaed4 100644 --- a/src/gba/cheats/parv3.c +++ b/src/gba/cheats/parv3.c @@ -155,6 +155,7 @@ static bool _addPAR3Special(struct GBACheatSet* cheats, uint32_t op2) { cheat = mCheatListAppend(&cheats->d.list); cheat->type = CHEAT_ASSIGN; cheat->width = 1; + cheat->repeat = 1; cheat->address = _parAddr(op2); cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); break; @@ -166,6 +167,7 @@ static bool _addPAR3Special(struct GBACheatSet* cheats, uint32_t op2) { cheat = mCheatListAppend(&cheats->d.list); cheat->type = CHEAT_ASSIGN; cheat->width = 2; + cheat->repeat = 1; cheat->address = _parAddr(op2); cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); break; @@ -177,6 +179,7 @@ static bool _addPAR3Special(struct GBACheatSet* cheats, uint32_t op2) { cheat = mCheatListAppend(&cheats->d.list); cheat->type = CHEAT_ASSIGN; cheat->width = 4; + cheat->repeat = 1; cheat->address = _parAddr(op2); cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); break; diff --git a/src/platform/python/CMakeLists.txt b/src/platform/python/CMakeLists.txt index a5b568813..d743e9924 100644 --- a/src/platform/python/CMakeLists.txt +++ b/src/platform/python/CMakeLists.txt @@ -5,8 +5,10 @@ include_directories(AFTER ${PYTHON_INCLUDE_DIRS}) get_property(INCLUDE_DIRECTORIES DIRECTORY PROPERTY INCLUDE_DIRECTORIES) set(INCLUDE_FLAGS) +set(INCLUDE_FLAGS_STR "") foreach(DIR IN LISTS INCLUDE_DIRECTORIES) - list(APPEND INCLUDE_FLAGS "-I${DIR}") + list(APPEND INCLUDE_FLAGS "-I${DIR}") + set(INCLUDE_FLAGS_STR "${INCLUDE_FLAGS_STR} \"-I${DIR}\"") endforeach() file(GLOB PYTHON_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) @@ -64,5 +66,5 @@ foreach(TEST IN LISTS BASE_TESTS SUBTESTS) add_test(NAME python-${TEST_NAME} COMMAND ${PYTHON_EXECUTABLE} setup.py build -b ${CMAKE_CURRENT_BINARY_DIR} pytest --extras --addopts ${TEST} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - set_tests_properties(python-${TEST_NAME} PROPERTIES ENVIRONMENT "${PATH}=${CMAKE_CURRENT_BINARY_DIR}/..;BINDIR=${CMAKE_CURRENT_BINARY_DIR}/..;LIBDIR=${CMAKE_CURRENT_BINARY_DIR}/..;CPPFLAGS=${INCLUDE_FLAGS}") + set_tests_properties(python-${TEST_NAME} PROPERTIES ENVIRONMENT "${PATH}=${CMAKE_CURRENT_BINARY_DIR}/..;BINDIR=${CMAKE_CURRENT_BINARY_DIR}/..;LIBDIR=${CMAKE_CURRENT_BINARY_DIR}/..;CPPFLAGS=${INCLUDE_FLAGS_STR}") endforeach() diff --git a/src/platform/python/_builder.py b/src/platform/python/_builder.py index b7f1a3dbc..101d30cca 100644 --- a/src/platform/python/_builder.py +++ b/src/platform/python/_builder.py @@ -13,8 +13,6 @@ libdir = os.environ.get("LIBDIR") cpp = shlex.split(os.environ.get("CPP", "cc -E")) cppflags = shlex.split(os.environ.get("CPPFLAGS", "")) -if __name__ == "__main__": - cppflags.extend(sys.argv[1:]) cppflags.extend(["-I" + incdir, "-I" + srcdir, "-I" + bindir]) ffi.set_source("mgba._pylib", """ diff --git a/src/platform/python/conftest.py b/src/platform/python/conftest.py index 6690268a1..06826a741 100644 --- a/src/platform/python/conftest.py +++ b/src/platform/python/conftest.py @@ -23,7 +23,7 @@ def pytest_exception_interact(node, call, report): if outroot: if not vtest: return - outdir = os.path.join(outroot, *vtest.fullPath) + outdir = os.path.join(outroot, *vtest.full_path) try: os.makedirs(outdir) except OSError as e: diff --git a/src/platform/python/setup.py.in b/src/platform/python/setup.py.in deleted file mode 100644 index 3546cb876..000000000 --- a/src/platform/python/setup.py.in +++ /dev/null @@ -1,35 +0,0 @@ -from setuptools import setup -import re -import os -import sys - -os.environ["BINDIR"] = "${CMAKE_BINARY_DIR}" -os.environ["LIBDIR"] = "${CMAKE_INSTALL_PREFIX}/${LIBDIR}" -os.environ["CPPFLAGS"] = " ".join([d for d in "${INCLUDE_FLAGS}".split(";") if d]) - -classifiers = [ - "Programming Language :: C", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 3", - "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", - "Topic :: Games/Entertainment", - "Topic :: System :: Emulators" -] - -setup(name="${BINARY_NAME}", - version="${LIB_VERSION_STRING}", - author="Jeffrey Pfau", - author_email="jeffrey@endrift.com", - url="http://github.com/mgba-emu/mgba/", - packages=["mgba"], - package_dir={ - "mgba": "${CMAKE_CURRENT_SOURCE_DIR}/mgba" - }, - setup_requires=['cffi>=1.6', 'pytest-runner'], - install_requires=['cffi>=1.6', 'cached-property'], - extras_require={'pil': ['Pillow>=2.3'], 'cinema': ['pyyaml', 'pytest']}, - tests_require=['pytest'], - cffi_modules=["${CMAKE_CURRENT_SOURCE_DIR}/_builder.py:ffi"], - license="MPL 2.0", - classifiers=classifiers - )