Merge branch 'master' into medusa

This commit is contained in:
Vicki Pfau 2022-08-23 21:06:35 -07:00
commit ddbdb62473
28 changed files with 734 additions and 600 deletions

View File

@ -97,6 +97,7 @@ Other fixes:
- Core: Fix the runloop resuming after a game has crashed (fixes mgba.io/i/2451)
- Core: Fix crash if library can't be opened
- Debugger: Fix crash with extremely long CLI strings
- Debugger: Fix multiple conditional watchpoints at the same address
- FFmpeg: Fix crash when encoding audio with some containers
- FFmpeg: Fix GIF recording (fixes mgba.io/i/2393)
- GB: Fix temporary saves

View File

@ -21,14 +21,11 @@ if(NOT LIBMGBA_ONLY)
set(BINARY_NAME ${BINARY_NAME} CACHE INTERNAL "Name of output binaries")
endif()
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD 11)
if(NOT MSVC)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
if(SWITCH OR 3DS)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_EXTENSIONS ON)
elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.3")
if(SWITCH OR 3DS OR (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.3"))
set(CMAKE_C_EXTENSIONS ON)
endif()
set(WARNING_FLAGS "-Wall -Wextra -Wno-missing-field-initializers")
@ -39,8 +36,8 @@ if(NOT MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=implicit-function-declaration")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267 /Zc:preprocessor-")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267 /Zc:preprocessor-")
endif()
if(NOT LIBMGBA_ONLY)

View File

@ -136,7 +136,7 @@ DS default controls are slightly different:
Compiling
---------
Compiling requires using CMake 3.1 or newer. GCC and Clang are both known to work to compile medusa, but Visual Studio 2013 and older are known not to work. Support for Visual Studio 2015 and newer is coming soon.
Compiling requires using CMake 3.1 or newer. GCC, Clang and Visual Studio 2019 known to work to compile medusa.
#### Docker building

View File

@ -20,6 +20,7 @@
CXX_GUARD_START
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <inttypes.h>

View File

@ -24,7 +24,6 @@ typedef THREAD_ENTRY (*ThreadEntry)(void*);
typedef pthread_t Thread;
typedef pthread_mutex_t Mutex;
typedef pthread_cond_t Condition;
typedef pthread_key_t ThreadLocal;
static inline int MutexInit(Mutex* mutex) {
return pthread_mutex_init(mutex, 0);
@ -104,6 +103,9 @@ static inline int ThreadSetName(const char* name) {
#endif
}
#if (__STDC_VERSION__ < 201112L) || (__STDC_NO_THREADS__ == 1)
typedef pthread_key_t ThreadLocal;
static inline void ThreadLocalInitKey(ThreadLocal* key) {
pthread_key_create(key, 0);
}
@ -115,6 +117,7 @@ static inline void ThreadLocalSetKey(ThreadLocal key, void* value) {
static inline void* ThreadLocalGetValue(ThreadLocal key) {
return pthread_getspecific(key);
}
#endif
CXX_GUARD_END

View File

@ -17,7 +17,6 @@ typedef struct {
} Condition;
#define THREAD_ENTRY int
typedef THREAD_ENTRY (*ThreadEntry)(void*);
typedef int ThreadLocal;
static inline int MutexInit(Mutex* mutex) {
Mutex id = sceKernelCreateMutex("mutex", 0, 0, 0);
@ -145,6 +144,9 @@ static inline int ThreadSetName(const char* name) {
return -1;
}
#if (__STDC_VERSION__ < 201112L) || (__STDC_NO_THREADS__ == 1)
typedef int ThreadLocal;
static inline void ThreadLocalInitKey(ThreadLocal* key) {
static int base = 0x90;
*key = __atomic_fetch_add(&base, 1, __ATOMIC_SEQ_CST);
@ -160,3 +162,4 @@ static inline void* ThreadLocalGetValue(ThreadLocal key) {
return *tls;
}
#endif
#endif

View File

@ -16,7 +16,6 @@ typedef THREAD_ENTRY ThreadEntry(LPVOID);
typedef HANDLE Thread;
typedef CRITICAL_SECTION Mutex;
typedef CONDITION_VARIABLE Condition;
typedef DWORD ThreadLocal;
static inline int MutexInit(Mutex* mutex) {
InitializeCriticalSection(mutex);
@ -89,6 +88,9 @@ static inline int ThreadSetName(const char* name) {
return -1;
}
#if (__STDC_VERSION__ < 201112L) || (__STDC_NO_THREADS__ == 1)
typedef DWORD ThreadLocal;
static inline void ThreadLocalInitKey(ThreadLocal* key) {
*key = TlsAlloc();
}
@ -100,5 +102,6 @@ static inline void ThreadLocalSetKey(ThreadLocal key, void* value) {
static inline void* ThreadLocalGetValue(ThreadLocal key) {
return TlsGetValue(key);
}
#endif
#endif

View File

@ -39,6 +39,10 @@ typedef SOCKET Socket;
typedef int Socket;
#endif
#if !defined(__3DS__) && !defined(GEKKO)
#define HAS_IPV6
#endif
enum IP {
IPV4,
IPV6
@ -152,12 +156,36 @@ static inline int SocketClose(Socket socket) {
#endif
}
static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress) {
#ifdef GEKKO
Socket sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
static inline void SocketCloseQuiet(Socket socket) {
int savedErrno = SocketError();
SocketClose(socket);
#ifdef _WIN32
WSASetLastError(savedErrno);
#else
Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
errno = savedErrno;
#endif
}
static inline Socket SocketCreate(bool useIPv6, int protocol) {
if (useIPv6) {
#ifdef HAS_IPV6
return socket(AF_INET6, SOCK_STREAM, protocol);
#else
errno = EAFNOSUPPORT;
return INVALID_SOCKET;
#endif
} else {
#ifdef GEKKO
return net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
#else
return socket(AF_INET, SOCK_STREAM, protocol);
#endif
}
}
static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress) {
bool useIPv6 = bindAddress && (bindAddress->version == IPV6);
Socket sock = SocketCreate(useIPv6, IPPROTO_TCP);
if (SOCKET_FAILED(sock)) {
return sock;
}
@ -178,7 +206,7 @@ static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress)
#else
err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo));
#endif
} else if (bindAddress->version == IPV4) {
} else if (!useIPv6) {
struct sockaddr_in bindInfo;
memset(&bindInfo, 0, sizeof(bindInfo));
bindInfo.sin_family = AF_INET;
@ -200,18 +228,15 @@ static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress)
#endif
}
if (err) {
SocketClose(sock);
SocketCloseQuiet(sock);
return INVALID_SOCKET;
}
return sock;
}
static inline Socket SocketConnectTCP(int port, const struct Address* destinationAddress) {
#ifdef GEKKO
Socket sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
#else
Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
#endif
bool useIPv6 = destinationAddress && (destinationAddress->version == IPV6);
Socket sock = SocketCreate(useIPv6, IPPROTO_TCP);
if (SOCKET_FAILED(sock)) {
return sock;
}
@ -238,7 +263,7 @@ static inline Socket SocketConnectTCP(int port, const struct Address* destinatio
#else
err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo));
#endif
#if !defined(__3DS__) && !defined(GEKKO)
#ifdef HAS_IPV6
} else {
struct sockaddr_in6 bindInfo;
memset(&bindInfo, 0, sizeof(bindInfo));
@ -250,7 +275,7 @@ static inline Socket SocketConnectTCP(int port, const struct Address* destinatio
}
if (err) {
SocketClose(sock);
SocketCloseQuiet(sock);
return INVALID_SOCKET;
}
return sock;

View File

@ -11,12 +11,6 @@
CXX_GUARD_START
#ifndef DISABLE_THREADING
#if (__STDC_VERSION__ >= 201112L) && (__STDC_NO_THREADS__ != 1)
#define ThreadLocal _Thread_local void*
#define ThreadLocalInitKey(X)
#define ThreadLocalSetKey(K, V) K = V
#define ThreadLocalGetValue(K) K
#endif
#ifdef USE_PTHREADS
#include <mgba-util/platform/posix/threading.h>
#elif defined(_WIN32)
@ -31,7 +25,15 @@ CXX_GUARD_START
#define DISABLE_THREADING
#endif
#endif
#ifdef DISABLE_THREADING
#ifndef DISABLE_THREADING
#if (__STDC_VERSION__ >= 201112L) && (__STDC_NO_THREADS__ != 1)
#define ThreadLocal _Thread_local void*
#define ThreadLocalInitKey(X)
#define ThreadLocalSetKey(K, V) K = V
#define ThreadLocalGetValue(K) K
#endif
#else
#ifdef __3DS__
// ctrulib already has a type called Thread
#include <3ds/thread.h>

View File

@ -164,12 +164,12 @@ mLOG_DECLARE_CATEGORY(GB_STATE);
* | 0x00197: Reserved (leave zero)
* 0x00198 - 0x0019F: Global cycle counter
* 0x001A0 - 0x001A1: Program counter for last cartridge read
* 0x001A2 - 0x00247: Reserved (leave zero)
* 0x00248 - 0x0025F: Additional audio state
* | 0x00248 - 0x0024B: Last sample timestamp
* | 0x0024C: Current audio sample index
* | 0x0024D - 0x0024F: Reserved (leave zero)
* | 0x00250 - 0x0025F: Audio rendered samples
* 0x001A2 - 0x001D7: Reserved (leave zero)
* 0x001D8 - 0x0025F: Additional audio state
* | 0x001D8 - 0x001DB: Last sample timestamp
* | 0x001DC: Current audio sample index
* | 0x001DD - 0x001DF: Reserved (leave zero)
* | 0x001E0 - 0x0025F: Audio rendered samples
* 0x00260 - 0x002FF: OAM
* 0x00300 - 0x0037F: I/O memory
* 0x00380 - 0x003FE: HRAM
@ -442,7 +442,7 @@ struct GBSerializedState {
int32_t lastSample;
uint8_t sampleIndex;
uint8_t reserved[3];
struct mStereoSample currentSamples[32];
struct mStereoSample currentSamples[GB_MAX_SAMPLES];
} audio2;
uint8_t oam[GB_SIZE_OAM];
@ -473,6 +473,8 @@ struct GBSerializedState {
};
#pragma pack(pop)
static_assert(sizeof(struct GBSerializedState) == 0x11800, "GB savestate struct sized wrong");
bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state);
void GBSerialize(struct GB* gb, struct GBSerializedState* state);

View File

@ -402,7 +402,7 @@ struct GBASerializedState {
int8_t chB[16];
} samples;
struct mStereoSample currentSamples[16];
struct mStereoSample currentSamples[GBA_MAX_SAMPLES];
uint32_t reserved[12];
@ -414,6 +414,8 @@ struct GBASerializedState {
uint8_t wram[SIZE_WORKING_RAM];
};
static_assert(sizeof(struct GBASerializedState) == 0x61000, "GBA savestate struct sized wrong");
struct VDir;
void GBASerialize(struct GBA* gba, struct GBASerializedState* state);

View File

@ -84,7 +84,9 @@ CXX_GUARD_START
extern const struct mScriptType mSTStruct_ ## STRUCT; \
extern const struct mScriptType mSTStructConst_ ## STRUCT; \
extern const struct mScriptType mSTStructPtr_ ## STRUCT; \
extern const struct mScriptType mSTStructPtrConst_ ## STRUCT;
extern const struct mScriptType mSTStructPtrConst_ ## STRUCT; \
extern const struct mScriptType mSTWrapper_ ## STRUCT; \
extern const struct mScriptType mSTWrapperConst_ ## STRUCT;
#define mSCRIPT_DEFINE_STRUCT(STRUCT) \
const struct mScriptType mSTStruct_ ## STRUCT; \

View File

@ -0,0 +1,25 @@
[shader]
name=TV Mode
author=Dominus Iniquitatis
description=Scanlines along with a subtle blurring.
passes=1
[pass.0]
fragmentShader=tv.fs
blend=1
width=-2
height=-2
[pass.0.uniform.lineBrightness]
type=float
readableName=Line brightness
default=0.75
min=0.0
max=1.0
[pass.0.uniform.blurring]
type=float
readableName=Blurring
default=1.0
min=0.0
max=1.0

View File

@ -0,0 +1,44 @@
/*
TV Mode Shader
Copyright (C) 2022 Dominus Iniquitatis - zerosaiko@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
uniform sampler2D tex;
uniform vec2 texSize;
varying vec2 texCoord;
uniform float lineBrightness;
uniform float blurring;
void main()
{
vec4 c = texture2D(tex, texCoord);
vec4 n = texture2D(tex, texCoord + vec2(1.0 / texSize.x * 0.5, 0.0));
vec4 color = mix(c, (c + n) / 2.0, blurring);
color.a = c.a;
if (int(mod(texCoord.t * texSize.y * 2.0, 2.0)) == 0)
{
color.rgb *= lineBrightness;
}
gl_FragColor = color;
}

View File

@ -102,7 +102,7 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st
int32_t value;
int segment;
if (!mDebuggerEvaluateParseTree(debugger->d.p, watchpoint->condition, &value, &segment) || !(value || segment >= 0)) {
return false;
continue;
}
}

View File

@ -717,7 +717,7 @@ static void mScriptConsoleLog(struct mScriptConsole* console, struct mScriptStri
if (console->logger) {
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_INFO, "%s", msg->buffer);
} else {
mLog(_mLOG_CAT_SCRIPT, mLOG_INFO, "%s", msg->buffer);
mLog(_mLOG_CAT_SCRIPT, mLOG_INFO, "%s", msg->buffer);
}
}
@ -725,7 +725,7 @@ static void mScriptConsoleWarn(struct mScriptConsole* console, struct mScriptStr
if (console->logger) {
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg->buffer);
} else {
mLog(_mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg->buffer);
mLog(_mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg->buffer);
}
}
@ -733,7 +733,7 @@ static void mScriptConsoleError(struct mScriptConsole* console, struct mScriptSt
if (console->logger) {
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_ERROR, "%s", msg->buffer);
} else {
mLog(_mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg->buffer);
mLog(_mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg->buffer);
}
}
@ -818,7 +818,7 @@ mSCRIPT_DEFINE_STRUCT(mScriptTextBuffer)
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, clear)
mSCRIPT_DEFINE_DOCSTRING("Set the number of rows and columns")
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, setSize)
mSCRIPT_DEFINE_DOCSTRING("Set the posiiton of the cursor")
mSCRIPT_DEFINE_DOCSTRING("Set the position of the cursor")
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, moveCursor)
mSCRIPT_DEFINE_DOCSTRING("Advance the cursor a number of columns")
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, advance)

View File

@ -474,9 +474,8 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) {
if (!audio->enable) {
return;
}
if (audio->p && channels != 0xF && timestamp - audio->lastSample > SAMPLE_INTERVAL) {
if (audio->p && channels != 0xF && timestamp - audio->lastSample > (int) (SAMPLE_INTERVAL * audio->timingFactor)) {
GBAudioSample(audio, timestamp);
return;
}
if (audio->playingCh1 && (channels & 0x1)) {
@ -747,10 +746,9 @@ void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) {
}
void GBAudioSample(struct GBAudio* audio, int32_t timestamp) {
timestamp -= audio->lastSample;
timestamp -= audio->sampleIndex * SAMPLE_INTERVAL;
int interval = SAMPLE_INTERVAL * audio->timingFactor;
timestamp -= audio->lastSample;
timestamp -= audio->sampleIndex * interval;
int sample;
for (sample = audio->sampleIndex; timestamp >= interval && sample < GB_MAX_SAMPLES; ++sample, timestamp -= interval) {

View File

@ -627,7 +627,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
if (startX == 0) {
_cleanOAM(softwareRenderer, y);
}
if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc) && !softwareRenderer->d.disableOBJ && (softwareRenderer->model != GB_MODEL_SCGB || softwareRenderer->sgbTransfer != 1)) {
if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc) && !softwareRenderer->d.disableOBJ) {
int i;
for (i = 0; i < softwareRenderer->objMax; ++i) {
GBVideoSoftwareRendererDrawObj(softwareRenderer, &softwareRenderer->obj[i], startX, endX, y);
@ -917,7 +917,7 @@ static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer
bgTile = ((int8_t*) maps)[topX + topY];
}
int p = highlight ? PAL_HIGHLIGHT_BG : PAL_BG;
if (renderer->model >= GB_MODEL_CGB && (!(renderer->model & GB_MODEL_SGB) || renderer->sgbTransfer != 1)) {
if (renderer->model >= GB_MODEL_CGB) {
GBObjAttributes attrs = attr[topX + topY];
p |= GBObjAttributesGetCGBPalette(attrs) * 4;
if (GBObjAttributesIsPriority(attrs) && GBRegisterLCDCIsBgEnable(renderer->lcdc)) {
@ -952,7 +952,7 @@ static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer
bgTile = ((int8_t*) maps)[topX + topY];
}
int p = highlight ? PAL_HIGHLIGHT_BG : PAL_BG;
if (renderer->model >= GB_MODEL_CGB && (!(renderer->model & GB_MODEL_SGB) || renderer->sgbTransfer != 1)) {
if (renderer->model >= GB_MODEL_CGB) {
GBObjAttributes attrs = attr[topX + topY];
p |= GBObjAttributesGetCGBPalette(attrs) * 4;
if (GBObjAttributesIsPriority(attrs) && GBRegisterLCDCIsBgEnable(renderer->lcdc)) {

View File

@ -12,6 +12,9 @@
#include <QMenu>
#include <mgba/feature/commandline.h>
#ifdef M_CORE_GB
#include <mgba/internal/gb/overrides.h>
#endif
static const mOption s_frontendOptions[] = {
{ "ecard", true, '\0' },
@ -128,8 +131,10 @@ ConfigController::ConfigController(QObject* parent)
m_opts.interframeBlending = false;
mCoreConfigLoad(&m_config);
mCoreConfigLoadDefaults(&m_config, &m_opts);
#ifdef M_CORE_GB
mCoreConfigSetDefaultIntValue(&m_config, "sgb.borders", 1);
mCoreConfigSetDefaultIntValue(&m_config, "useCgbColors", 1);
mCoreConfigSetDefaultIntValue(&m_config, "gb.colors", GB_COLORS_CGB);
#endif
mCoreConfigMap(&m_config, &m_opts);
mSubParserGraphicsInit(&m_subparsers[0], &m_graphicsOpts);

View File

@ -221,7 +221,7 @@ void DisplayGL::startDrawing(std::shared_ptr<CoreController> controller) {
CoreController::Interrupter interrupter(controller);
QMetaObject::invokeMethod(m_painter.get(), "start");
if (!m_gl) {
if (QGuiApplication::platformName() == "windows") {
if (shouldDisableUpdates()) {
setUpdatesEnabled(false);
}
} else {
@ -309,7 +309,7 @@ void DisplayGL::unpauseDrawing() {
if (m_hasStarted) {
m_isDrawing = true;
QMetaObject::invokeMethod(m_painter.get(), "unpause", Qt::BlockingQueuedConnection);
if (!m_gl && QGuiApplication::platformName() == "windows") {
if (!m_gl && shouldDisableUpdates()) {
setUpdatesEnabled(false);
}
}
@ -388,6 +388,16 @@ void DisplayGL::resizePainter() {
}
}
bool DisplayGL::shouldDisableUpdates() {
if (QGuiApplication::platformName() == "windows") {
return true;
}
if (QGuiApplication::platformName() == "xcb") {
return true;
}
return false;
}
void DisplayGL::setVideoProxy(std::shared_ptr<VideoProxy> proxy) {
Display::setVideoProxy(proxy);
if (proxy) {

View File

@ -112,6 +112,7 @@ protected:
private:
void resizePainter();
bool shouldDisableUpdates();
static QHash<QSurfaceFormat, bool> s_supports;

View File

@ -165,10 +165,16 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi
});
#endif
#if defined(M_CORE_GBA)
resizeFrame(QSize(GBA_VIDEO_HORIZONTAL_PIXELS * i, GBA_VIDEO_VERTICAL_PIXELS * i));
QSize minimumSize = QSize(GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS);
#elif defined(M_CORE_GB)
resizeFrame(QSize(GB_VIDEO_HORIZONTAL_PIXELS * i, GB_VIDEO_VERTICAL_PIXELS * i));
QSize minimumSize = QSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS);
#endif
setMinimumSize(minimumSize);
if (i > 0) {
m_initialSize = minimumSize * i;
} else {
m_initialSize = minimumSize * 2;
}
setLogo();
connect(this, &Window::shutdown, m_logView, &QWidget::hide);
@ -232,7 +238,7 @@ void Window::argumentsPassed() {
}
#endif
if (m_config->graphicsOpts()->multiplier) {
if (m_config->graphicsOpts()->multiplier > 0) {
m_savedScale = m_config->graphicsOpts()->multiplier;
#if defined(M_CORE_GBA)
@ -240,7 +246,7 @@ void Window::argumentsPassed() {
#elif defined(M_CORE_GB)
QSize size(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS);
#endif
resizeFrame(size * m_savedScale);
m_initialSize = size * m_savedScale;
}
if (args->fname) {
@ -263,9 +269,8 @@ void Window::resizeFrame(const QSize& size) {
newSize.setHeight(geom.height());
}
}
m_screenWidget->setSizeHint(newSize);
newSize -= m_screenWidget->size();
newSize += this->size();
newSize -= centralWidget()->size();
if (!isFullScreen()) {
resize(newSize);
}
@ -295,7 +300,7 @@ void Window::loadConfig() {
reloadConfig();
if (opts->width && opts->height) {
resizeFrame(QSize(opts->width, opts->height));
m_initialSize = QSize(opts->width, opts->height);
}
if (opts->fullscreen) {
@ -715,9 +720,10 @@ void Window::scriptingOpen() {
#endif
void Window::resizeEvent(QResizeEvent*) {
QSize newSize = centralWidget()->size();
if (!isFullScreen()) {
m_config->setOption("height", m_screenWidget->height());
m_config->setOption("width", m_screenWidget->width());
m_config->setOption("height", newSize.height());
m_config->setOption("width", newSize.width());
}
int factor = 0;
@ -725,9 +731,9 @@ void Window::resizeEvent(QResizeEvent*) {
if (m_controller) {
size = m_controller->screenDimensions();
}
if (m_screenWidget->width() % size.width() == 0 && m_screenWidget->height() % size.height() == 0 &&
m_screenWidget->width() / size.width() == m_screenWidget->height() / size.height()) {
factor = m_screenWidget->width() / size.width();
if (newSize.width() % size.width() == 0 && newSize.height() % size.height() == 0 &&
newSize.width() / size.width() == newSize.height() / size.height()) {
factor = newSize.width() / size.width();
}
m_savedScale = factor;
for (QMap<int, Action*>::iterator iter = m_frameSizes.begin(); iter != m_frameSizes.end(); ++iter) {
@ -754,7 +760,9 @@ void Window::showEvent(QShowEvent* event) {
return;
}
m_wasOpened = true;
resizeFrame(m_screenWidget->sizeHint());
if (m_initialSize.isValid()) {
resizeFrame(m_initialSize);
}
QVariant windowPos = m_config->getQtOption("windowPos", m_playerId > 0 ? QString("player%0").arg(m_playerId) : QString());
bool maximized = m_config->getQtOption("maximized").toBool();
QRect geom = windowHandle()->screen()->availableGeometry();
@ -910,7 +918,7 @@ void Window::exitFullScreen() {
if (!isFullScreen()) {
return;
}
m_screenWidget->unsetCursor();
centralWidget()->unsetCursor();
menuBar()->show();
showNormal();
}
@ -973,7 +981,7 @@ void Window::gameStarted() {
}
m_focusCheck.start();
if (m_display->underMouse()) {
m_screenWidget->setCursor(Qt::BlankCursor);
centralWidget()->setCursor(Qt::BlankCursor);
}
CoreController::Interrupter interrupter(m_controller);
@ -1118,11 +1126,11 @@ void Window::reloadDisplayDriver() {
connect(m_display.get(), &QGBA::Display::hideCursor, [this]() {
if (centralWidget() == m_display.get()) {
m_screenWidget->setCursor(Qt::BlankCursor);
centralWidget()->setCursor(Qt::BlankCursor);
}
});
connect(m_display.get(), &QGBA::Display::showCursor, [this]() {
m_screenWidget->unsetCursor();
centralWidget()->unsetCursor();
});
m_display->configure(m_config);
@ -2207,7 +2215,7 @@ void Window::updateMute() {
void Window::setLogo() {
m_screenWidget->setPixmap(m_logo);
m_screenWidget->setDimensions(m_logo.width(), m_logo.height());
m_screenWidget->unsetCursor();
centralWidget()->unsetCursor();
}
WindowBackground::WindowBackground(QWidget* parent)

View File

@ -195,6 +195,7 @@ private:
std::unique_ptr<AudioProcessor> m_audioProcessor;
std::unique_ptr<QGBA::Display> m_display;
QSize m_initialSize;
int m_savedScale;
// TODO: Move these to a new class

View File

@ -180,7 +180,7 @@ Tamaño de la descarga: %3</translation>
<message>
<location filename="../AudioDevice.cpp" line="62"/>
<source>Writing data to read-only audio device</source>
<translation type="unfinished"></translation>
<translation>Escribiendo datos a dispositivo de audio de sólo lectura</translation>
</message>
</context>
<context>
@ -188,7 +188,7 @@ Tamaño de la descarga: %3</translation>
<message>
<location filename="../AudioProcessorQt.cpp" line="43"/>
<source>Can&apos;t start an audio processor without input</source>
<translation type="unfinished"></translation>
<translation>Sin entrada no se puede iniciar un procesador de audio</translation>
</message>
</context>
<context>
@ -196,7 +196,7 @@ Tamaño de la descarga: %3</translation>
<message>
<location filename="../AudioProcessorSDL.cpp" line="34"/>
<source>Can&apos;t start an audio processor without input</source>
<translation type="unfinished"></translation>
<translation>Sin entrada no se puede iniciar un procesador de audio</translation>
</message>
</context>
<context>
@ -264,12 +264,12 @@ Tamaño de la descarga: %3</translation>
<message>
<location filename="../BattleChipView.cpp" line="117"/>
<source>BattleChip data missing</source>
<translation type="unfinished"></translation>
<translation type="unfinished">Faltan los datos de BattleChip</translation>
</message>
<message>
<location filename="../BattleChipView.cpp" line="118"/>
<source>BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now?</source>
<translation type="unfinished"></translation>
<translation>Faltan los datos de BattleChip. BattleChip Gates seguirán funcionando, pero faltarán algunos gráficos. ¿Quiere descargar los datos ahora?</translation>
</message>
<message>
<location filename="../BattleChipView.cpp" line="184"/>
@ -358,7 +358,7 @@ Tamaño de la descarga: %3</translation>
<message>
<location filename="../CheatsView.cpp" line="187"/>
<source>Some cheats could not be added. Please ensure they&apos;re formatted correctly and/or try other cheat types.</source>
<translation type="unfinished"></translation>
<translation type="unfinished">Algunos trucos no se pudieron añadir. Asegúrese de que están formateados correctamente y/o pruebe otros tipos de trucos.</translation>
</message>
</context>
<context>
@ -793,7 +793,7 @@ Tamaño de la descarga: %3</translation>
<message>
<location filename="../GameBoy.cpp" line="75"/>
<source>ROM Only</source>
<translation type="unfinished"></translation>
<translation type="unfinished">Sólo ROM</translation>
</message>
<message>
<location filename="../GameBoy.cpp" line="76"/>

View File

@ -758,37 +758,37 @@ Dimensione del download: %3</translation>
<message>
<location filename="../GameBoy.cpp" line="56"/>
<source>Game Boy (DMG)</source>
<translation type="unfinished"></translation>
<translation>Game Boy (DMG)</translation>
</message>
<message>
<location filename="../GameBoy.cpp" line="57"/>
<source>Game Boy Pocket (MGB)</source>
<translation type="unfinished"></translation>
<translation>Game Boy Pocket (MGB)</translation>
</message>
<message>
<location filename="../GameBoy.cpp" line="58"/>
<source>Super Game Boy (SGB)</source>
<translation type="unfinished"></translation>
<translation>Super Game Boy (SGB)</translation>
</message>
<message>
<location filename="../GameBoy.cpp" line="59"/>
<source>Super Game Boy 2 (SGB)</source>
<translation type="unfinished"></translation>
<translation>Super Game Boy 2 (SGB)</translation>
</message>
<message>
<location filename="../GameBoy.cpp" line="60"/>
<source>Game Boy Color (CGB)</source>
<translation type="unfinished"></translation>
<translation>Game Boy Color (CGB)</translation>
</message>
<message>
<location filename="../GameBoy.cpp" line="61"/>
<source>Game Boy Advance (AGB)</source>
<translation type="unfinished"></translation>
<translation>Game Boy Advance (AGB)</translation>
</message>
<message>
<location filename="../GameBoy.cpp" line="62"/>
<source>Super Game Boy Color (SGB + CGB)</source>
<translation type="unfinished"></translation>
<translation>Super Game Boy Color (SGB + CGB)</translation>
</message>
<message>
<location filename="../GameBoy.cpp" line="75"/>
@ -4788,7 +4788,7 @@ Dimensione del download: %3</translation>
<message>
<location filename="../SettingsView.ui" line="555"/>
<source>Load last state</source>
<translation type="unfinished"></translation>
<translation>Carica l&apos;ultimo stato</translation>
</message>
<message>
<location filename="../SettingsView.ui" line="565"/>
@ -4798,7 +4798,7 @@ Dimensione del download: %3</translation>
<message>
<location filename="../SettingsView.ui" line="592"/>
<source>Save entered cheats</source>
<translation type="unfinished"></translation>
<translation>Salva i trucchi inseriti</translation>
</message>
<message>
<location filename="../SettingsView.ui" line="813"/>
@ -4979,7 +4979,7 @@ Dimensione del download: %3</translation>
<message>
<location filename="../SettingsView.ui" line="582"/>
<source>Periodically autosave state</source>
<translation type="unfinished"></translation>
<translation>Salva periodicamente in automatico lo stato</translation>
</message>
<message>
<location filename="../SettingsView.ui" line="865"/>

File diff suppressed because it is too large Load Diff

View File

@ -4008,12 +4008,12 @@ Download size: %3</source>
<message>
<location filename="../PrinterView.cpp" line="59"/>
<source>Save Printout</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../PrinterView.cpp" line="59"/>
<source>Portable Network Graphics (*.png)</source>
<translation type="unfinished">便 (*.png)</translation>
<translation>便 (*.png)</translation>
</message>
</context>
<context>
@ -4337,17 +4337,17 @@ Download size: %3</source>
<message>
<location filename="../scripting/ScriptingView.cpp" line="60"/>
<source>Select script to load</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../scripting/ScriptingView.cpp" line="85"/>
<source>Lua scripts (*.lua)</source>
<translation type="unfinished">Lua (*.lua)</translation>
<translation>Lua (*.lua)</translation>
</message>
<message>
<location filename="../scripting/ScriptingView.cpp" line="87"/>
<source>All files (*.*)</source>
<translation type="unfinished"> (*.*)</translation>
<translation> (*.*)</translation>
</message>
</context>
<context>
@ -4796,22 +4796,22 @@ Download size: %3</source>
<message>
<location filename="../SettingsView.ui" line="548"/>
<source>On loading a game:</source>
<translation type="unfinished"></translation>
<translation>:</translation>
</message>
<message>
<location filename="../SettingsView.ui" line="555"/>
<source>Load last state</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../SettingsView.ui" line="565"/>
<source>Load cheats</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../SettingsView.ui" line="592"/>
<source>Save entered cheats</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../SettingsView.ui" line="813"/>
@ -5641,12 +5641,12 @@ Download size: %3</source>
<message>
<location filename="../VideoView.ui" line="277"/>
<source>H.264</source>
<translation type="unfinished">H.264</translation>
<translation>H.264</translation>
</message>
<message>
<location filename="../VideoView.ui" line="282"/>
<source>H.264 (NVENC)</source>
<translation type="unfinished">H.264 (NVENC)</translation>
<translation>H.264 (NVENC)</translation>
</message>
<message>
<location filename="../VideoView.ui" line="455"/>
@ -5656,7 +5656,7 @@ Download size: %3</source>
<message>
<location filename="../VideoView.ui" line="468"/>
<source>CRF</source>
<translation type="unfinished">CRF</translation>
<translation>CRF</translation>
</message>
<message>
<location filename="../VideoView.ui" line="484"/>
@ -6338,7 +6338,7 @@ Download size: %3</source>
<message>
<location filename="../Window.cpp" line="1665"/>
<source>Game state views</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../Window.cpp" line="1666"/>
@ -6363,7 +6363,7 @@ Download size: %3</source>
<message>
<location filename="../Window.cpp" line="1671"/>
<source>&amp;Frame inspector...</source>
<translation>(&amp;F)...</translation>
<translation>(&amp;F)...</translation>
</message>
<message>
<location filename="../Window.cpp" line="1687"/>

View File

@ -52,7 +52,7 @@ static bool _checkWatchpoints(struct SM83Debugger* debugger, uint16_t address, s
int32_t value;
int segment;
if (!mDebuggerEvaluateParseTree(debugger->d.p, watchpoint->condition, &value, &segment) || !(value || segment >= 0)) {
return false;
continue;
}
}
uint8_t oldValue = debugger->originalMemory.load8(debugger->cpu, address);