all repos — mgba @ e94744d8c761139a6246ae48e9723825c5bd28f7

mGBA Game Boy Advance Emulator

Merge branch 'master' into port/wii
Jeffrey Pfau jeffrey@endrift.com
Thu, 18 Jun 2015 02:06:19 -0700
commit

e94744d8c761139a6246ae48e9723825c5bd28f7

parent

3bb8075fe7be1c6b2759113544ba32b9bd5f3b19

M CHANGESCHANGES

@@ -44,6 +44,8 @@ - GBA Audio: Fix audio pitch changing when adjusting buffer size

- SDL: Fix SDL build when OpenGL is missing - ARM7: Fix timing of multiplies to use N cycles - GBA: Fix calls to endian-independent loadstores + - GBA Video: Fix windows not affecting sprites + - VFS: Fix line-reading to return proper values Misc: - Qt: Handle saving input settings better - Debugger: Free watchpoints in addition to breakpoints

@@ -73,6 +75,7 @@ - SDL: Clean up initialization functions

- All: Threads are now named - Qt: Rename "Fullscreen" to "Toggle fullscreen" - Qt: Don't save window size when entering fullscreen + - Qt: Make the default fullscreen binding for Windows be Alt-Enter 0.2.1: (2015-05-13) Bugfixes:
M src/gba/renderers/video-software.csrc/gba/renderers/video-software.c

@@ -1883,6 +1883,9 @@ bool objwinOnly = false;

if (objwinSlowPath) { objwinDisable = !GBAWindowControlIsObjEnable(renderer->objwin.packed); objwinOnly = !objwinDisable && !GBAWindowControlIsObjEnable(renderer->currentWindow.packed); + if (objwinDisable && !GBAWindowControlIsObjEnable(renderer->currentWindow.packed)) { + return; + } if (objwinDisable) { for (x = renderer->start; x < renderer->end; ++x, ++pixel) {

@@ -1912,6 +1915,8 @@ }

} return; } + } else if (!GBAWindowControlIsObjEnable(renderer->currentWindow.packed)) { + return; } for (x = renderer->start; x < renderer->end; ++x, ++pixel) { uint32_t color = renderer->spriteLayer[x] & ~FLAG_OBJWIN;
M src/gba/supervisor/config.csrc/gba/supervisor/config.c

@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "config.h" #include "util/formatting.h" +#include "util/string.h" #include "util/vfs.h" #include <sys/stat.h>
M src/platform/commandline.csrc/platform/commandline.c

@@ -17,6 +17,7 @@ #include "debugger/gdb-stub.h"

#endif #include "gba/video.h" +#include "util/string.h" #include <fcntl.h> #include <getopt.h>
M src/platform/imagemagick/imagemagick-gif-encoder.csrc/platform/imagemagick/imagemagick-gif-encoder.c

@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "imagemagick-gif-encoder.h" #include "gba/video.h" +#include "util/string.h" static void _magickPostVideoFrame(struct GBAAVStream*, struct GBAVideoRenderer* renderer); static void _magickPostAudioFrame(struct GBAAVStream*, int16_t left, int16_t right);
M src/platform/perf-main.csrc/platform/perf-main.c

@@ -10,6 +10,7 @@ #include "gba/renderers/video-software.h"

#include "gba/serialize.h" #include "platform/commandline.h" +#include "util/string.h" #include "util/vfs.h" #include <errno.h>
A src/platform/posix/threading.h

@@ -0,0 +1,90 @@

+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef POSIX_THREADING_H +#define POSIX_THREADING_H + +#include "util/common.h" + +#include <pthread.h> +#include <sys/time.h> +#ifdef __FreeBSD__ +#include <pthread_np.h> +#endif + +#define THREAD_ENTRY void* +typedef THREAD_ENTRY (*ThreadEntry)(void*); + +typedef pthread_t Thread; +typedef pthread_mutex_t Mutex; +typedef pthread_cond_t Condition; + +static inline int MutexInit(Mutex* mutex) { + return pthread_mutex_init(mutex, 0); +} + +static inline int MutexDeinit(Mutex* mutex) { + return pthread_mutex_destroy(mutex); +} + +static inline int MutexLock(Mutex* mutex) { + return pthread_mutex_lock(mutex); +} + +static inline int MutexUnlock(Mutex* mutex) { + return pthread_mutex_unlock(mutex); +} + +static inline int ConditionInit(Condition* cond) { + return pthread_cond_init(cond, 0); +} + +static inline int ConditionDeinit(Condition* cond) { + return pthread_cond_destroy(cond); +} + +static inline int ConditionWait(Condition* cond, Mutex* mutex) { + return pthread_cond_wait(cond, mutex); +} + +static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) { + struct timespec ts; + struct timeval tv; + + gettimeofday(&tv, 0); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = (tv.tv_usec + timeoutMs * 1000L) * 1000L; + if (ts.tv_nsec >= 1000000000L) { + ts.tv_nsec -= 1000000000L; + ++ts.tv_sec; + } + + return pthread_cond_timedwait(cond, mutex, &ts); +} + +static inline int ConditionWake(Condition* cond) { + return pthread_cond_broadcast(cond); +} + +static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) { + return pthread_create(thread, 0, entry, context); +} + +static inline int ThreadJoin(Thread thread) { + return pthread_join(thread, 0); +} + +static inline int ThreadSetName(const char* name) { +#ifdef __APPLE__ + return pthread_setname_np(name); +#elif defined(__FreeBSD__) + pthread_set_name_np(pthread_self(), name); + return 0; +#else + return pthread_setname_np(pthread_self(), name); +#endif +} + +#endif
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -826,7 +826,13 @@ resizeFrame(VIDEO_HORIZONTAL_PIXELS * i, VIDEO_VERTICAL_PIXELS * i);

}); addControlledAction(frameMenu, setSize, QString("frame%1x").arg(QString::number(i))); } - addControlledAction(frameMenu, frameMenu->addAction(tr("Toggle fullscreen"), this, SLOT(toggleFullScreen()), QKeySequence("Ctrl+F")), "fullscreen"); + QKeySequence fullscreenKeys; +#ifdef Q_OS_WIN + fullscreenKeys = QKeySequence("Alt+Enter"); +#else + fullscreenKeys = QKeySequence("Ctrl+F"); +#endif + addControlledAction(frameMenu, frameMenu->addAction(tr("Toggle fullscreen"), this, SLOT(toggleFullScreen()), fullscreenKeys), "fullscreen"); ConfigOption* lockAspectRatio = m_config->addOption("lockAspectRatio"); lockAspectRatio->addBoolean(tr("Lock aspect ratio"), avMenu);
A src/platform/windows/threading.h

@@ -0,0 +1,84 @@

+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef WINDOWS_THREADING_H +#define WINDOWS_THREADING_H + +#include "util/common.h" + +#define _WIN32_WINNT 0x0600 +#include <windows.h> +#define THREAD_ENTRY DWORD WINAPI +typedef THREAD_ENTRY ThreadEntry(LPVOID); + +typedef HANDLE Thread; +typedef CRITICAL_SECTION Mutex; +typedef CONDITION_VARIABLE Condition; + +static inline int MutexInit(Mutex* mutex) { + InitializeCriticalSection(mutex); + return GetLastError(); +} + +static inline int MutexDeinit(Mutex* mutex) { + DeleteCriticalSection(mutex); + return GetLastError(); +} + +static inline int MutexLock(Mutex* mutex) { + EnterCriticalSection(mutex); + return GetLastError(); +} + +static inline int MutexUnlock(Mutex* mutex) { + LeaveCriticalSection(mutex); + return GetLastError(); +} + +static inline int ConditionInit(Condition* cond) { + InitializeConditionVariable(cond); + return GetLastError(); +} + +static inline int ConditionDeinit(Condition* cond) { + // This is a no-op on Windows + UNUSED(cond); + return 0; +} + +static inline int ConditionWait(Condition* cond, Mutex* mutex) { + SleepConditionVariableCS(cond, mutex, INFINITE); + return GetLastError(); +} + +static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) { + SleepConditionVariableCS(cond, mutex, timeoutMs); + return GetLastError(); +} + +static inline int ConditionWake(Condition* cond) { + WakeAllConditionVariable(cond); + return GetLastError(); +} + +static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) { + *thread = CreateThread(NULL, 0, entry, context, 0, 0); + return GetLastError(); +} + +static inline int ThreadJoin(Thread thread) { + DWORD error = WaitForSingleObject(thread, INFINITE); + if (error == WAIT_FAILED) { + return GetLastError(); + } + return 0; +} + +static inline int ThreadSetName(const char* name) { + UNUSED(name); + return -1; +} + +#endif
M src/util/common.hsrc/util/common.h

@@ -19,16 +19,12 @@ #include <stdio.h>

#include <stdlib.h> #include <string.h> +#include "version.h" + #ifdef _MSC_VER -#ifdef _WIN64 -typedef int64_t off_t; -typedef int64_t ssize_t; -#else -typedef int32_t off_t; -typedef int32_t ssize_t; -#endif +typedef intptr_t off_t; +typedef intptr_t ssize_t; #define restrict __restrict -#define SSIZE_MAX ((ssize_t) SIZE_MAX) #define strcasecmp _stricmp #define strncasecmp _strnicmp #define ftruncate _chsize

@@ -40,7 +36,9 @@ #include <strings.h>

#include <unistd.h> #endif -#include "version.h" +#ifndef SSIZE_MAX +#define SSIZE_MAX ((ssize_t) (SIZE_MAX >> 1)) +#endif #define UNUSED(V) (void)(V)
M src/util/configuration.csrc/util/configuration.c

@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "configuration.h" #include "util/formatting.h" +#include "util/string.h" #include "util/vfs.h" #include "third-party/inih/ini.h"
M src/util/table.csrc/util/table.c

@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "table.h" #include "util/hash.h" +#include "util/string.h" #define LIST_INITIAL_SIZE 8 #define TABLE_INITIAL_SIZE 8
M src/util/threading.hsrc/util/threading.h

@@ -1,4 +1,4 @@

-/* Copyright (c) 2013-2014 Jeffrey Pfau +/* Copyright (c) 2013-2015 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this

@@ -10,158 +10,9 @@ #include "util/common.h"

#ifndef DISABLE_THREADING #ifdef USE_PTHREADS -#include <pthread.h> -#include <sys/time.h> -#ifdef __FreeBSD__ -#include <pthread_np.h> -#endif - -#define THREAD_ENTRY void* -typedef THREAD_ENTRY (*ThreadEntry)(void*); - -typedef pthread_t Thread; -typedef pthread_mutex_t Mutex; -typedef pthread_cond_t Condition; - -static inline int MutexInit(Mutex* mutex) { - return pthread_mutex_init(mutex, 0); -} - -static inline int MutexDeinit(Mutex* mutex) { - return pthread_mutex_destroy(mutex); -} - -static inline int MutexLock(Mutex* mutex) { - return pthread_mutex_lock(mutex); -} - -static inline int MutexUnlock(Mutex* mutex) { - return pthread_mutex_unlock(mutex); -} - -static inline int ConditionInit(Condition* cond) { - return pthread_cond_init(cond, 0); -} - -static inline int ConditionDeinit(Condition* cond) { - return pthread_cond_destroy(cond); -} - -static inline int ConditionWait(Condition* cond, Mutex* mutex) { - return pthread_cond_wait(cond, mutex); -} - -static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) { - struct timespec ts; - struct timeval tv; - - gettimeofday(&tv, 0); - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = (tv.tv_usec + timeoutMs * 1000L) * 1000L; - if (ts.tv_nsec >= 1000000000L) { - ts.tv_nsec -= 1000000000L; - ++ts.tv_sec; - } - - return pthread_cond_timedwait(cond, mutex, &ts); -} - -static inline int ConditionWake(Condition* cond) { - return pthread_cond_broadcast(cond); -} - -static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) { - return pthread_create(thread, 0, entry, context); -} - -static inline int ThreadJoin(Thread thread) { - return pthread_join(thread, 0); -} - -static inline int ThreadSetName(const char* name) { -#ifdef __APPLE__ - return pthread_setname_np(name); -#elif defined(__FreeBSD__) - pthread_set_name_np(pthread_self(), name); - return 0; -#else - return pthread_setname_np(pthread_self(), name); -#endif -} - +#include "platform/posix/threading.h" #elif _WIN32 -#define _WIN32_WINNT 0x0600 -#include <windows.h> -#define THREAD_ENTRY DWORD WINAPI -typedef THREAD_ENTRY ThreadEntry(LPVOID); - -typedef HANDLE Thread; -typedef CRITICAL_SECTION Mutex; -typedef CONDITION_VARIABLE Condition; - -static inline int MutexInit(Mutex* mutex) { - InitializeCriticalSection(mutex); - return GetLastError(); -} - -static inline int MutexDeinit(Mutex* mutex) { - DeleteCriticalSection(mutex); - return GetLastError(); -} - -static inline int MutexLock(Mutex* mutex) { - EnterCriticalSection(mutex); - return GetLastError(); -} - -static inline int MutexUnlock(Mutex* mutex) { - LeaveCriticalSection(mutex); - return GetLastError(); -} - -static inline int ConditionInit(Condition* cond) { - InitializeConditionVariable(cond); - return GetLastError(); -} - -static inline int ConditionDeinit(Condition* cond) { - // This is a no-op on Windows - UNUSED(cond); - return 0; -} - -static inline int ConditionWait(Condition* cond, Mutex* mutex) { - SleepConditionVariableCS(cond, mutex, INFINITE); - return GetLastError(); -} - -static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) { - SleepConditionVariableCS(cond, mutex, timeoutMs); - return GetLastError(); -} - -static inline int ConditionWake(Condition* cond) { - WakeAllConditionVariable(cond); - return GetLastError(); -} - -static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) { - *thread = CreateThread(NULL, 0, entry, context, 0, 0); - return GetLastError(); -} - -static inline int ThreadJoin(Thread thread) { - DWORD error = WaitForSingleObject(thread, INFINITE); - if (error == WAIT_FAILED) { - return GetLastError(); - } - return 0; -} - -static inline int ThreadSetName(const char* name) { - UNUSED(name); - return -1; -} +#include "platform/windows/threading.h" #else #define DISABLE_THREADING #endif
M src/util/vfs.csrc/util/vfs.c

@@ -6,43 +6,19 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "vfs.h" ssize_t VFileReadline(struct VFile* vf, char* buffer, size_t size) { - size_t bytesRead = 0; + ssize_t bytesRead = 0; while (bytesRead < size - 1) { - size_t newRead = vf->read(vf, &buffer[bytesRead], 1); - bytesRead += newRead; - if (!newRead || buffer[bytesRead] == '\n') { + ssize_t newRead = vf->read(vf, &buffer[bytesRead], 1); + if (newRead <= 0) { break; } - } - return buffer[bytesRead] = '\0'; -} - -struct VFile* VDirOptionalOpenFile(struct VDir* dir, const char* realPath, const char* prefix, const char* suffix, int mode) { - char path[PATH_MAX]; - path[PATH_MAX - 1] = '\0'; - struct VFile* vf; - if (!dir) { - if (!realPath) { - return 0; - } - char* dotPoint = strrchr(realPath, '.'); - if (dotPoint - realPath + 1 >= PATH_MAX - 1) { - return 0; - } - if (dotPoint > strrchr(realPath, '/')) { - int len = dotPoint - realPath; - strncpy(path, realPath, len); - path[len] = 0; - strncat(path + len, suffix, PATH_MAX - len - 1); - } else { - snprintf(path, PATH_MAX - 1, "%s%s", realPath, suffix); + bytesRead += newRead; + if (buffer[bytesRead] == '\n') { + break; } - vf = VFileOpen(path, mode); - } else { - snprintf(path, PATH_MAX - 1, "%s%s", prefix, suffix); - vf = dir->openFile(dir, path, mode); } - return vf; + buffer[bytesRead] = '\0'; + return bytesRead; } ssize_t VFileWrite32LE(struct VFile* vf, int32_t word) {
M src/util/vfs/vfs-dirent.csrc/util/vfs/vfs-dirent.c

@@ -190,3 +190,31 @@ return vdede->ent->d_name;

} return 0; } + +struct VFile* VDirOptionalOpenFile(struct VDir* dir, const char* realPath, const char* prefix, const char* suffix, int mode) { + char path[PATH_MAX]; + path[PATH_MAX - 1] = '\0'; + struct VFile* vf; + if (!dir) { + if (!realPath) { + return 0; + } + char* dotPoint = strrchr(realPath, '.'); + if (dotPoint - realPath + 1 >= PATH_MAX - 1) { + return 0; + } + if (dotPoint > strrchr(realPath, '/')) { + int len = dotPoint - realPath; + strncpy(path, realPath, len); + path[len] = 0; + strncat(path + len, suffix, PATH_MAX - len - 1); + } else { + snprintf(path, PATH_MAX - 1, "%s%s", realPath, suffix); + } + vf = VFileOpen(path, mode); + } else { + snprintf(path, PATH_MAX - 1, "%s%s", prefix, suffix); + vf = dir->openFile(dir, path, mode); + } + return vf; +}