mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
5f46f126c1
6
CHANGES
6
CHANGES
|
@ -29,15 +29,21 @@ Emulation fixes:
|
|||
- GBA BIOS: Improve HLE BIOS timing
|
||||
- GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320)
|
||||
- GBA Memory: Improve gamepak prefetch timing
|
||||
- GBA SIO: Fix Multiplayer busy bit
|
||||
- GBA SIO: Fix double-unloading active driver
|
||||
- GBA SIO: Fix copying Normal mode transfer values
|
||||
- GBA Timers: Fix deserializing count-up timers
|
||||
- GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319)
|
||||
- GBA Video: Fix Hblank timing
|
||||
Other fixes:
|
||||
- Core: Ensure ELF regions can be written before trying
|
||||
- Core: Fix ELF loading regression (fixes mgba.io/i/1669)
|
||||
- Core: Fix crash modifying hash table entry (fixes mgba.io/i/1673)
|
||||
- GB Video: Fix some cases where SGB border doesn't draw to mutli-buffers
|
||||
- GBA: Reject incorrectly sized BIOSes
|
||||
- Debugger: Don't skip undefined instructions when debugger attached
|
||||
- Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642)
|
||||
- Qt: Fix OpenGL 2.1 support (fixes mgba.io/i/1678)
|
||||
Misc:
|
||||
- FFmpeg: Add looping option for GIF/APNG
|
||||
- Qt: Renderer can be changed while a game is running
|
||||
|
|
|
@ -121,7 +121,7 @@ typedef intptr_t ssize_t;
|
|||
// newlib doesn't support %z properly by default
|
||||
#define PRIz ""
|
||||
#elif defined(_WIN64)
|
||||
#define PRIz "ll"
|
||||
#define PRIz "I64"
|
||||
#elif defined(_WIN32)
|
||||
#define PRIz ""
|
||||
#else
|
||||
|
|
|
@ -154,9 +154,9 @@ struct GBAVideoSoftwareRenderer {
|
|||
int16_t objOffsetY;
|
||||
|
||||
uint32_t scanlineDirty[5];
|
||||
uint16_t nextIo[REG_SOUND1CNT_LO];
|
||||
uint16_t nextIo[REG_SOUND1CNT_LO >> 1];
|
||||
struct ScanlineCache {
|
||||
uint16_t io[REG_SOUND1CNT_LO];
|
||||
uint16_t io[REG_SOUND1CNT_LO >> 1];
|
||||
int32_t scale[2][2];
|
||||
} cache[GBA_VIDEO_VERTICAL_PIXELS];
|
||||
int nextY;
|
||||
|
|
|
@ -47,7 +47,7 @@ DECL_BIT(GBASIOMultiplayer, Slave, 2);
|
|||
DECL_BIT(GBASIOMultiplayer, Ready, 3);
|
||||
DECL_BITS(GBASIOMultiplayer, Id, 4, 2);
|
||||
DECL_BIT(GBASIOMultiplayer, Error, 6);
|
||||
DECL_BIT(GBASIOMultiplayer, Busy, 8);
|
||||
DECL_BIT(GBASIOMultiplayer, Busy, 7);
|
||||
DECL_BIT(GBASIOMultiplayer, Irq, 14);
|
||||
|
||||
struct GBASIODriverSet {
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
#include <mgba-util/platform/3ds/3ds-vfs.h>
|
||||
#endif
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#include <FindDirectory.h>
|
||||
#endif
|
||||
|
||||
#define SECTION_NAME_MAX 128
|
||||
|
||||
struct mCoreConfigEnumerateData {
|
||||
|
@ -227,6 +231,20 @@ void mCoreConfigDirectory(char* out, size_t outLength) {
|
|||
UNUSED(portable);
|
||||
snprintf(out, outLength, "/%s", projectName);
|
||||
FSUSER_CreateDirectory(sdmcArchive, fsMakePath(PATH_ASCII, out), 0);
|
||||
#elif defined(__HAIKU__)
|
||||
getcwd(out, outLength);
|
||||
strncat(out, PATH_SEP "portable.ini", outLength - strlen(out));
|
||||
portable = VFileOpen(out, O_RDONLY);
|
||||
if (portable) {
|
||||
getcwd(out, outLength);
|
||||
portable->close(portable);
|
||||
return;
|
||||
}
|
||||
|
||||
char path[B_PATH_NAME_LENGTH];
|
||||
find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, path, B_PATH_NAME_LENGTH);
|
||||
snprintf(out, outLength, "%s/%s", path, binaryName);
|
||||
mkdir(out, 0755);
|
||||
#else
|
||||
getcwd(out, outLength);
|
||||
strncat(out, PATH_SEP "portable.ini", outLength - strlen(out));
|
||||
|
|
|
@ -977,7 +977,7 @@ static void _reportEntry(struct mDebugger* debugger, enum mDebuggerEntryReason r
|
|||
case DEBUGGER_ENTER_BREAKPOINT:
|
||||
if (info) {
|
||||
if (info->pointId > 0) {
|
||||
cliDebugger->backend->printf(cliDebugger->backend, "Hit breakpoint %zi at 0x%08X\n", info->pointId, info->address);
|
||||
cliDebugger->backend->printf(cliDebugger->backend, "Hit breakpoint %" PRIz "i at 0x%08X\n", info->pointId, info->address);
|
||||
} else {
|
||||
cliDebugger->backend->printf(cliDebugger->backend, "Hit unknown breakpoint at 0x%08X\n", info->address);
|
||||
}
|
||||
|
@ -988,9 +988,9 @@ static void _reportEntry(struct mDebugger* debugger, enum mDebuggerEntryReason r
|
|||
case DEBUGGER_ENTER_WATCHPOINT:
|
||||
if (info) {
|
||||
if (info->type.wp.accessType & WATCHPOINT_WRITE) {
|
||||
cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint %zi at 0x%08X: (new value = 0x%08X, old value = 0x%08X)\n", info->pointId, info->address, info->type.wp.newValue, info->type.wp.oldValue);
|
||||
cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint %" PRIz "i at 0x%08X: (new value = 0x%08X, old value = 0x%08X)\n", info->pointId, info->address, info->type.wp.newValue, info->type.wp.oldValue);
|
||||
} else {
|
||||
cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint %zi at 0x%08X: (value = 0x%08X)\n", info->pointId, info->address, info->type.wp.oldValue);
|
||||
cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint %" PRIz "i at 0x%08X: (value = 0x%08X)\n", info->pointId, info->address, info->type.wp.oldValue);
|
||||
}
|
||||
} else {
|
||||
cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint\n");
|
||||
|
|
|
@ -705,7 +705,9 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer)
|
|||
case SGB_PAL_TRN:
|
||||
case SGB_CHR_TRN:
|
||||
case SGB_PCT_TRN:
|
||||
if (softwareRenderer->sgbTransfer > 0 && softwareRenderer->sgbBorders && !renderer->sgbRenderMode) {
|
||||
case SGB_ATRC_EN:
|
||||
case SGB_MASK_EN:
|
||||
if (softwareRenderer->sgbBorders && !renderer->sgbRenderMode) {
|
||||
// Make sure every buffer sees this if we're multibuffering
|
||||
_regenerateSGBBorder(softwareRenderer);
|
||||
}
|
||||
|
|
|
@ -375,7 +375,6 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c
|
|||
if (gbacore->renderer.outputBuffer) {
|
||||
renderer = &gbacore->renderer.d;
|
||||
}
|
||||
int fakeBool;
|
||||
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||
if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) {
|
||||
mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale);
|
||||
|
@ -563,7 +562,7 @@ static void _GBACoreReset(struct mCore* core) {
|
|||
if (gbacore->renderer.outputBuffer) {
|
||||
renderer = &gbacore->renderer.d;
|
||||
}
|
||||
int fakeBool;
|
||||
int fakeBool ATTRIBUTE_UNUSED;
|
||||
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||
if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) {
|
||||
mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale);
|
||||
|
|
|
@ -51,7 +51,7 @@ static void _triggerIRQ(struct mTiming*, void* user, uint32_t cyclesLate);
|
|||
|
||||
#ifdef USE_DEBUGGERS
|
||||
static bool _setSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode);
|
||||
static bool _clearSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode);
|
||||
static void _clearSoftwareBreakpoint(struct ARMDebugger*, const struct ARMDebugBreakpoint*);
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_ROM_BUFFER
|
||||
|
@ -917,8 +917,7 @@ static bool _setSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t addres
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool _clearSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t opcode) {
|
||||
GBAClearBreakpoint((struct GBA*) debugger->cpu->master, address, mode, opcode);
|
||||
return true;
|
||||
static void _clearSoftwareBreakpoint(struct ARMDebugger* debugger, const struct ARMDebugBreakpoint* breakpoint) {
|
||||
GBAClearBreakpoint((struct GBA*) debugger->cpu->master, breakpoint->d.address, breakpoint->sw.mode, breakpoint->sw.opcode);
|
||||
}
|
||||
#endif
|
51
src/gba/io.c
51
src/gba/io.c
|
@ -723,8 +723,7 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
|
|||
GBATimerUpdateRegister(gba, 3, 2);
|
||||
break;
|
||||
|
||||
case REG_KEYINPUT:
|
||||
{
|
||||
case REG_KEYINPUT: {
|
||||
size_t c;
|
||||
for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
|
||||
struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);
|
||||
|
@ -732,29 +731,28 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
|
|||
callbacks->keysRead(callbacks->context);
|
||||
}
|
||||
}
|
||||
}
|
||||
uint16_t input = 0;
|
||||
if (gba->keyCallback) {
|
||||
input = gba->keyCallback->readKeys(gba->keyCallback);
|
||||
if (gba->keySource) {
|
||||
*gba->keySource = input;
|
||||
}
|
||||
} else if (gba->keySource) {
|
||||
input = *gba->keySource;
|
||||
if (!gba->allowOpposingDirections) {
|
||||
unsigned rl = input & 0x030;
|
||||
unsigned ud = input & 0x0C0;
|
||||
input &= 0x30F;
|
||||
if (rl != 0x030) {
|
||||
input |= rl;
|
||||
uint16_t input = 0;
|
||||
if (gba->keyCallback) {
|
||||
input = gba->keyCallback->readKeys(gba->keyCallback);
|
||||
if (gba->keySource) {
|
||||
*gba->keySource = input;
|
||||
}
|
||||
if (ud != 0x0C0) {
|
||||
input |= ud;
|
||||
} else if (gba->keySource) {
|
||||
input = *gba->keySource;
|
||||
if (!gba->allowOpposingDirections) {
|
||||
unsigned rl = input & 0x030;
|
||||
unsigned ud = input & 0x0C0;
|
||||
input &= 0x30F;
|
||||
if (rl != 0x030) {
|
||||
input |= rl;
|
||||
}
|
||||
if (ud != 0x0C0) {
|
||||
input |= ud;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0x3FF ^ input;
|
||||
}
|
||||
|
||||
case REG_SIOCNT:
|
||||
return gba->sio.siocnt;
|
||||
case REG_RCNT:
|
||||
|
@ -964,16 +962,13 @@ void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
|||
for (i = 0; i < 4; ++i) {
|
||||
LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
|
||||
LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
|
||||
if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) {
|
||||
// Overwrite invalid values in savestate
|
||||
gba->timers[i].lastEvent = 0;
|
||||
} else {
|
||||
LOAD_32(when, 0, &state->timers[i].lastEvent);
|
||||
gba->timers[i].lastEvent = when + mTimingCurrentTime(&gba->timing);
|
||||
}
|
||||
LOAD_32(when, 0, &state->timers[i].lastEvent);
|
||||
gba->timers[i].lastEvent = when + mTimingCurrentTime(&gba->timing);
|
||||
LOAD_32(when, 0, &state->timers[i].nextEvent);
|
||||
if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
|
||||
if ((i < 1 || !GBATimerFlagsIsCountUp(gba->timers[i].flags)) && GBATimerFlagsIsEnable(gba->timers[i].flags)) {
|
||||
mTimingSchedule(&gba->timing, &gba->timers[i].event, when);
|
||||
} else {
|
||||
gba->timers[i].event.when = when + mTimingCurrentTime(&gba->timing);
|
||||
}
|
||||
|
||||
LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
|
||||
|
|
|
@ -242,7 +242,8 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
|||
int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23;
|
||||
x >>= 23;
|
||||
x += renderer->objOffsetX;
|
||||
unsigned charBase = GBAObjAttributesCGetTile(sprite->c);
|
||||
unsigned align = GBAObjAttributesAIs256Color(sprite->a) && !GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt);
|
||||
unsigned charBase = GBAObjAttributesCGetTile(sprite->c) & ~align;
|
||||
if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_BITMAP && renderer->bitmapStride) {
|
||||
charBase = (charBase & (renderer->bitmapStride - 1)) * 0x10 + (charBase & ~(renderer->bitmapStride - 1)) * 0x80;
|
||||
} else {
|
||||
|
|
|
@ -75,10 +75,13 @@ void GBASIODeinit(struct GBASIO* sio) {
|
|||
}
|
||||
|
||||
void GBASIOReset(struct GBASIO* sio) {
|
||||
GBASIODeinit(sio);
|
||||
if (sio->activeDriver && sio->activeDriver->unload) {
|
||||
sio->activeDriver->unload(sio->activeDriver);
|
||||
}
|
||||
sio->rcnt = RCNT_INITIAL;
|
||||
sio->siocnt = 0;
|
||||
sio->mode = -1;
|
||||
sio->activeDriver = NULL;
|
||||
_switchMode(sio);
|
||||
}
|
||||
|
||||
|
|
|
@ -279,19 +279,39 @@ static int32_t _masterUpdate(struct GBASIOLockstepNode* node) {
|
|||
case TRANSFER_IDLE:
|
||||
// If the master hasn't initiated a transfer, it can keep going.
|
||||
node->nextEvent += LOCKSTEP_INCREMENT;
|
||||
node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, attachedMulti == attached);
|
||||
if (node->mode == SIO_MULTI) {
|
||||
node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, attachedMulti == attached);
|
||||
}
|
||||
break;
|
||||
case TRANSFER_STARTING:
|
||||
// Start the transfer, but wait for the other GBAs to catch up
|
||||
node->transferFinished = false;
|
||||
node->p->multiRecv[0] = node->d.p->p->memory.io[REG_SIOMLT_SEND >> 1];
|
||||
node->d.p->p->memory.io[REG_SIOMULTI0 >> 1] = 0xFFFF;
|
||||
node->d.p->p->memory.io[REG_SIOMULTI1 >> 1] = 0xFFFF;
|
||||
node->d.p->p->memory.io[REG_SIOMULTI2 >> 1] = 0xFFFF;
|
||||
node->d.p->p->memory.io[REG_SIOMULTI3 >> 1] = 0xFFFF;
|
||||
node->p->multiRecv[1] = 0xFFFF;
|
||||
node->p->multiRecv[2] = 0xFFFF;
|
||||
node->p->multiRecv[3] = 0xFFFF;
|
||||
switch (node->mode) {
|
||||
case SIO_MULTI:
|
||||
node->p->multiRecv[0] = node->d.p->p->memory.io[REG_SIOMLT_SEND >> 1];
|
||||
node->d.p->p->memory.io[REG_SIOMULTI0 >> 1] = 0xFFFF;
|
||||
node->d.p->p->memory.io[REG_SIOMULTI1 >> 1] = 0xFFFF;
|
||||
node->d.p->p->memory.io[REG_SIOMULTI2 >> 1] = 0xFFFF;
|
||||
node->d.p->p->memory.io[REG_SIOMULTI3 >> 1] = 0xFFFF;
|
||||
node->p->multiRecv[1] = 0xFFFF;
|
||||
node->p->multiRecv[2] = 0xFFFF;
|
||||
node->p->multiRecv[3] = 0xFFFF;
|
||||
break;
|
||||
case SIO_NORMAL_8:
|
||||
node->p->multiRecv[0] = 0xFFFF;
|
||||
node->p->normalRecv[0] = node->d.p->p->memory.io[REG_SIODATA8 >> 1] & 0xFF;
|
||||
break;
|
||||
case SIO_NORMAL_32:
|
||||
node->p->multiRecv[0] = 0xFFFF;
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_LO <- %04x", node->id, node->d.p->p->memory.io[REG_SIODATA32_LO >> 1]);
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_HI <- %04x", node->id, node->d.p->p->memory.io[REG_SIODATA32_HI >> 1]);
|
||||
node->p->normalRecv[0] = node->d.p->p->memory.io[REG_SIODATA32_LO >> 1];
|
||||
node->p->normalRecv[0] |= node->d.p->p->memory.io[REG_SIODATA32_HI >> 1] << 16;
|
||||
break;
|
||||
default:
|
||||
node->p->multiRecv[0] = 0xFFFF;
|
||||
break;
|
||||
}
|
||||
needsToWait = true;
|
||||
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTED);
|
||||
node->nextEvent += LOCKSTEP_TRANSFER;
|
||||
|
@ -456,7 +476,7 @@ static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* drive
|
|||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04x", node->id, value);
|
||||
value &= 0xFF8B;
|
||||
if (!node->id) {
|
||||
driver->p->siocnt = GBASIONormalFillSi(driver->p->siocnt);
|
||||
value = GBASIONormalFillSi(value);
|
||||
}
|
||||
if (value & 0x0080 && !node->id) {
|
||||
// Internal shift clock
|
||||
|
|
|
@ -21,6 +21,9 @@ static const GLchar* const _gles2Header =
|
|||
"#version 100\n"
|
||||
"precision mediump float;\n";
|
||||
|
||||
static const GLchar* const _gl2Header =
|
||||
"#version 120\n";
|
||||
|
||||
static const GLchar* const _gl32VHeader =
|
||||
"#version 150 core\n"
|
||||
"#define attribute in\n"
|
||||
|
@ -462,10 +465,12 @@ void mGLES2ShaderInit(struct mGLES2Shader* shader, const char* vs, const char* f
|
|||
shader->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
const GLchar* shaderBuffer[2];
|
||||
const GLubyte* version = glGetString(GL_VERSION);
|
||||
if (strncmp((const char*) version, "OpenGL ES ", strlen("OpenGL ES "))) {
|
||||
shaderBuffer[0] = _gl32VHeader;
|
||||
} else {
|
||||
if (strncmp((const char*) version, "OpenGL ES ", strlen("OpenGL ES ")) == 0) {
|
||||
shaderBuffer[0] = _gles2Header;
|
||||
} else if (version[0] == '2') {
|
||||
shaderBuffer[0] = _gl2Header;
|
||||
} else {
|
||||
shaderBuffer[0] = _gl32VHeader;
|
||||
}
|
||||
if (vs) {
|
||||
shaderBuffer[1] = vs;
|
||||
|
@ -474,7 +479,7 @@ void mGLES2ShaderInit(struct mGLES2Shader* shader, const char* vs, const char* f
|
|||
}
|
||||
glShaderSource(shader->vertexShader, 2, shaderBuffer, 0);
|
||||
|
||||
if (strncmp((const char*) version, "OpenGL ES ", strlen("OpenGL ES "))) {
|
||||
if (shaderBuffer[0] == _gl32VHeader) {
|
||||
shaderBuffer[0] = _gl32FHeader;
|
||||
}
|
||||
if (fs) {
|
||||
|
|
|
@ -683,7 +683,7 @@ void CoreController::scanCard(const QString& path) {
|
|||
#else
|
||||
size = image.byteCount();
|
||||
#endif
|
||||
m_eReaderData.setRawData(reinterpret_cast<const char*>(bits), image.sizeInBytes());
|
||||
m_eReaderData.setRawData(reinterpret_cast<const char*>(bits), size);
|
||||
}
|
||||
|
||||
mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* thread) {
|
||||
|
|
|
@ -21,6 +21,7 @@ MemorySearch::MemorySearch(std::shared_ptr<CoreController> controller, QWidget*
|
|||
|
||||
mCoreMemorySearchResultsInit(&m_results, 0);
|
||||
connect(m_ui.search, &QPushButton::clicked, this, &MemorySearch::search);
|
||||
connect(m_ui.value, &QLineEdit::returnPressed, this, &MemorySearch::search);
|
||||
connect(m_ui.searchWithin, &QPushButton::clicked, this, &MemorySearch::searchWithin);
|
||||
connect(m_ui.refresh, &QPushButton::clicked, this, &MemorySearch::refresh);
|
||||
connect(m_ui.numHex, &QPushButton::clicked, this, &MemorySearch::refresh);
|
||||
|
|
|
@ -388,8 +388,8 @@ void InputController::setPreferredGamepad(uint32_t type, int index) {
|
|||
return;
|
||||
}
|
||||
#ifdef BUILD_SDL
|
||||
char name[34] = {0};
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
char name[34] = {0};
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, index)->joystick), name, sizeof(name));
|
||||
#else
|
||||
const char* name = SDL_JoystickName(SDL_JoystickIndex(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, index)->joystick));
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -246,6 +246,9 @@ void mSDLDetachPlayer(struct mSDLEvents* events, struct mSDLPlayer* player) {
|
|||
}
|
||||
--events->playersAttached;
|
||||
CircleBufferDeinit(&player->rotation.zHistory);
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
CircleBufferDeinit(&player->rumble.history);
|
||||
#endif
|
||||
}
|
||||
|
||||
void mSDLPlayerLoadConfig(struct mSDLPlayer* context, const struct Configuration* config) {
|
||||
|
@ -349,10 +352,10 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration*
|
|||
continue;
|
||||
}
|
||||
ssize_t joysticks[MAX_PLAYERS];
|
||||
size_t i;
|
||||
ssize_t i;
|
||||
// Pointers can get invalidated, so we'll need to refresh them
|
||||
for (i = 0; i < events->playersAttached && i < MAX_PLAYERS; ++i) {
|
||||
joysticks[i] = events->players[i]->joystick ? SDL_JoystickListIndex(&events->joysticks, events->players[i]->joystick) : SIZE_MAX;
|
||||
joysticks[i] = events->players[i]->joystick ? (ssize_t) SDL_JoystickListIndex(&events->joysticks, events->players[i]->joystick) : -1;
|
||||
events->players[i]->joystick = NULL;
|
||||
}
|
||||
struct SDL_JoystickCombo* joystick = SDL_JoystickListAppend(&events->joysticks);
|
||||
|
@ -363,7 +366,7 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration*
|
|||
joystick->haptic = SDL_HapticOpenFromJoystick(joystick->joystick);
|
||||
#endif
|
||||
for (i = 0; i < events->playersAttached && i < MAX_PLAYERS; ++i) {
|
||||
if (joysticks[i] != SIZE_MAX) {
|
||||
if (joysticks[i] != -1) {
|
||||
events->players[i]->joystick = SDL_JoystickListGetPointer(&events->joysticks, joysticks[i]);
|
||||
}
|
||||
}
|
||||
|
@ -394,7 +397,11 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration*
|
|||
continue;
|
||||
}
|
||||
events->players[i]->joystick = joystick;
|
||||
if (config && events->players[i]->bindings && joystickName) {
|
||||
if (config && events->players[i]->bindings
|
||||
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
&& joystickName
|
||||
#endif
|
||||
) {
|
||||
mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -44,7 +44,7 @@ static bool _dispatchExiting = false;
|
|||
int main(int argc, char** argv) {
|
||||
signal(SIGINT, _fuzzShutdown);
|
||||
|
||||
struct FuzzOpts fuzzOpts = { false, 0, 0, 0, 0 };
|
||||
struct FuzzOpts fuzzOpts = { false, 0, 0, 0 };
|
||||
struct mSubParser subparser = {
|
||||
.usage = FUZZ_USAGE,
|
||||
.parse = _parseFuzzOpts,
|
||||
|
|
|
@ -52,7 +52,7 @@ OutputBaseFilename={#AppName}-setup-{#CleanVersionString}-win{#WinBits}
|
|||
UsePreviousLanguage=False
|
||||
DisableWelcomePage=False
|
||||
VersionInfoDescription={#AppName} is an open-source Game Boy Advance emulator
|
||||
VersionInfoCopyright=© 2013–2019 Jeffrey Pfau
|
||||
VersionInfoCopyright=© 2013–2020 Jeffrey Pfau
|
||||
VersionInfoProductName={#AppName}
|
||||
VersionInfoVersion={#AppVer}
|
||||
Compression=lzma2/ultra64
|
||||
|
|
Loading…
Reference in New Issue