From 62c84ab815c4a10be30b8b91679083d8c4536b22 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 10 Jan 2023 23:13:58 -0800 Subject: [PATCH 01/16] Util: Add some base vector implementations --- include/mgba-util/vector.h | 10 +++++++++- src/debugger/parser.c | 2 -- src/util/CMakeLists.txt | 1 + src/util/string.c | 4 ---- src/util/vector.c | 17 +++++++++++++++++ 5 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 src/util/vector.c diff --git a/include/mgba-util/vector.h b/include/mgba-util/vector.h index a4ec71b65..83112c0b5 100644 --- a/include/mgba-util/vector.h +++ b/include/mgba-util/vector.h @@ -97,8 +97,16 @@ CXX_GUARD_START dest->size = src->size; \ } \ -DECLARE_VECTOR(StringList, char*); DECLARE_VECTOR(IntList, int); +DECLARE_VECTOR(SInt8List, int8_t); +DECLARE_VECTOR(SInt16List, int16_t); +DECLARE_VECTOR(SInt32List, int32_t); +DECLARE_VECTOR(SIntPtrList, intptr_t); +DECLARE_VECTOR(UInt8List, uint8_t); +DECLARE_VECTOR(UInt16List, uint16_t); +DECLARE_VECTOR(UInt32List, uint32_t); +DECLARE_VECTOR(UIntPtrList, uintptr_t); +DECLARE_VECTOR(StringList, char*); CXX_GUARD_END diff --git a/src/debugger/parser.c b/src/debugger/parser.c index 0d4924ea9..3c3b037fa 100644 --- a/src/debugger/parser.c +++ b/src/debugger/parser.c @@ -11,8 +11,6 @@ DEFINE_VECTOR(LexVector, struct Token); -DEFINE_VECTOR(IntList, int32_t); - enum LexState { LEX_ERROR = -1, LEX_ROOT = 0, diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index df0d84c5c..9246b20c4 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -8,6 +8,7 @@ set(BASE_SOURCE_FILES hash.c string.c table.c + vector.c vfs.c) set(SOURCE_FILES diff --git a/src/util/string.c b/src/util/string.c index 9e007dc2d..1a2ffe7a4 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -5,12 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#include - #include -DEFINE_VECTOR(StringList, char*); - #ifndef HAVE_STRNDUP char* strndup(const char* start, size_t len) { // This is suboptimal, but anything recent should have strndup diff --git a/src/util/vector.c b/src/util/vector.c new file mode 100644 index 000000000..28750a1b4 --- /dev/null +++ b/src/util/vector.c @@ -0,0 +1,17 @@ +/* Copyright (c) 2013-2023 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/. */ +#include + +DEFINE_VECTOR(IntList, int); +DEFINE_VECTOR(SInt8List, int8_t); +DEFINE_VECTOR(SInt16List, int16_t); +DEFINE_VECTOR(SInt32List, int32_t); +DEFINE_VECTOR(SIntPtrList, intptr_t); +DEFINE_VECTOR(UInt8List, uint8_t); +DEFINE_VECTOR(UInt16List, uint16_t); +DEFINE_VECTOR(UInt32List, uint32_t); +DEFINE_VECTOR(UIntPtrList, uintptr_t); +DEFINE_VECTOR(StringList, char*); From 2df70ee45e4620a5a579dc76497b858e81f04703 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 11 Jan 2023 02:24:54 -0800 Subject: [PATCH 02/16] Util: Add debug bounds checking to vector --- include/mgba-util/vector.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/mgba-util/vector.h b/include/mgba-util/vector.h index 83112c0b5..8c0f11e45 100644 --- a/include/mgba-util/vector.h +++ b/include/mgba-util/vector.h @@ -34,6 +34,16 @@ CXX_GUARD_START size_t NAME ## Index(const struct NAME* vector, const TYPE* member); \ void NAME ## Copy(struct NAME* dest, const struct NAME* src); +#ifdef NDEBUG +#define VECTOR_BOUNDS_CHECK(NAME, V, L) +#else +#define VECTOR_BOUNDS_CHECK(NAME, V, L) \ + if ((L) >= (V)->size) { \ + fprintf(stderr, "Vector type %s invalid access of index %" PRIuPTR " into vector of size %" PRIuPTR "\n", #NAME, (L), (V)->size); \ + abort(); \ + } +#endif + #define DEFINE_VECTOR(NAME, TYPE) \ void NAME ## Init(struct NAME* vector, size_t capacity) { \ vector->size = 0; \ @@ -50,9 +60,11 @@ CXX_GUARD_START vector->size = 0; \ } \ TYPE* NAME ## GetPointer(struct NAME* vector, size_t location) { \ + VECTOR_BOUNDS_CHECK(NAME, vector, location); \ return &vector->vector[location]; \ } \ TYPE const* NAME ## GetConstPointer(const struct NAME* vector, size_t location) { \ + VECTOR_BOUNDS_CHECK(NAME, vector, location); \ return &vector->vector[location]; \ } \ TYPE* NAME ## Append(struct NAME* vector) { \ @@ -78,10 +90,12 @@ CXX_GUARD_START vector->vector = realloc(vector->vector, vector->capacity * sizeof(TYPE)); \ } \ void NAME ## Shift(struct NAME* vector, size_t location, size_t difference) { \ + VECTOR_BOUNDS_CHECK(NAME, vector, location); \ memmove(&vector->vector[location], &vector->vector[location + difference], (vector->size - location - difference) * sizeof(TYPE)); \ vector->size -= difference; \ } \ void NAME ## Unshift(struct NAME* vector, size_t location, size_t difference) { \ + VECTOR_BOUNDS_CHECK(NAME, vector, location); \ NAME ## Resize(vector, difference); \ memmove(&vector->vector[location + difference], &vector->vector[location], (vector->size - location - difference) * sizeof(TYPE)); \ } \ From 74e7a44da3d51dfe2be27961eca651cc3a9e05f8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Jan 2023 20:01:45 -0800 Subject: [PATCH 03/16] Qt: More API cleanup --- src/platform/qt/InputController.cpp | 25 ++++++++++-------------- src/platform/qt/InputController.h | 8 ++++---- src/platform/qt/input/InputDriver.cpp | 22 +++++++++++++++++++-- src/platform/qt/input/InputDriver.h | 7 +++++-- src/platform/qt/input/SDLInputDriver.cpp | 2 +- src/platform/qt/input/SDLInputDriver.h | 2 +- 6 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index 0c94e7511..e6e741a56 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -240,7 +240,7 @@ int InputController::gamepadIndex(uint32_t type) const { if (!driver) { return -1; } - return driver->activeGamepad(); + return driver->activeGamepadIndex(); } void InputController::setGamepad(uint32_t type, int index) { @@ -361,13 +361,9 @@ Gamepad* InputController::gamepad(uint32_t type) { } if (!driver->supportsGamepads()) { return nullptr; -} - QList driverPads(driver->connectedGamepads()); - int activeGamepad = driver->activeGamepad(); - if (activeGamepad < 0 || activeGamepad >= driverPads.count()) { - return nullptr; } - return driverPads[activeGamepad]; + + return driver->activeGamepad(); } QList InputController::gamepads() { @@ -376,16 +372,15 @@ QList InputController::gamepads() { if (!driver->supportsGamepads()) { continue; } - QList driverPads(driver->connectedGamepads()); - int activeGamepad = driver->activeGamepad(); - if (activeGamepad >= 0 && activeGamepad < driverPads.count()) { - pads.append(driverPads[activeGamepad]); + Gamepad* pad = driver->activeGamepad(); + if (pad) { + pads.append(pad); } } return pads; } -QSet InputController::activeGamepadButtons(int type) { +QSet InputController::activeGamepadButtons(uint32_t type) { QSet activeButtons; Gamepad* pad = gamepad(type); if (!pad) { @@ -400,7 +395,7 @@ QSet InputController::activeGamepadButtons(int type) { return activeButtons; } -QSet> InputController::activeGamepadAxes(int type) { +QSet> InputController::activeGamepadAxes(uint32_t type) { QSet> activeAxes; Gamepad* pad = gamepad(type); if (!pad) { @@ -421,7 +416,7 @@ QSet> InputController::activeGamepadAxes return activeAxes; } -QSet> InputController::activeGamepadHats(int type) { +QSet> InputController::activeGamepadHats(uint32_t type) { QSet> activeHats; Gamepad* pad = gamepad(type); if (!pad) { @@ -436,7 +431,7 @@ QSet> InputController::activeGamepadHats( return activeHats; } -void InputController::testGamepad(int type) { +void InputController::testGamepad(uint32_t type) { QWriteLocker l(&m_eventsLock); auto activeAxes = activeGamepadAxes(type); auto oldAxes = m_activeAxes; diff --git a/src/platform/qt/InputController.h b/src/platform/qt/InputController.h index ab6590e7c..e974c1aaa 100644 --- a/src/platform/qt/InputController.h +++ b/src/platform/qt/InputController.h @@ -107,7 +107,7 @@ signals: void luminanceValueChanged(int value); public slots: - void testGamepad(int type); + void testGamepad(uint32_t type); void update(); void increaseLuminanceLevel(); @@ -136,9 +136,9 @@ private: Gamepad* gamepad(uint32_t type); QList gamepads(); - QSet activeGamepadButtons(int type); - QSet> activeGamepadAxes(int type); - QSet> activeGamepadHats(int type); + QSet activeGamepadButtons(uint32_t type); + QSet> activeGamepadAxes(uint32_t type); + QSet> activeGamepadHats(uint32_t type); struct InputControllerLux : GBALuminanceSource { InputController* p; diff --git a/src/platform/qt/input/InputDriver.cpp b/src/platform/qt/input/InputDriver.cpp index 912395e0d..f76649bd8 100644 --- a/src/platform/qt/input/InputDriver.cpp +++ b/src/platform/qt/input/InputDriver.cpp @@ -40,14 +40,32 @@ QList InputDriver::connectedGamepads() const { return {}; } -int InputDriver::activeKeySource() const { +int InputDriver::activeKeySourceIndex() const { return -1; } -int InputDriver::activeGamepad() const { +int InputDriver::activeGamepadIndex() const { return -1; } +KeySource* InputDriver::activeKeySource() { + QList ks(connectedKeySources()); + int activeKeySource = activeKeySourceIndex(); + if (activeKeySource < 0 || activeKeySource >= ks.count()) { + return nullptr; + } + return ks[activeKeySource]; +} + +Gamepad* InputDriver::activeGamepad() { + QList pads(connectedGamepads()); + int activeGamepad = activeGamepadIndex(); + if (activeGamepad < 0 || activeGamepad >= pads.count()) { + return nullptr; + } + return pads[activeGamepad]; +} + void InputDriver::setActiveKeySource(int) { } diff --git a/src/platform/qt/input/InputDriver.h b/src/platform/qt/input/InputDriver.h index f344b271b..cc0a6e0cd 100644 --- a/src/platform/qt/input/InputDriver.h +++ b/src/platform/qt/input/InputDriver.h @@ -44,8 +44,11 @@ public: virtual QList connectedKeySources() const; virtual QList connectedGamepads() const; - virtual int activeKeySource() const; - virtual int activeGamepad() const; + virtual int activeKeySourceIndex() const; + virtual int activeGamepadIndex() const; + + KeySource* activeKeySource(); + Gamepad* activeGamepad(); virtual void setActiveKeySource(int); virtual void setActiveGamepad(int); diff --git a/src/platform/qt/input/SDLInputDriver.cpp b/src/platform/qt/input/SDLInputDriver.cpp index 2eda6a4f0..ca9e30b25 100644 --- a/src/platform/qt/input/SDLInputDriver.cpp +++ b/src/platform/qt/input/SDLInputDriver.cpp @@ -173,7 +173,7 @@ void SDLInputDriver::updateGamepads() { } #endif -int SDLInputDriver::activeGamepad() const { +int SDLInputDriver::activeGamepadIndex() const { return m_sdlPlayer.joystick ? m_sdlPlayer.joystick->index : 0; } diff --git a/src/platform/qt/input/SDLInputDriver.h b/src/platform/qt/input/SDLInputDriver.h index 79deac22c..09f4b9555 100644 --- a/src/platform/qt/input/SDLInputDriver.h +++ b/src/platform/qt/input/SDLInputDriver.h @@ -46,7 +46,7 @@ public: QList connectedGamepads() const override; - int activeGamepad() const override; + int activeGamepadIndex() const override; void setActiveGamepad(int) override; void registerTiltAxisX(int axis) override; From 53abcfd28e79d6316227b187c197673dc0fe40d5 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 23 Jan 2023 21:03:50 -0800 Subject: [PATCH 04/16] Scripting: Fix mSCRIPT_TYPE_MS_PCS macro --- include/mgba/script/types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mgba/script/types.h b/include/mgba/script/types.h index 470ed40ce..3099540dc 100644 --- a/include/mgba/script/types.h +++ b/include/mgba/script/types.h @@ -97,7 +97,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_MS_CS(STRUCT) (&mSTStructConst_ ## STRUCT) #define mSCRIPT_TYPE_MS_S_METHOD(STRUCT, NAME) (&_mSTStructBindingType_ ## STRUCT ## _ ## NAME) #define mSCRIPT_TYPE_MS_PS(STRUCT) (&mSTStructPtr_ ## STRUCT) -#define mSCRIPT_TYPE_MS_PCS(STRUCT) (&mSTStructConstPtr_ ## STRUCT) +#define mSCRIPT_TYPE_MS_PCS(STRUCT) (&mSTStructPtrConst_ ## STRUCT) #define mSCRIPT_TYPE_MS_WSTR (&mSTStringWrapper) #define mSCRIPT_TYPE_MS_WLIST (&mSTListWrapper) #define mSCRIPT_TYPE_MS_W(TYPE) (&mSTWrapper_ ## TYPE) From 0da94526bcaf11f8502b364b5d9feb50b279edff Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 25 Jan 2023 04:10:36 -0800 Subject: [PATCH 05/16] Scripting: Add some nullity tests --- src/script/test/lua.c | 20 +++++++++++++++++ src/script/test/types.c | 49 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/src/script/test/lua.c b/src/script/test/lua.c index 73954e91e..ec478fc3c 100644 --- a/src/script/test/lua.c +++ b/src/script/test/lua.c @@ -371,6 +371,25 @@ M_TEST_DEFINE(callCFunc) { mScriptContextDeinit(&context); } +M_TEST_DEFINE(globalStructNull) { + SETUP_LUA; + + struct Test s = {}; + + struct mScriptValue a; + + LOAD_PROGRAM("assert(a)"); + + a = mSCRIPT_MAKE_S(Test, &s); + assert_true(lua->setGlobal(lua, "a", &a)); + assert_true(lua->run(lua)); + + a = mSCRIPT_MAKE_S(Test, NULL); + assert_true(lua->setGlobal(lua, "a", &a)); + assert_false(lua->run(lua)); + + mScriptContextDeinit(&context); +} M_TEST_DEFINE(globalStructFieldGet) { SETUP_LUA; @@ -709,6 +728,7 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua, cmocka_unit_test(rootScope), cmocka_unit_test(callLuaFunc), cmocka_unit_test(callCFunc), + cmocka_unit_test(globalStructNull), cmocka_unit_test(globalStructFieldGet), cmocka_unit_test(globalStructFieldSet), cmocka_unit_test(globalStructMethods), diff --git a/src/script/test/types.c b/src/script/test/types.c index 6ad38563a..ae1df5ba0 100644 --- a/src/script/test/types.c +++ b/src/script/test/types.c @@ -76,6 +76,14 @@ static int isSequential(struct mScriptList* list) { return true; } +static bool isNullCharp(const char* arg) { + return !arg; +} + +static bool isNullStruct(struct Test* arg) { + return !arg; +} + mSCRIPT_BIND_FUNCTION(boundVoidOne, S32, voidOne, 0); mSCRIPT_BIND_VOID_FUNCTION(boundDiscard, discard, 1, S32, ignored); mSCRIPT_BIND_FUNCTION(boundIdentityInt, S32, identityInt, 1, S32, in); @@ -86,6 +94,8 @@ mSCRIPT_BIND_FUNCTION(boundAddInts, S32, addInts, 2, S32, a, S32, b); mSCRIPT_BIND_FUNCTION(boundSubInts, S32, subInts, 2, S32, a, S32, b); mSCRIPT_BIND_FUNCTION(boundIsHello, S32, isHello, 1, CHARP, str); mSCRIPT_BIND_FUNCTION(boundIsSequential, S32, isSequential, 1, LIST, list); +mSCRIPT_BIND_FUNCTION(boundIsNullCharp, BOOL, isNullCharp, 1, CHARP, arg); +mSCRIPT_BIND_FUNCTION(boundIsNullStruct, BOOL, isNullStruct, 1, S(Test), arg); M_TEST_DEFINE(voidArgs) { struct mScriptFrame frame; @@ -1261,6 +1271,43 @@ M_TEST_DEFINE(invokeList) { mScriptListDeinit(&list); } +M_TEST_DEFINE(nullString) { + struct mScriptFrame frame; + bool res; + mScriptFrameInit(&frame); + + mSCRIPT_PUSH(&frame.arguments, CHARP, "hi"); + assert_true(mScriptInvoke(&boundIsNullCharp, &frame)); + assert_true(mScriptPopBool(&frame.returnValues, &res)); + assert_false(res); + + mSCRIPT_PUSH(&frame.arguments, CHARP, NULL); + assert_true(mScriptInvoke(&boundIsNullCharp, &frame)); + assert_true(mScriptPopBool(&frame.returnValues, &res)); + assert_true(res); + + mScriptFrameDeinit(&frame); +} + +M_TEST_DEFINE(nullStruct) { + struct mScriptFrame frame; + struct Test v = {}; + bool res; + mScriptFrameInit(&frame); + + mSCRIPT_PUSH(&frame.arguments, S(Test), &v); + assert_true(mScriptInvoke(&boundIsNullStruct, &frame)); + assert_true(mScriptPopBool(&frame.returnValues, &res)); + assert_false(res); + + mSCRIPT_PUSH(&frame.arguments, S(Test), NULL); + assert_true(mScriptInvoke(&boundIsNullStruct, &frame)); + assert_true(mScriptPopBool(&frame.returnValues, &res)); + assert_true(res); + + mScriptFrameDeinit(&frame); +} + M_TEST_SUITE_DEFINE(mScript, cmocka_unit_test(voidArgs), cmocka_unit_test(voidFunc), @@ -1295,4 +1342,6 @@ M_TEST_SUITE_DEFINE(mScript, cmocka_unit_test(stringIsHello), cmocka_unit_test(stringIsNotHello), cmocka_unit_test(invokeList), + cmocka_unit_test(nullString), + cmocka_unit_test(nullStruct), ) From e2668c25c5095a5551b536e242d07873a0af6af8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 25 Jan 2023 04:17:38 -0800 Subject: [PATCH 06/16] Qt: Set default gamepad and sensor drivers --- src/platform/qt/Window.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index c07d82704..7e25159eb 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -176,6 +176,8 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi #ifdef BUILD_SDL m_inputController.addInputDriver(std::make_shared(&m_inputController)); + m_inputController.setGamepadDriver(SDL_BINDING_BUTTON); + m_inputController.setSensorDriver(SDL_BINDING_BUTTON); #endif m_shortcutController->setConfigController(m_config); From dfd772d2ca9b9199cb72f3b3db29648ce396039b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 25 Jan 2023 04:19:12 -0800 Subject: [PATCH 07/16] Scripting: Add missing type export --- include/mgba/script/types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mgba/script/types.h b/include/mgba/script/types.h index 3099540dc..556fff57b 100644 --- a/include/mgba/script/types.h +++ b/include/mgba/script/types.h @@ -76,6 +76,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_FIELD_W(TYPE) opaque #define mSCRIPT_TYPE_FIELD_CW(TYPE) opaque +#define mSCRIPT_TYPE_MS_VOID (&mSTVoid) #define mSCRIPT_TYPE_MS_S8 (&mSTSInt8) #define mSCRIPT_TYPE_MS_U8 (&mSTUInt8) #define mSCRIPT_TYPE_MS_S16 (&mSTSInt16) From 17ef84804bd0e43319935104e2c7c85b3a459060 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 25 Jan 2023 04:47:15 -0800 Subject: [PATCH 08/16] Scripting: Lua nullity fixes --- src/script/engines/lua.c | 18 +++++++++++++++++- src/script/test/lua.c | 14 +++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index 37327ee54..3c7266a2a 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -738,7 +738,19 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v } break; case mSCRIPT_TYPE_STRING: - lua_pushlstring(luaContext->lua, value->value.string->buffer, value->value.string->size); + if (!value->value.string) { + lua_pushnil(luaContext->lua); + break; + } + if (value->type == mSCRIPT_TYPE_MS_STR) { + lua_pushlstring(luaContext->lua, value->value.string->buffer, value->value.string->size); + break; + } + if (value->type == mSCRIPT_TYPE_MS_CHARP) { + lua_pushstring(luaContext->lua, value->value.copaque); + break; + } + ok = false; break; case mSCRIPT_TYPE_LIST: newValue = lua_newuserdata(luaContext->lua, sizeof(*newValue)); @@ -769,6 +781,10 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v mScriptValueDeref(value); break; case mSCRIPT_TYPE_OBJECT: + if (!value->value.opaque) { + lua_pushnil(luaContext->lua); + break; + } newValue = lua_newuserdata(luaContext->lua, sizeof(*newValue)); if (needsWeakref) { *newValue = mSCRIPT_MAKE(WEAKREF, weakref); diff --git a/src/script/test/lua.c b/src/script/test/lua.c index ec478fc3c..2c047ec39 100644 --- a/src/script/test/lua.c +++ b/src/script/test/lua.c @@ -371,15 +371,23 @@ M_TEST_DEFINE(callCFunc) { mScriptContextDeinit(&context); } -M_TEST_DEFINE(globalStructNull) { +M_TEST_DEFINE(globalNull) { SETUP_LUA; struct Test s = {}; - + struct mScriptValue* val; struct mScriptValue a; LOAD_PROGRAM("assert(a)"); + a = mSCRIPT_MAKE_CHARP("hello"); + assert_true(lua->setGlobal(lua, "a", &a)); + assert_true(lua->run(lua)); + + a = mSCRIPT_MAKE_CHARP(NULL); + assert_true(lua->setGlobal(lua, "a", &a)); + assert_false(lua->run(lua)); + a = mSCRIPT_MAKE_S(Test, &s); assert_true(lua->setGlobal(lua, "a", &a)); assert_true(lua->run(lua)); @@ -728,7 +736,7 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua, cmocka_unit_test(rootScope), cmocka_unit_test(callLuaFunc), cmocka_unit_test(callCFunc), - cmocka_unit_test(globalStructNull), + cmocka_unit_test(globalNull), cmocka_unit_test(globalStructFieldGet), cmocka_unit_test(globalStructFieldSet), cmocka_unit_test(globalStructMethods), From 5216383c28332cbed2cfe962ce9c8be5daff8595 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 25 Jan 2023 21:52:23 -0800 Subject: [PATCH 09/16] Scripting: Fix scripting console --- src/core/scripting.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/core/scripting.c b/src/core/scripting.c index 05433b747..1eca1159b 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -761,14 +761,16 @@ mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mScriptConsole, createBuffer) mSCRIPT_DEFINE_DEFAULTS_END; static struct mScriptConsole* _ensureConsole(struct mScriptContext* context) { - struct mScriptValue* value = mScriptContextEnsureGlobal(context, "console", mSCRIPT_TYPE_MS_S(mScriptConsole)); - struct mScriptConsole* console = value->value.opaque; - if (!console) { - console = calloc(1, sizeof(*console)); - value->value.opaque = console; - value->flags = mSCRIPT_VALUE_FLAG_FREE_BUFFER; - mScriptContextSetDocstring(context, "console", "Singleton instance of struct::mScriptConsole"); + struct mScriptValue* value = mScriptContextGetGlobal(context, "console"); + if (value) { + return value->value.opaque; } + struct mScriptConsole* console = calloc(1, sizeof(*console)); + value = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mScriptConsole)); + value->value.opaque = console; + value->flags = mSCRIPT_VALUE_FLAG_FREE_BUFFER; + mScriptContextSetGlobal(context, "console", value); + mScriptContextSetDocstring(context, "console", "Singleton instance of struct::mScriptConsole"); return console; } From 58089fb334bfdbc6ce2e0ff77eeb321623460cf3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 26 Jan 2023 03:25:51 -0800 Subject: [PATCH 10/16] Scripting: Allow mScriptList members, better testing --- src/script/test/classes.c | 50 +++++++++++++++++++++++++++++++++++++++ src/script/types.c | 6 +++++ 2 files changed, 56 insertions(+) diff --git a/src/script/test/classes.c b/src/script/test/classes.c index 476e24455..95bb32920 100644 --- a/src/script/test/classes.c +++ b/src/script/test/classes.c @@ -14,6 +14,8 @@ struct TestA { int32_t i2; int8_t b8; int16_t hUnaligned; + struct mScriptValue table; + struct mScriptList list; int32_t (*ifn0)(struct TestA*); int32_t (*ifn1)(struct TestA*, int); void (*vfn0)(struct TestA*); @@ -103,6 +105,8 @@ mSCRIPT_DEFINE_STRUCT(TestA) mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, S32, i2) mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, S8, b8) mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, S16, hUnaligned) + mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, TABLE, table) + mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, LIST, list) mSCRIPT_DEFINE_STRUCT_METHOD(TestA, ifn0) mSCRIPT_DEFINE_STRUCT_METHOD(TestA, ifn1) mSCRIPT_DEFINE_STRUCT_METHOD(TestA, icfn0) @@ -187,6 +191,20 @@ M_TEST_DEFINE(testALayout) { assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_S16); assert_int_not_equal(member->offset, sizeof(int32_t) * 2 + 1); + member = HashTableLookup(&cls->instanceMembers, "table"); + assert_non_null(member); + assert_string_equal(member->name, "table"); + assert_null(member->docstring); + assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_TABLE); + assert_int_equal(member->offset, &((struct TestA*) 0)->table); + + member = HashTableLookup(&cls->instanceMembers, "list"); + assert_non_null(member); + assert_string_equal(member->name, "list"); + assert_null(member->docstring); + assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_LIST); + assert_int_equal(member->offset, &((struct TestA*) 0)->list); + member = HashTableLookup(&cls->instanceMembers, "unknown"); assert_null(member); @@ -280,6 +298,12 @@ M_TEST_DEFINE(testAGet) { .hUnaligned = 4 }; + mScriptListInit(&s.list, 1); + *mScriptListAppend(&s.list) = mSCRIPT_MAKE_S32(5); + + s.table.type = mSCRIPT_TYPE_MS_TABLE; + s.table.type->alloc(&s.table); + struct mScriptValue sval = mSCRIPT_MAKE_S(TestA, &s); struct mScriptValue val; struct mScriptValue compare; @@ -300,8 +324,34 @@ M_TEST_DEFINE(testAGet) { assert_true(mScriptObjectGet(&sval, "hUnaligned", &val)); assert_true(compare.type->equal(&compare, &val)); + compare = mSCRIPT_MAKE_S32(5); + assert_true(mScriptObjectGet(&sval, "list", &val)); + assert_ptr_equal(val.type, mSCRIPT_TYPE_MS_LIST); + assert_int_equal(mScriptListSize(val.value.list), 1); + assert_true(compare.type->equal(&compare, mScriptListGetPointer(val.value.list, 0))); + + *mScriptListAppend(&s.list) = mSCRIPT_MAKE_S32(6); + compare = mSCRIPT_MAKE_S32(6); + assert_int_equal(mScriptListSize(val.value.list), 2); + assert_true(compare.type->equal(&compare, mScriptListGetPointer(val.value.list, 1))); + + struct mScriptValue* ival = &val; + assert_true(mScriptObjectGet(&sval, "table", &val)); + if (val.type->base == mSCRIPT_TYPE_WRAPPER) { + ival = mScriptValueUnwrap(&val); + } + assert_ptr_equal(ival->type, mSCRIPT_TYPE_MS_TABLE); + assert_int_equal(mScriptTableSize(ival), 0); + compare = mSCRIPT_MAKE_S32(7); + mScriptTableInsert(&s.table, &compare, &compare); + assert_int_equal(mScriptTableSize(&s.table), 1); + assert_int_equal(mScriptTableSize(ival), 1); + assert_false(mScriptObjectGet(&sval, "unknown", &val)); + mScriptListDeinit(&s.list); + mSCRIPT_TYPE_MS_TABLE->free(&s.table); + assert_true(cls->init); mScriptClassDeinit(cls); assert_false(cls->init); diff --git a/src/script/types.c b/src/script/types.c index b63fed4a5..dc9153587 100644 --- a/src/script/types.c +++ b/src/script/types.c @@ -1178,6 +1178,12 @@ static bool _accessRawMember(struct mScriptClassMember* member, void* raw, bool val->type = mSCRIPT_TYPE_MS_WRAPPER; val->value.table = raw; break; + case mSCRIPT_TYPE_LIST: + val->refs = mSCRIPT_VALUE_UNREF; + val->flags = 0; + val->type = mSCRIPT_TYPE_MS_LIST; + val->value.list = raw; + break; case mSCRIPT_TYPE_FUNCTION: val->refs = mSCRIPT_VALUE_UNREF; val->flags = 0; From b5f600c0c5bb411b9d31739b6725147932296e02 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 26 Jan 2023 03:29:55 -0800 Subject: [PATCH 11/16] Scripting: Allow weakrefs to be marked for auto-collection --- include/mgba/script/context.h | 1 + src/script/CMakeLists.txt | 5 +- src/script/context.c | 16 +++++- src/script/test/context.c | 103 ++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 src/script/test/context.c diff --git a/include/mgba/script/context.h b/include/mgba/script/context.h index 99eefe069..396084f14 100644 --- a/include/mgba/script/context.h +++ b/include/mgba/script/context.h @@ -89,6 +89,7 @@ uint32_t mScriptContextSetWeakref(struct mScriptContext*, struct mScriptValue* v struct mScriptValue* mScriptContextMakeWeakref(struct mScriptContext*, struct mScriptValue* value); struct mScriptValue* mScriptContextAccessWeakref(struct mScriptContext*, struct mScriptValue* value); void mScriptContextClearWeakref(struct mScriptContext*, uint32_t weakref); +void mScriptContextDisownWeakref(struct mScriptContext*, uint32_t weakref); void mScriptContextAttachStdlib(struct mScriptContext* context); void mScriptContextAttachSocket(struct mScriptContext* context); diff --git a/src/script/CMakeLists.txt b/src/script/CMakeLists.txt index 5cfb4ff41..504736f2f 100644 --- a/src/script/CMakeLists.txt +++ b/src/script/CMakeLists.txt @@ -12,8 +12,9 @@ set(TEST_FILES if(USE_LUA) list(APPEND SOURCE_FILES engines/lua.c) list(APPEND TEST_FILES - test/stdlib.c - test/lua.c) + test/context.c + test/lua.c + test/stdlib.c) endif() source_group("Scripting" FILES ${SOURCE_FILES}) diff --git a/src/script/context.c b/src/script/context.c index fa1a0b4a2..14775b05c 100644 --- a/src/script/context.c +++ b/src/script/context.c @@ -71,8 +71,8 @@ void mScriptContextInit(struct mScriptContext* context) { void mScriptContextDeinit(struct mScriptContext* context) { HashTableDeinit(&context->rootScope); - HashTableDeinit(&context->weakrefs); mScriptContextDrainPool(context); + HashTableDeinit(&context->weakrefs); mScriptListDeinit(&context->refPool); HashTableDeinit(&context->callbacks); TableDeinit(&context->callbackId); @@ -102,9 +102,12 @@ void mScriptContextFillPool(struct mScriptContext* context, struct mScriptValue* void mScriptContextDrainPool(struct mScriptContext* context) { size_t i; for (i = 0; i < mScriptListSize(&context->refPool); ++i) { - struct mScriptValue* value = mScriptValueUnwrap(mScriptListGetPointer(&context->refPool, i)); - if (value) { + struct mScriptValue* value = mScriptListGetPointer(&context->refPool, i); + if (value->type->base == mSCRIPT_TYPE_WRAPPER) { + value = mScriptValueUnwrap(value); mScriptValueDeref(value); + } else if (value->type == mSCRIPT_TYPE_MS_WEAKREF) { + mScriptContextClearWeakref(context, value->value.u32); } } mScriptListClear(&context->refPool); @@ -201,6 +204,13 @@ void mScriptContextClearWeakref(struct mScriptContext* context, uint32_t weakref TableRemove(&context->weakrefs, weakref); } +void mScriptContextDisownWeakref(struct mScriptContext* context, uint32_t weakref) { + struct mScriptValue* poolEntry = mScriptListAppend(&context->refPool); + poolEntry->type = mSCRIPT_TYPE_MS_WEAKREF; + poolEntry->value.u32 = weakref; + poolEntry->refs = mSCRIPT_VALUE_UNREF; +} + void mScriptContextTriggerCallback(struct mScriptContext* context, const char* callback) { struct mScriptValue* list = HashTableLookup(&context->callbacks, callback); if (!list) { diff --git a/src/script/test/context.c b/src/script/test/context.c new file mode 100644 index 000000000..178dc25a7 --- /dev/null +++ b/src/script/test/context.c @@ -0,0 +1,103 @@ +/* Copyright (c) 2013-2023 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/. */ +#include "util/test/suite.h" + +#include +#include +#include + +M_TEST_DEFINE(weakrefBasic) { + struct mScriptContext context; + mScriptContextInit(&context); + + struct mScriptValue weakref = mSCRIPT_VAL(WEAKREF, 1); + struct mScriptValue fakeVal = mSCRIPT_S32(0x7E57CA5E); + struct mScriptValue* val; + + assert_int_equal(TableSize(&context.weakrefs), 0); + assert_null(TableLookup(&context.weakrefs, 1)); + assert_int_equal(context.nextWeakref, 1); + assert_null(mScriptContextAccessWeakref(&context, &weakref)); + + assert_int_equal(mScriptContextSetWeakref(&context, &fakeVal), 1); + assert_int_equal(context.nextWeakref, 2); + assert_int_equal(TableSize(&context.weakrefs), 1); + val = mScriptContextAccessWeakref(&context, &weakref); + assert_non_null(val); + assert_int_equal(val->value.u32, 0x7E57CA5E); + + mScriptContextClearWeakref(&context, 1); + + assert_int_equal(TableSize(&context.weakrefs), 0); + assert_null(TableLookup(&context.weakrefs, 1)); + assert_int_equal(context.nextWeakref, 2); + assert_null(mScriptContextAccessWeakref(&context, &weakref)); + + mScriptContextDeinit(&context); +} + +M_TEST_DEFINE(drainPool) { + struct mScriptContext context; + mScriptContextInit(&context); + + assert_int_equal(mScriptListSize(&context.refPool), 0); + + struct mScriptValue fakeVal = mSCRIPT_CHARP("foo"); + fakeVal.refs = 2; + + mScriptContextFillPool(&context, &fakeVal); + assert_int_equal(mScriptListSize(&context.refPool), 1); + assert_int_equal(fakeVal.refs, 2); + + mScriptContextDrainPool(&context); + assert_int_equal(mScriptListSize(&context.refPool), 0); + assert_int_equal(fakeVal.refs, 1); + + mScriptContextDeinit(&context); +} + +M_TEST_DEFINE(disownWeakref) { + struct mScriptContext context; + mScriptContextInit(&context); + + struct mScriptValue weakref = mSCRIPT_VAL(WEAKREF, 1); + struct mScriptValue fakeVal = mSCRIPT_S32(0x7E57CA5E); + struct mScriptValue* val; + + assert_int_equal(mScriptListSize(&context.refPool), 0); + assert_int_equal(TableSize(&context.weakrefs), 0); + assert_null(TableLookup(&context.weakrefs, 1)); + assert_int_equal(context.nextWeakref, 1); + assert_null(mScriptContextAccessWeakref(&context, &weakref)); + + assert_int_equal(mScriptContextSetWeakref(&context, &fakeVal), 1); + assert_int_equal(TableSize(&context.weakrefs), 1); + assert_int_equal(context.nextWeakref, 2); + val = mScriptContextAccessWeakref(&context, &weakref); + assert_non_null(val); + assert_int_equal(val->value.u32, 0x7E57CA5E); + + mScriptContextDisownWeakref(&context, 1); + assert_int_equal(mScriptListSize(&context.refPool), 1); + assert_int_equal(TableSize(&context.weakrefs), 1); + val = mScriptContextAccessWeakref(&context, &weakref); + assert_non_null(val); + assert_int_equal(val->value.u32, 0x7E57CA5E); + + mScriptContextDrainPool(&context); + assert_int_equal(mScriptListSize(&context.refPool), 0); + assert_int_equal(TableSize(&context.weakrefs), 0); + assert_null(TableLookup(&context.weakrefs, 1)); + assert_null(mScriptContextAccessWeakref(&context, &weakref)); + + mScriptContextDeinit(&context); +} + +M_TEST_SUITE_DEFINE(mScript, + cmocka_unit_test(weakrefBasic), + cmocka_unit_test(drainPool), + cmocka_unit_test(disownWeakref), +) From c4157e59fc960c170fa116f7d4a70d8731d10a13 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 26 Jan 2023 04:05:23 -0800 Subject: [PATCH 12/16] Qt: Fix gamepad driver lookup --- src/platform/qt/InputController.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/InputController.h b/src/platform/qt/InputController.h index e974c1aaa..16670d267 100644 --- a/src/platform/qt/InputController.h +++ b/src/platform/qt/InputController.h @@ -74,8 +74,8 @@ public: static const int32_t AXIS_THRESHOLD = 0x3000; void setGamepadDriver(uint32_t type); - const InputDriver* gamepadDriver() const { return m_inputDrivers.value(m_sensorDriver).get(); } - InputDriver* gamepadDriver() { return m_inputDrivers.value(m_sensorDriver).get(); } + const InputDriver* gamepadDriver() const { return m_inputDrivers.value(m_gamepadDriver).get(); } + InputDriver* gamepadDriver() { return m_inputDrivers.value(m_gamepadDriver).get(); } QStringList connectedGamepads(uint32_t type = 0) const; int gamepadIndex(uint32_t type = 0) const; From 8e671b083029f4afcc1d8927556b2619ee752c2b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 26 Jan 2023 05:57:08 -0800 Subject: [PATCH 13/16] Qt: Fix crash when attempting to use OpenGL 2.1 to 3.1 (fixes #2794) --- CHANGES | 2 ++ src/platform/qt/DisplayGL.cpp | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 637fdf28f..ddbff820a 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,8 @@ Features: Emulation fixes: - GBA Memory: Make VRAM access stalls only apply to BG RAM - GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722) +Other fixes: + - Qt: Fix crash when attempting to use OpenGL 2.1 to 3.1 (fixes mgba.io/i/2794) Misc: - GB Serialize: Add missing savestate support for MBC6 and NT (newer) - GBA: Improve detection of valid ELF ROMs diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 7a4f73858..469b7e315 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -513,10 +513,10 @@ void PainterGL::create() { #if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (m_supportsShaders) { - QOpenGLFunctions_Baseline* fn = m_gl->versionFunctions(); gl2Backend = static_cast(malloc(sizeof(mGLES2Context))); mGLES2ContextCreate(gl2Backend); m_backend = &gl2Backend->d; + QOpenGLFunctions* fn = m_gl->functions(); fn->glGenTextures(m_bridgeTexes.size(), m_bridgeTexes.data()); for (auto tex : m_bridgeTexes) { m_freeTex.enqueue(tex); @@ -543,7 +543,7 @@ void PainterGL::create() { #if defined(BUILD_GLES2) || defined(BUILD_GLES3) mGLES2Context* gl2Backend = reinterpret_cast(painter->m_backend); if (painter->m_widget && painter->supportsShaders()) { - QOpenGLFunctions_Baseline* fn = painter->m_gl->versionFunctions(); + QOpenGLFunctions* fn = painter->m_gl->functions(); fn->glFinish(); painter->m_widget->setTex(painter->m_finalTex[painter->m_finalTexIdx]); painter->m_finalTexIdx ^= 1; @@ -589,7 +589,7 @@ void PainterGL::destroy() { } makeCurrent(); #if defined(BUILD_GLES2) || defined(BUILD_GLES3) - QOpenGLFunctions_Baseline* fn = m_gl->versionFunctions(); + QOpenGLFunctions* fn = m_gl->functions(); if (m_shader.passes) { mGLES2ShaderFree(&m_shader); } @@ -680,7 +680,7 @@ void PainterGL::start() { if (glContextHasBug(OpenGLBug::GLTHREAD_BLOCKS_SWAP)) { // Suggested on Discord as a way to strongly hint that glthread should be disabled // See https://gitlab.freedesktop.org/mesa/mesa/-/issues/8035 - QOpenGLFunctions_Baseline* fn = m_gl->versionFunctions(); + QOpenGLFunctions* fn = m_gl->functions(); fn->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); } #endif @@ -972,7 +972,7 @@ QOpenGLContext* PainterGL::shareContext() { } void PainterGL::updateFramebufferHandle() { - QOpenGLFunctions_Baseline* fn = m_gl->versionFunctions(); + QOpenGLFunctions* fn = m_gl->functions(); // TODO: Figure out why glFlush doesn't work here on Intel/Windows if (glContextHasBug(OpenGLBug::CROSS_THREAD_FLUSH)) { fn->glFinish(); From 1dedd1d7a7514c11ad461e3ef14bb31a6a8eee37 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 26 Jan 2023 07:17:53 -0800 Subject: [PATCH 14/16] Qt: Include wayland QPA in AppImage (fixes #2796) --- CHANGES | 1 + src/platform/qt/CMakeLists.txt | 2 +- src/platform/qt/main.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index ddbff820a..4803ef370 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,7 @@ Other fixes: Misc: - GB Serialize: Add missing savestate support for MBC6 and NT (newer) - GBA: Improve detection of valid ELF ROMs + - Qt: Include wayland QPA in AppImage (fixes mgba.io/i/2796) 0.10.1: (2023-01-10) Emulation fixes: diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 327309acf..7bd8e095b 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -426,7 +426,7 @@ if(QT_STATIC) list(APPEND QT_LIBRARIES "-framework AVFoundation" "-framework CoreMedia" "-framework SystemConfiguration" "-framework Security") set_target_properties(${QT}::Core PROPERTIES INTERFACE_LINK_LIBRARIES "${QTPCRE}") elseif(UNIX) - list(APPEND QT_LIBRARIES ${QT}::FontDatabaseSupport ${QT}::XcbQpa) + list(APPEND QT_LIBRARIES ${QT}::FontDatabaseSupport ${QT}::XcbQpa ${QT}::QWaylandIntegrationPlugin) endif() endif() target_link_libraries(${BINARY_NAME}-qt ${PLATFORM_LIBRARY} ${BINARY_NAME} ${QT_LIBRARIES}) diff --git a/src/platform/qt/main.cpp b/src/platform/qt/main.cpp index b3d4bafc9..c53408e8e 100644 --- a/src/platform/qt/main.cpp +++ b/src/platform/qt/main.cpp @@ -42,6 +42,7 @@ Q_IMPORT_PLUGIN(AVFServicePlugin); #endif #elif defined(Q_OS_UNIX) Q_IMPORT_PLUGIN(QXcbIntegrationPlugin); +Q_IMPORT_PLUGIN(QWaylandIntegrationPlugin); #endif #endif From 0cfec878c8f706cdc9709cd581a0d7dbfa29cdee Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 26 Jan 2023 15:32:00 -0800 Subject: [PATCH 15/16] Qt: mInputMapHat returns a mask, not a single key (fixes #2800) --- src/platform/qt/input/InputMapper.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/platform/qt/input/InputMapper.cpp b/src/platform/qt/input/InputMapper.cpp index 41a3bc8c3..c84316efd 100644 --- a/src/platform/qt/input/InputMapper.cpp +++ b/src/platform/qt/input/InputMapper.cpp @@ -66,10 +66,7 @@ int InputMapper::mapAxes(QList axes) const { int InputMapper::mapHats(QList hats) const { int platformKeys = 0; for (int i = 0; i < hats.count(); ++i) { - int platformKey = mInputMapHat(m_map, m_type, i, hats[i]); - if (platformKey >= 0) { - platformKeys |= 1 << platformKey; - } + platformKeys |= mInputMapHat(m_map, m_type, i, hats[i]); } return platformKeys; } From 6b63e42146bf8d29cc88fdc7a145dcf7f515626b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 26 Jan 2023 16:18:10 -0800 Subject: [PATCH 16/16] Qt: These return multiple keys --- src/platform/qt/InputController.cpp | 22 +++++++++++++++++++--- src/platform/qt/InputController.h | 8 +++++--- src/platform/qt/input/GamepadHatEvent.cpp | 4 ++-- src/platform/qt/input/GamepadHatEvent.h | 4 ++-- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index e6e741a56..f036d6f52 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -495,15 +495,15 @@ void InputController::testGamepad(uint32_t type) { for (auto& hat : activeHats) { GamepadHatEvent* event = new GamepadHatEvent(GamepadHatEvent::Down(), hat.first, hat.second, type, this); - postPendingEvent(event->platformKey()); + postPendingEvents(event->platformKeys()); sendGamepadEvent(event); if (!event->isAccepted()) { - clearPendingEvent(event->platformKey()); + clearPendingEvents(event->platformKeys()); } } for (auto& hat : oldHats) { GamepadHatEvent* event = new GamepadHatEvent(GamepadHatEvent::Up(), hat.first, hat.second, type, this); - clearPendingEvent(event->platformKey()); + clearPendingEvents(event->platformKeys()); sendGamepadEvent(event); } } @@ -529,6 +529,22 @@ void InputController::clearPendingEvent(int key) { m_pendingEvents.remove(key); } +void InputController::postPendingEvents(int keys) { + for (int i = 0; keys; ++i, keys >>= 1) { + if (keys & 1) { + m_pendingEvents.insert(i); + } + } +} + +void InputController::clearPendingEvents(int keys) { + for (int i = 0; keys; ++i, keys >>= 1) { + if (keys & 1) { + m_pendingEvents.remove(i); + } + } +} + bool InputController::hasPendingEvent(int key) const { return m_pendingEvents.contains(key); } diff --git a/src/platform/qt/InputController.h b/src/platform/qt/InputController.h index 16670d267..d74cd3148 100644 --- a/src/platform/qt/InputController.h +++ b/src/platform/qt/InputController.h @@ -128,9 +128,11 @@ private slots: void teardownCam(); private: - void postPendingEvent(int); - void clearPendingEvent(int); - bool hasPendingEvent(int) const; + void postPendingEvent(int key); + void clearPendingEvent(int key); + void postPendingEvents(int keys); + void clearPendingEvents(int keys); + bool hasPendingEvent(int key) const; void sendGamepadEvent(QEvent*); Gamepad* gamepad(uint32_t type); diff --git a/src/platform/qt/input/GamepadHatEvent.cpp b/src/platform/qt/input/GamepadHatEvent.cpp index 1ca0408b0..25033997f 100644 --- a/src/platform/qt/input/GamepadHatEvent.cpp +++ b/src/platform/qt/input/GamepadHatEvent.cpp @@ -16,11 +16,11 @@ GamepadHatEvent::GamepadHatEvent(QEvent::Type pressType, int hatId, Direction di : QEvent(pressType) , m_hatId(hatId) , m_direction(direction) - , m_key(-1) + , m_keys(0) { ignore(); if (controller) { - m_key = mInputMapHat(controller->map(), type, hatId, direction); + m_keys = mInputMapHat(controller->map(), type, hatId, direction); } } diff --git a/src/platform/qt/input/GamepadHatEvent.h b/src/platform/qt/input/GamepadHatEvent.h index 2ba73088d..c6c49fe3c 100644 --- a/src/platform/qt/input/GamepadHatEvent.h +++ b/src/platform/qt/input/GamepadHatEvent.h @@ -25,7 +25,7 @@ public: int hatId() const { return m_hatId; } Direction direction() const { return m_direction; } - int platformKey() const { return m_key; } + int platformKeys() const { return m_keys; } static Type Down(); static Type Up(); @@ -36,7 +36,7 @@ private: int m_hatId; Direction m_direction; - int m_key; + int m_keys; }; }