mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
295966ab50
4
CHANGES
4
CHANGES
|
@ -46,6 +46,7 @@ Features:
|
|||
- New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81
|
||||
- Debugger: Add range watchpoints
|
||||
Emulation fixes:
|
||||
- GB Video: Implement DMG-style sprite ordering
|
||||
- GBA Audio: Fix improperly deserializing GB audio registers (fixes mgba.io/i/2793)
|
||||
- GBA Memory: Make VRAM access stalls only apply to BG RAM
|
||||
- GBA SIO: Fix SIOCNT SI pin value after attaching player 2 (fixes mgba.io/i/2805)
|
||||
|
@ -62,6 +63,9 @@ Other fixes:
|
|||
- Qt: Disable attempted linking betwen incompatible platforms (fixes mgba.io/i/2702)
|
||||
- Qt: Fix modifier key names in shortcut editor (fixes mgba.io/i/2817)
|
||||
- Qt: Fix a handful of edge cases with graphics viewers (fixes mgba.io/i/2827)
|
||||
- Qt: Fix full-buffer rewind
|
||||
- Qt: Fix crash if loading a shader fails
|
||||
- Qt: Fix black screen when starting with a game (fixes mgba.io/i/2781)
|
||||
- Scripting: Fix receiving packets for client sockets
|
||||
- Scripting: Fix empty receive calls returning unknown error on Windows
|
||||
Misc:
|
||||
|
|
|
@ -34,7 +34,7 @@ if(NOT MSVC)
|
|||
set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-format")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=implicit-function-declaration -Werror=implicit-int")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -Woverloaded-virtual")
|
||||
else()
|
||||
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-")
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
[testinfo]
|
||||
skip=15
|
||||
frames=1
|
||||
|
||||
[ports.cinema]
|
||||
sgb.borders=0
|
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 702 B After Width: | Height: | Size: 703 B |
Binary file not shown.
Before Width: | Height: | Size: 711 B |
|
@ -27,6 +27,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct option;
|
||||
|
||||
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
|
||||
|
||||
#ifdef REPLACE_GETOPT
|
||||
|
|
|
@ -204,6 +204,7 @@ static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress)
|
|||
err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
|
||||
#endif
|
||||
if (err) {
|
||||
SocketCloseQuiet(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
|
|
@ -489,8 +489,10 @@ bool mCheatParseEZFChtFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
return false;
|
||||
}
|
||||
char* name = gbkToUtf8(&cheat[1], end - cheat - 1);
|
||||
strncpy(cheatName, name, sizeof(cheatName) - 1);
|
||||
free(name);
|
||||
if (name) {
|
||||
strncpy(cheatName, name, sizeof(cheatName) - 1);
|
||||
free(name);
|
||||
}
|
||||
cheatNameLength = strlen(cheatName);
|
||||
continue;
|
||||
}
|
||||
|
@ -501,7 +503,10 @@ bool mCheatParseEZFChtFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
}
|
||||
if (strncmp(cheat, "ON", eq - cheat) != 0) {
|
||||
char* subname = gbkToUtf8(cheat, eq - cheat);
|
||||
snprintf(&cheatName[cheatNameLength], sizeof(cheatName) - cheatNameLength - 1, ": %s", subname);
|
||||
if (subname) {
|
||||
snprintf(&cheatName[cheatNameLength], sizeof(cheatName) - cheatNameLength - 1, ": %s", subname);
|
||||
free(subname);
|
||||
}
|
||||
}
|
||||
set = device->createSet(device, cheatName);
|
||||
set->enabled = false;
|
||||
|
|
|
@ -169,14 +169,14 @@ void mCoreConfigDeinit(struct mCoreConfig* config) {
|
|||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
bool mCoreConfigLoad(struct mCoreConfig* config) {
|
||||
char path[PATH_MAX];
|
||||
char path[PATH_MAX + 1];
|
||||
mCoreConfigDirectory(path, PATH_MAX);
|
||||
strncat(path, PATH_SEP "config.ini", PATH_MAX - strlen(path));
|
||||
return mCoreConfigLoadPath(config, path);
|
||||
}
|
||||
|
||||
bool mCoreConfigSave(const struct mCoreConfig* config) {
|
||||
char path[PATH_MAX];
|
||||
char path[PATH_MAX + 1];
|
||||
mCoreConfigDirectory(path, PATH_MAX);
|
||||
strncat(path, PATH_SEP "config.ini", PATH_MAX - strlen(path));
|
||||
return mCoreConfigSavePath(config, path);
|
||||
|
@ -304,7 +304,7 @@ void mCoreConfigPortablePath(char* out, size_t outLength) {
|
|||
CFRelease(suburl);
|
||||
}
|
||||
#endif
|
||||
strncat(out, PATH_SEP "portable.ini", outLength - strlen(out));
|
||||
strncat(out, PATH_SEP "portable.ini", outLength - strlen(out) - 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ const char* mLogCategoryName(int category) {
|
|||
}
|
||||
|
||||
const char* mLogCategoryId(int category) {
|
||||
if (category < MAX_CATEGORY) {
|
||||
if (category >= 0 && category < MAX_CATEGORY) {
|
||||
return _categoryIds[category];
|
||||
}
|
||||
return NULL;
|
||||
|
@ -88,6 +88,7 @@ void mLogExplicit(struct mLogger* context, int category, enum mLogLevel level, c
|
|||
if (!context->filter || mLogFilterTest(context->filter, category, level)) {
|
||||
context->log(context, category, level, format, args);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void mLogFilterInit(struct mLogFilter* filter) {
|
||||
|
|
|
@ -846,6 +846,7 @@ void GDBStubUpdate(struct GDBStub* stub) {
|
|||
} else {
|
||||
goto connectionLost;
|
||||
}
|
||||
SocketSetTCPPush(stub->connection, 1);
|
||||
}
|
||||
while (true) {
|
||||
if (stub->shouldBlock) {
|
||||
|
|
|
@ -17,7 +17,7 @@ struct NoIntroDB {
|
|||
};
|
||||
|
||||
struct NoIntroDB* NoIntroDBLoad(const char* path) {
|
||||
struct NoIntroDB* db = malloc(sizeof(*db));
|
||||
struct NoIntroDB* db = calloc(1, sizeof(*db));
|
||||
|
||||
if (sqlite3_open_v2(path, &db->db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL)) {
|
||||
goto error;
|
||||
|
@ -60,9 +60,6 @@ struct NoIntroDB* NoIntroDBLoad(const char* path) {
|
|||
return db;
|
||||
|
||||
error:
|
||||
if (db->crc32) {
|
||||
sqlite3_finalize(db->crc32);
|
||||
}
|
||||
NoIntroDBDestroy(db);
|
||||
return NULL;
|
||||
|
||||
|
@ -285,8 +282,12 @@ bool NoIntroDBLoadClrMamePro(struct NoIntroDB* db, struct VFile* vf) {
|
|||
}
|
||||
|
||||
void NoIntroDBDestroy(struct NoIntroDB* db) {
|
||||
sqlite3_finalize(db->crc32);
|
||||
sqlite3_close(db->db);
|
||||
if (db->crc32) {
|
||||
sqlite3_finalize(db->crc32);
|
||||
}
|
||||
if (db->db) {
|
||||
sqlite3_close(db->db);
|
||||
}
|
||||
free(db);
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ int main(int argc, char* argv[]) {
|
|||
int ok = 1;
|
||||
|
||||
mCoreConfigDirectory(bin, sizeof(bin));
|
||||
strncat(bin, "/updater.log", sizeof(bin));
|
||||
strncat(bin, "/updater.log", sizeof(bin) - 1);
|
||||
logfile = fopen(bin, "w");
|
||||
|
||||
mCoreConfigInit(&config, "updater");
|
||||
|
|
|
@ -382,10 +382,7 @@ static void _copyVf(struct VFile* dest, struct VFile* src) {
|
|||
static void _compress(struct VFile* dest, struct VFile* src) {
|
||||
uint8_t writeBuffer[0x800];
|
||||
uint8_t compressBuffer[0x400];
|
||||
z_stream zstr;
|
||||
zstr.zalloc = Z_NULL;
|
||||
zstr.zfree = Z_NULL;
|
||||
zstr.opaque = Z_NULL;
|
||||
z_stream zstr = {0};
|
||||
zstr.avail_in = 0;
|
||||
zstr.avail_out = sizeof(compressBuffer);
|
||||
zstr.next_out = (Bytef*) compressBuffer;
|
||||
|
@ -425,10 +422,7 @@ static void _compress(struct VFile* dest, struct VFile* src) {
|
|||
static bool _decompress(struct VFile* dest, struct VFile* src, size_t compressedLength) {
|
||||
uint8_t fbuffer[0x400];
|
||||
uint8_t zbuffer[0x800];
|
||||
z_stream zstr;
|
||||
zstr.zalloc = Z_NULL;
|
||||
zstr.zfree = Z_NULL;
|
||||
zstr.opaque = Z_NULL;
|
||||
z_stream zstr = {0};
|
||||
zstr.avail_in = 0;
|
||||
zstr.avail_out = sizeof(zbuffer);
|
||||
zstr.next_out = (Bytef*) zbuffer;
|
||||
|
|
|
@ -619,16 +619,16 @@ static void _GBCoreReset(struct mCore* core) {
|
|||
switch (gb->model) {
|
||||
case GB_MODEL_DMG:
|
||||
case GB_MODEL_MGB: // TODO
|
||||
strncat(path, PATH_SEP "gb_bios.bin", PATH_MAX - strlen(path));
|
||||
strncat(path, PATH_SEP "gb_bios.bin", PATH_MAX - strlen(path) - 1);
|
||||
break;
|
||||
case GB_MODEL_SGB:
|
||||
case GB_MODEL_SGB2: // TODO
|
||||
strncat(path, PATH_SEP "sgb_bios.bin", PATH_MAX - strlen(path));
|
||||
strncat(path, PATH_SEP "sgb_bios.bin", PATH_MAX - strlen(path) - 1);
|
||||
break;
|
||||
case GB_MODEL_CGB:
|
||||
case GB_MODEL_AGB:
|
||||
case GB_MODEL_SCGB:
|
||||
strncat(path, PATH_SEP "gbc_bios.bin", PATH_MAX - strlen(path));
|
||||
strncat(path, PATH_SEP "gbc_bios.bin", PATH_MAX - strlen(path) - 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -405,7 +405,9 @@ void GBUnloadROM(struct GB* gb) {
|
|||
|
||||
if (gb->romVf) {
|
||||
#ifndef FIXED_ROM_BUFFER
|
||||
gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->pristineRomSize);
|
||||
if (gb->isPristine && gb->memory.rom) {
|
||||
gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->pristineRomSize);
|
||||
}
|
||||
#endif
|
||||
gb->romVf->close(gb->romVf);
|
||||
gb->romVf = NULL;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <mgba/internal/sm83/sm83.h>
|
||||
|
||||
#include <mgba-util/memory.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
mLOG_DEFINE_CATEGORY(GB_MEM, "GB Memory", "gb.memory");
|
||||
|
||||
|
@ -474,13 +475,14 @@ uint8_t GBView8(struct SM83Core* cpu, uint16_t address, int segment) {
|
|||
if (memory->rtcAccess) {
|
||||
return memory->rtcRegs[memory->activeRtcReg];
|
||||
} else if (memory->sramAccess) {
|
||||
if (segment < 0 && memory->sram) {
|
||||
return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
|
||||
} else if ((size_t) segment * GB_SIZE_EXTERNAL_RAM < gb->sramSize) {
|
||||
return memory->sram[(address & (GB_SIZE_EXTERNAL_RAM - 1)) + segment *GB_SIZE_EXTERNAL_RAM];
|
||||
} else {
|
||||
return 0xFF;
|
||||
if (memory->sram) {
|
||||
if (segment < 0) {
|
||||
return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
|
||||
} else if ((size_t) segment * GB_SIZE_EXTERNAL_RAM < gb->sramSize) {
|
||||
return memory->sram[(address & (GB_SIZE_EXTERNAL_RAM - 1)) + segment *GB_SIZE_EXTERNAL_RAM];
|
||||
}
|
||||
}
|
||||
return 0xFF;
|
||||
} else if (memory->mbcRead) {
|
||||
return memory->mbcRead(memory, address);
|
||||
} else if (memory->mbcType == GB_HuC3) {
|
||||
|
@ -1005,6 +1007,11 @@ void _pristineCow(struct GB* gb) {
|
|||
if (gb->memory.rom == gb->memory.romBase) {
|
||||
gb->memory.romBase = newRom;
|
||||
}
|
||||
if (gb->romVf) {
|
||||
gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->memory.romSize);
|
||||
gb->romVf->close(gb->romVf);
|
||||
gb->romVf = NULL;
|
||||
}
|
||||
gb->memory.rom = newRom;
|
||||
GBMBCSwitchBank(gb, gb->memory.currentBank);
|
||||
gb->isPristine = false;
|
||||
|
|
|
@ -571,20 +571,38 @@ static void _cleanOAM(struct GBVideoSoftwareRenderer* renderer, int y) {
|
|||
}
|
||||
int o = 0;
|
||||
int i;
|
||||
int16_t ids[GB_VIDEO_MAX_LINE_OBJ];
|
||||
for (i = 0; i < GB_VIDEO_MAX_OBJ && o < GB_VIDEO_MAX_LINE_OBJ; ++i) {
|
||||
uint8_t oy = renderer->d.oam->obj[i].y;
|
||||
if (y < oy - 16 || y >= oy - 16 + spriteHeight) {
|
||||
continue;
|
||||
}
|
||||
// TODO: Sort
|
||||
renderer->obj[o].obj = renderer->d.oam->obj[i];
|
||||
renderer->obj[o].index = i;
|
||||
ids[o] = (renderer->d.oam->obj[i].x << 7) | i;
|
||||
++o;
|
||||
if (o == 10) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
renderer->objMax = o;
|
||||
if (renderer->model < GB_MODEL_CGB) {
|
||||
// Terrble n^2 sort, but it's only 10 elements so it shouldn't be that bad
|
||||
int16_t ids2[GB_VIDEO_MAX_LINE_OBJ];
|
||||
int min = -1;
|
||||
int j;
|
||||
for (i = 0; i < o; ++i) {
|
||||
int min2 = 0xFFFF;
|
||||
for (j = 0; j < o; ++j) {
|
||||
if (ids[j] > min && ids[j] < min2) {
|
||||
min2 = ids[j];
|
||||
}
|
||||
}
|
||||
min = min2;
|
||||
ids2[i] = min;
|
||||
}
|
||||
memcpy(ids, ids2, sizeof(ids));
|
||||
}
|
||||
for (i = 0; i < o; ++i) {
|
||||
int id = ids[i] & 0x7F;
|
||||
renderer->obj[i].obj = renderer->d.oam->obj[id];
|
||||
renderer->obj[i].index = id;
|
||||
}
|
||||
}
|
||||
|
||||
static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y) {
|
||||
|
|
|
@ -695,7 +695,7 @@ static void _GBACoreReset(struct mCore* core) {
|
|||
if (!found) {
|
||||
char path[PATH_MAX];
|
||||
mCoreConfigDirectory(path, PATH_MAX);
|
||||
strncat(path, PATH_SEP "gba_bios.bin", PATH_MAX - strlen(path));
|
||||
strncat(path, PATH_SEP "gba_bios.bin", PATH_MAX - strlen(path) - 1);
|
||||
bios = VFileOpen(path, O_RDONLY);
|
||||
if (bios && GBAIsBIOS(bios)) {
|
||||
found = true;
|
||||
|
|
|
@ -159,6 +159,10 @@ static const struct GBACartridgeOverride _overrides[] = {
|
|||
// Shin Bokura no Taiyou: Gyakushuu no Sabata
|
||||
{ "U33J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false },
|
||||
|
||||
// Stuart Little 2
|
||||
{ "ASLE", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false },
|
||||
{ "ASLF", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false },
|
||||
|
||||
// Super Mario Advance 2
|
||||
{ "AA2J", SAVEDATA_EEPROM, HW_NONE, 0x800052E, false },
|
||||
{ "AA2E", SAVEDATA_EEPROM, HW_NONE, 0x800052E, false },
|
||||
|
|
|
@ -184,7 +184,7 @@ size_t GBASavedataSize(const struct GBASavedata* savedata) {
|
|||
|
||||
bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in) {
|
||||
if (savedata->data) {
|
||||
if (!in && savedata->type != SAVEDATA_FORCE_NONE) {
|
||||
if (!in || savedata->type == SAVEDATA_FORCE_NONE) {
|
||||
return false;
|
||||
}
|
||||
ssize_t size = GBASavedataSize(savedata);
|
||||
|
|
|
@ -463,7 +463,7 @@ static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* user,
|
|||
struct GBASIOLockstepNode* node = user;
|
||||
mLockstepLock(&node->p->d);
|
||||
|
||||
int32_t cycles = cycles = node->nextEvent;
|
||||
int32_t cycles = node->nextEvent;
|
||||
node->nextEvent -= cyclesLate;
|
||||
node->eventDiff += cyclesLate;
|
||||
if (node->p->d.attached < 2) {
|
||||
|
|
|
@ -1053,6 +1053,7 @@ bool mGLES2ShaderLoad(struct VideoShader* shader, struct VDir* dir) {
|
|||
for (n = 0; n < inShaders; ++n) {
|
||||
mGLES2ShaderDeinit(&shaderBlock[n]);
|
||||
}
|
||||
free(shaderBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -343,6 +343,7 @@ constexpr const char* ConfigController::mruName(ConfigController::MRU mru) {
|
|||
case MRU::Script:
|
||||
return "recentScripts";
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
void ConfigController::write() {
|
||||
|
|
|
@ -80,7 +80,7 @@ CoreController::CoreController(mCore* core, QObject* parent)
|
|||
|
||||
m_threadContext.resetCallback = [](mCoreThread* context) {
|
||||
CoreController* controller = static_cast<CoreController*>(context->userData);
|
||||
for (auto action : controller->m_resetActions) {
|
||||
for (auto& action : controller->m_resetActions) {
|
||||
action();
|
||||
}
|
||||
|
||||
|
@ -522,9 +522,6 @@ void CoreController::setRewinding(bool rewind) {
|
|||
}
|
||||
|
||||
void CoreController::rewind(int states) {
|
||||
if (!states) {
|
||||
return;
|
||||
}
|
||||
if (!m_threadContext.core->opts.rewindEnable) {
|
||||
emit statusPosted(tr("Rewinding not currently enabled"));
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#endif
|
||||
|
||||
#include <mgba/core/core.h>
|
||||
#include <mgba-util/string.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
using namespace QGBA;
|
||||
|
@ -161,7 +162,7 @@ CoreController* CoreManager::loadBIOS(int platform, const QString& path) {
|
|||
mCoreConfigSetOverrideIntValue(&core->config, "skipBios", 0);
|
||||
|
||||
QByteArray bytes(info.baseName().toUtf8());
|
||||
strncpy(core->dirs.baseName, bytes.constData(), sizeof(core->dirs.baseName));
|
||||
strlcpy(core->dirs.baseName, bytes.constData(), sizeof(core->dirs.baseName));
|
||||
|
||||
bytes = info.dir().canonicalPath().toUtf8();
|
||||
mDirectorySetAttachBase(&core->dirs, VDirOpen(bytes.constData()));
|
||||
|
|
|
@ -130,9 +130,9 @@ void QGBA::Display::configure(ConfigController* config) {
|
|||
config->updateOption("showOSD");
|
||||
config->updateOption("showFrameCounter");
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||
if (opts->shader) {
|
||||
if (opts->shader && supportsShaders()) {
|
||||
struct VDir* shader = VDirOpen(opts->shader);
|
||||
if (shader && supportsShaders()) {
|
||||
if (shader) {
|
||||
setShaders(shader);
|
||||
shader->close(shader);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,11 @@ using QOpenGLFunctions_Baseline = QOpenGLFunctions_3_2_Core;
|
|||
|
||||
using namespace QGBA;
|
||||
|
||||
enum ThreadStartFrom {
|
||||
START = 1,
|
||||
PROXY = 2,
|
||||
};
|
||||
|
||||
QHash<QSurfaceFormat, bool> DisplayGL::s_supports;
|
||||
|
||||
uint qHash(const QSurfaceFormat& format, uint seed) {
|
||||
|
@ -238,7 +243,16 @@ void DisplayGL::startDrawing(std::shared_ptr<CoreController> controller) {
|
|||
messagePainter()->resize(size(), devicePixelRatio());
|
||||
#endif
|
||||
|
||||
CoreController::Interrupter interrupter(controller);
|
||||
startThread(ThreadStartFrom::START);
|
||||
}
|
||||
|
||||
void DisplayGL::startThread(int from) {
|
||||
m_threadStartPending |= from;
|
||||
if (m_threadStartPending < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreController::Interrupter interrupter(m_context);
|
||||
QMetaObject::invokeMethod(m_painter.get(), "start");
|
||||
if (!m_gl) {
|
||||
if (shouldDisableUpdates()) {
|
||||
|
@ -313,6 +327,7 @@ void DisplayGL::stopDrawing() {
|
|||
hide();
|
||||
}
|
||||
setUpdatesEnabled(true);
|
||||
m_threadStartPending &= ~1;
|
||||
}
|
||||
m_context.reset();
|
||||
}
|
||||
|
@ -438,6 +453,7 @@ void DisplayGL::setupProxyThread() {
|
|||
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||
epoxy_handle_external_wglMakeCurrent();
|
||||
#endif
|
||||
QMetaObject::invokeMethod(this, "startThread", Q_ARG(int, ThreadStartFrom::PROXY));
|
||||
});
|
||||
connect(m_painter.get(), &PainterGL::texSwapped, m_proxyContext.get(), [this]() {
|
||||
if (!m_context->hardwareAccelerated()) {
|
||||
|
@ -918,8 +934,9 @@ void PainterGL::setShaders(struct VDir* dir) {
|
|||
mGLES2ShaderDetach(reinterpret_cast<mGLES2Context*>(m_backend));
|
||||
mGLES2ShaderFree(&m_shader);
|
||||
}
|
||||
mGLES2ShaderLoad(&m_shader, dir);
|
||||
mGLES2ShaderAttach(reinterpret_cast<mGLES2Context*>(m_backend), static_cast<mGLES2Shader*>(m_shader.passes), m_shader.nPasses);
|
||||
if (mGLES2ShaderLoad(&m_shader, dir)) {
|
||||
mGLES2ShaderAttach(reinterpret_cast<mGLES2Context*>(m_backend), static_cast<mGLES2Shader*>(m_shader.passes), m_shader.nPasses);
|
||||
}
|
||||
|
||||
if (!m_started) {
|
||||
m_gl->doneCurrent();
|
||||
|
|
|
@ -113,6 +113,7 @@ protected:
|
|||
virtual void resizeEvent(QResizeEvent*) override;
|
||||
|
||||
private slots:
|
||||
void startThread(int);
|
||||
void setupProxyThread();
|
||||
|
||||
private:
|
||||
|
@ -123,6 +124,7 @@ private:
|
|||
|
||||
bool m_isDrawing = false;
|
||||
bool m_hasStarted = false;
|
||||
int m_threadStartPending = 0;
|
||||
std::unique_ptr<PainterGL> m_painter;
|
||||
QThread m_drawThread;
|
||||
QThread m_proxyThread;
|
||||
|
|
|
@ -79,8 +79,8 @@ public slots:
|
|||
|
||||
private:
|
||||
mLogFilter m_filter;
|
||||
bool m_logToFile;
|
||||
bool m_logToStdout;
|
||||
bool m_logToFile = false;
|
||||
bool m_logToStdout = false;
|
||||
std::unique_ptr<QFile> m_logFile;
|
||||
std::unique_ptr<QTextStream> m_logStream;
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ void MemorySearch::refresh() {
|
|||
mCoreMemorySearchResult* result = mCoreMemorySearchResultsGetPointer(&m_results, i);
|
||||
QTableWidgetItem* item = new QTableWidgetItem(QString("%1").arg(result->address, 8, 16, QChar('0')));
|
||||
m_ui.results->setItem(i, 0, item);
|
||||
QTableWidgetItem* type;
|
||||
QTableWidgetItem* type = nullptr;
|
||||
QByteArray string;
|
||||
if (result->type == mCORE_MEMORY_SEARCH_INT && m_ui.numHex->isChecked()) {
|
||||
switch (result->width) {
|
||||
|
@ -213,7 +213,12 @@ void MemorySearch::refresh() {
|
|||
string.append(core->rawRead8(core, result->address + i, result->segment));
|
||||
}
|
||||
item = new QTableWidgetItem(QLatin1String(string)); // TODO
|
||||
break;
|
||||
case mCORE_MEMORY_SEARCH_GUESS:
|
||||
item = nullptr;
|
||||
break;
|
||||
}
|
||||
Q_ASSERT(item);
|
||||
}
|
||||
QString divisor;
|
||||
if (result->guessDivisor > 1) {
|
||||
|
@ -231,7 +236,12 @@ void MemorySearch::refresh() {
|
|||
break;
|
||||
case mCORE_MEMORY_SEARCH_STRING:
|
||||
type = new QTableWidgetItem("string");
|
||||
break;
|
||||
case mCORE_MEMORY_SEARCH_GUESS:
|
||||
break;
|
||||
}
|
||||
Q_ASSERT(type);
|
||||
|
||||
m_ui.results->setItem(i, 1, item);
|
||||
m_ui.results->setItem(i, 2, type);
|
||||
m_ui.opDelta->setEnabled(true);
|
||||
|
|
|
@ -51,7 +51,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
#ifdef M_CORE_GB
|
||||
m_pageIndex[Page::GB] = 9;
|
||||
|
||||
for (auto model : GameBoy::modelList()) {
|
||||
for (auto& model : GameBoy::modelList()) {
|
||||
m_ui.gbModel->addItem(GameBoy::modelName(model), model);
|
||||
m_ui.sgbModel->addItem(GameBoy::modelName(model), model);
|
||||
m_ui.cgbModel->addItem(GameBoy::modelName(model), model);
|
||||
|
@ -350,7 +350,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
QLocale englishLocale("en");
|
||||
m_ui.languages->addItem(englishLocale.nativeLanguageName(), englishLocale);
|
||||
QDir ts(":/translations/");
|
||||
for (auto name : ts.entryList()) {
|
||||
for (auto& name : ts.entryList()) {
|
||||
if (!name.endsWith(".qm") || !name.startsWith(binaryName)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ private:
|
|||
int m_shortcut = 0;
|
||||
int m_button = -1;
|
||||
int m_axis = -1;
|
||||
GamepadAxisEvent::Direction m_direction;
|
||||
GamepadAxisEvent::Direction m_direction = GamepadAxisEvent::NEUTRAL;
|
||||
};
|
||||
|
||||
class ShortcutController : public QObject {
|
||||
|
|
|
@ -1179,14 +1179,14 @@ void Window::recordFrame() {
|
|||
}
|
||||
|
||||
void Window::showFPS() {
|
||||
if (m_frameList.isEmpty()) {
|
||||
updateTitle();
|
||||
return;
|
||||
}
|
||||
qint64 total = 0;
|
||||
for (qint64 t : m_frameList) {
|
||||
total += t;
|
||||
}
|
||||
if (!total) {
|
||||
updateTitle();
|
||||
return;
|
||||
}
|
||||
double fps = (m_frameList.size() * 1e10) / total;
|
||||
m_frameList.clear();
|
||||
fps = round(fps) / 10.f;
|
||||
|
|
|
@ -146,7 +146,7 @@ bool InputController::loadConfiguration(uint32_t type) {
|
|||
if (!mInputMapLoad(&m_inputMap, type, m_config->input())) {
|
||||
return false;
|
||||
}
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
auto& driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return false;
|
||||
}
|
||||
|
@ -179,7 +179,8 @@ void InputController::saveConfiguration() {
|
|||
}
|
||||
|
||||
void InputController::saveConfiguration(uint32_t type) {
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
mInputMapSave(&m_inputMap, type, m_config->input());
|
||||
auto& driver = m_inputDrivers.value(type);
|
||||
if (driver) {
|
||||
driver->saveConfiguration(m_config);
|
||||
}
|
||||
|
@ -197,7 +198,7 @@ void InputController::saveProfile(uint32_t type, const QString& profile) {
|
|||
}
|
||||
|
||||
QString InputController::profileForType(uint32_t type) {
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
auto& driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return {};
|
||||
}
|
||||
|
@ -205,7 +206,7 @@ QString InputController::profileForType(uint32_t type) {
|
|||
}
|
||||
|
||||
void InputController::setGamepadDriver(uint32_t type) {
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
auto& driver = m_inputDrivers.value(type);
|
||||
if (!driver || !driver->supportsGamepads()) {
|
||||
return;
|
||||
}
|
||||
|
@ -216,13 +217,13 @@ QStringList InputController::connectedGamepads(uint32_t type) const {
|
|||
if (!type) {
|
||||
type = m_gamepadDriver;
|
||||
}
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
auto& driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return {};
|
||||
}
|
||||
|
||||
QStringList pads;
|
||||
for (auto pad : driver->connectedGamepads()) {
|
||||
for (auto& pad : driver->connectedGamepads()) {
|
||||
pads.append(pad->visibleName());
|
||||
}
|
||||
return pads;
|
||||
|
@ -232,7 +233,7 @@ int InputController::gamepadIndex(uint32_t type) const {
|
|||
if (!type) {
|
||||
type = m_gamepadDriver;
|
||||
}
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
auto& driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -243,7 +244,7 @@ void InputController::setGamepad(uint32_t type, int index) {
|
|||
if (!type) {
|
||||
type = m_gamepadDriver;
|
||||
}
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
auto& driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return;
|
||||
}
|
||||
|
@ -261,7 +262,7 @@ void InputController::setPreferredGamepad(uint32_t type, int index) {
|
|||
if (!type) {
|
||||
type = m_gamepadDriver;
|
||||
}
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
auto& driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return;
|
||||
}
|
||||
|
@ -295,7 +296,7 @@ InputMapper InputController::mapper(InputSource* source) {
|
|||
}
|
||||
|
||||
void InputController::setSensorDriver(uint32_t type) {
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
auto& driver = m_inputDrivers.value(type);
|
||||
if (!driver || !driver->supportsSensors()) {
|
||||
return;
|
||||
}
|
||||
|
@ -304,7 +305,7 @@ void InputController::setSensorDriver(uint32_t type) {
|
|||
|
||||
|
||||
mRumble* InputController::rumble() {
|
||||
auto driver = m_inputDrivers.value(m_sensorDriver);
|
||||
auto& driver = m_inputDrivers.value(m_sensorDriver);
|
||||
if (driver) {
|
||||
return driver->rumble();
|
||||
}
|
||||
|
@ -312,7 +313,7 @@ mRumble* InputController::rumble() {
|
|||
}
|
||||
|
||||
mRotationSource* InputController::rotationSource() {
|
||||
auto driver = m_inputDrivers.value(m_sensorDriver);
|
||||
auto& driver = m_inputDrivers.value(m_sensorDriver);
|
||||
if (driver) {
|
||||
return driver->rotationSource();
|
||||
}
|
||||
|
@ -337,7 +338,7 @@ void InputController::update() {
|
|||
|
||||
int InputController::pollEvents() {
|
||||
int activeButtons = 0;
|
||||
for (auto pad : gamepads()) {
|
||||
for (auto& pad : gamepads()) {
|
||||
InputMapper im(mapper(pad));
|
||||
activeButtons |= im.mapKeys(pad->currentButtons());
|
||||
activeButtons |= im.mapAxes(pad->currentAxes());
|
||||
|
@ -352,7 +353,7 @@ int InputController::pollEvents() {
|
|||
}
|
||||
|
||||
Gamepad* InputController::gamepad(uint32_t type) {
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
auto& driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -460,7 +461,7 @@ void InputController::testGamepad(uint32_t type) {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (auto axis : oldAxes) {
|
||||
for (auto& axis : oldAxes) {
|
||||
GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, false, type, this);
|
||||
clearPendingEvent(event->platformKey());
|
||||
sendGamepadEvent(event);
|
||||
|
|
|
@ -149,7 +149,7 @@ MAKE_SCALAR_SETTER(Bool, BOOL)
|
|||
void mScriptStorageGetBucketPath(const char* bucket, char* out) {
|
||||
mCoreConfigDirectory(out, PATH_MAX);
|
||||
|
||||
strncat(out, PATH_SEP "storage" PATH_SEP, PATH_MAX);
|
||||
strncat(out, PATH_SEP "storage" PATH_SEP, PATH_MAX - 1);
|
||||
#ifdef _WIN32
|
||||
// TODO: Move this to vfs somewhere
|
||||
WCHAR wout[MAX_PATH];
|
||||
|
@ -161,7 +161,7 @@ void mScriptStorageGetBucketPath(const char* bucket, char* out) {
|
|||
|
||||
char suffix[STORAGE_LEN_MAX + 6];
|
||||
snprintf(suffix, sizeof(suffix), "%s.json", bucket);
|
||||
strncat(out, suffix, PATH_MAX);
|
||||
strncat(out, suffix, PATH_MAX - 1);
|
||||
}
|
||||
|
||||
static struct json_object* _tableToJson(struct mScriptValue* rootVal) {
|
||||
|
@ -307,6 +307,9 @@ bool mScriptStorageBucketFlush(struct mScriptStorageBucket* bucket) {
|
|||
char path[PATH_MAX];
|
||||
mScriptStorageGetBucketPath(bucket->name, path);
|
||||
struct VFile* vf = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
return _mScriptStorageBucketFlushVF(bucket, vf);
|
||||
}
|
||||
|
||||
|
@ -329,6 +332,9 @@ bool mScriptStorageSaveBucket(struct mScriptContext* context, const char* bucket
|
|||
char path[PATH_MAX];
|
||||
mScriptStorageGetBucketPath(bucketName, path);
|
||||
struct VFile* vf = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
return mScriptStorageSaveBucketVF(context, bucketName, vf);
|
||||
}
|
||||
|
||||
|
|
|
@ -309,6 +309,9 @@ ssize_t _vfzRead(struct VFile* vf, void* buffer, size_t size) {
|
|||
if (!vfz->buffer) {
|
||||
vfz->bufferSize = BLOCK_SIZE;
|
||||
vfz->buffer = malloc(BLOCK_SIZE);
|
||||
if (vfz->readSize) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
while (bytesRead < size) {
|
||||
|
@ -714,7 +717,7 @@ struct VFile* _vdzOpenFile(struct VDir* vd, const char* path, int mode) {
|
|||
}
|
||||
}
|
||||
|
||||
struct VFileZip* vfz = malloc(sizeof(struct VFileZip));
|
||||
struct VFileZip* vfz = calloc(1, sizeof(struct VFileZip));
|
||||
vfz->uz = vdz->uz;
|
||||
vfz->z = vdz->z;
|
||||
vfz->buffer = 0;
|
||||
|
|
Loading…
Reference in New Issue