mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
9991729de5
1
CHANGES
1
CHANGES
|
@ -112,6 +112,7 @@ Other fixes:
|
|||
- Qt: Fix preloading for ROM replacing
|
||||
- Qt: Fix screen not displaying on Wayland (fixes mgba.io/i/2190)
|
||||
- Qt: Fix crash when selecting 256-color sprite in sprite view
|
||||
- Qt: Fix coloration of swatches on styles with distinct frame backgrounds
|
||||
- VFS: Failed file mapping should return NULL on POSIX
|
||||
Misc:
|
||||
- Core: Suspend runloop when a core crashes
|
||||
|
|
|
@ -239,6 +239,7 @@ elseif(UNIX)
|
|||
endif()
|
||||
|
||||
if(APPLE)
|
||||
execute_process(COMMAND xcrun --show-sdk-version OUTPUT_VARIABLE MACOSX_SDK)
|
||||
add_definitions(-D_DARWIN_C_SOURCE)
|
||||
list(APPEND OS_LIB "-framework Foundation")
|
||||
if(NOT CMAKE_SYSTEM_VERSION VERSION_LESS "10.0") # Darwin 10.x is Mac OS X 10.6
|
||||
|
@ -417,7 +418,7 @@ endif()
|
|||
|
||||
if(BUILD_GL)
|
||||
find_package(OpenGL QUIET)
|
||||
if(NOT OPENGL_FOUND)
|
||||
if(NOT OPENGL_FOUND OR (APPLE AND MACOSX_SDK VERSION_GREATER 10.14))
|
||||
set(BUILD_GL OFF CACHE BOOL "OpenGL not found" FORCE)
|
||||
elseif(UNIX AND NOT APPLE AND TARGET OpenGL::GL)
|
||||
set(OPENGL_LIBRARY OpenGL::GL)
|
||||
|
@ -434,6 +435,11 @@ if(NOT BUILD_GL AND NOT LIBMGBA_ONLY)
|
|||
endif()
|
||||
|
||||
if(BUILD_GLES2 AND NOT BUILD_GL)
|
||||
if(APPLE AND MACOSX_SDK VERSION_GREATER 10.14)
|
||||
find_package(OpenGL QUIET)
|
||||
set(OPENGLES2_INCLUDE_DIR ${OPENGL_INCLUDE_DIR})
|
||||
set(OPENGLES2_LIBRARY ${OPENGL_LIBRARY})
|
||||
endif()
|
||||
find_path(OPENGLES2_INCLUDE_DIR NAMES GLES2/gl2.h)
|
||||
find_library(OPENGLES2_LIBRARY NAMES GLESv2 GLESv2_CM)
|
||||
if(NOT OPENGLES2_INCLUDE_DIR OR NOT OPENGLES2_LIBRARY)
|
||||
|
@ -447,6 +453,11 @@ if(BUILD_GLES2)
|
|||
endif()
|
||||
|
||||
if(BUILD_GLES3 AND NOT BUILD_GL)
|
||||
if(APPLE AND MACOSX_SDK VERSION_GREATER 10.14)
|
||||
find_package(OpenGL QUIET)
|
||||
set(OPENGLES3_INCLUDE_DIR ${OPENGL_INCLUDE_DIR})
|
||||
set(OPENGLES3_LIBRARY ${OPENGL_LIBRARY})
|
||||
endif()
|
||||
find_path(OPENGLES3_INCLUDE_DIR NAMES GLES3/gl3.h)
|
||||
find_library(OPENGLES3_LIBRARY NAMES GLESv3 GLESv2)
|
||||
if(NOT OPENGLES3_INCLUDE_DIR OR NOT OPENGLES3_LIBRARY)
|
||||
|
|
|
@ -33,14 +33,20 @@ struct mTiming {
|
|||
|
||||
void mTimingInit(struct mTiming* timing, int32_t* relativeCycles, int32_t* nextEvent);
|
||||
void mTimingDeinit(struct mTiming* timing);
|
||||
|
||||
void mTimingClear(struct mTiming* timing);
|
||||
void mTimingInterrupt(struct mTiming* timing);
|
||||
|
||||
void mTimingSchedule(struct mTiming* timing, struct mTimingEvent*, int32_t when);
|
||||
void mTimingScheduleAbsolute(struct mTiming* timing, struct mTimingEvent*, int32_t when);
|
||||
void mTimingDeschedule(struct mTiming* timing, struct mTimingEvent*);
|
||||
bool mTimingIsScheduled(const struct mTiming* timing, const struct mTimingEvent*);
|
||||
|
||||
int32_t mTimingTick(struct mTiming* timing, int32_t cycles);
|
||||
|
||||
int32_t mTimingCurrentTime(const struct mTiming* timing);
|
||||
uint64_t mTimingGlobalTime(const struct mTiming* timing);
|
||||
|
||||
int32_t mTimingNextEvent(struct mTiming* timing);
|
||||
int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent*);
|
||||
|
||||
|
|
|
@ -463,7 +463,8 @@ struct GBSerializedState {
|
|||
union {
|
||||
uint8_t huc3Registers[0x80];
|
||||
struct {
|
||||
uint8_t registers[8];
|
||||
uint8_t registers[4];
|
||||
uint8_t reserved[4];
|
||||
uint8_t rtcTimerPage[8];
|
||||
uint8_t rtcAlarmPage[8];
|
||||
uint8_t rtcFreePage0[8];
|
||||
|
|
|
@ -20,14 +20,12 @@ CXX_GUARD_START
|
|||
|
||||
#ifdef USE_EPOXY
|
||||
#include <epoxy/gl.h>
|
||||
#elif defined(BUILD_GL)
|
||||
#ifdef __APPLE__
|
||||
#elif defined(__APPLE__)
|
||||
#include <OpenGL/gl3.h>
|
||||
#else
|
||||
#elif defined(BUILD_GL)
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#endif
|
||||
#else
|
||||
#include <GLES3/gl3.h>
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,14 @@ void mTimingClear(struct mTiming* timing) {
|
|||
timing->masterCycles = 0;
|
||||
}
|
||||
|
||||
void mTimingInterrupt(struct mTiming* timing) {
|
||||
if (!timing->root) {
|
||||
return;
|
||||
}
|
||||
timing->reroot = timing->root;
|
||||
timing->root = NULL;
|
||||
}
|
||||
|
||||
void mTimingSchedule(struct mTiming* timing, struct mTimingEvent* event, int32_t when) {
|
||||
int32_t nextEvent = when + *timing->relativeCycles;
|
||||
event->when = nextEvent + timing->masterCycles;
|
||||
|
|
|
@ -94,7 +94,7 @@ static void mGUIShowCheatSet(struct mGUIRunner* runner, struct mCheatDevice* dev
|
|||
switch (action) {
|
||||
case CHEAT_ADD_LINE:
|
||||
strlcpy(keyboard.title, "Add line", sizeof(keyboard.title));
|
||||
keyboard.maxLen = 12;
|
||||
keyboard.maxLen = 17;
|
||||
if (runner->params.getText(&keyboard) == GUI_KEYBOARD_DONE) {
|
||||
mCheatAddLine(set, keyboard.result, 0);
|
||||
_rebuildCheatView(&view.items, set);
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#define W_OK 02
|
||||
#endif
|
||||
|
||||
FILE* logfile;
|
||||
|
||||
bool extractArchive(struct VDir* archive, const char* root, bool prefix) {
|
||||
char path[PATH_MAX] = {0};
|
||||
struct VDirEntry* vde;
|
||||
|
@ -53,7 +55,7 @@ bool extractArchive(struct VDir* archive, const char* root, bool prefix) {
|
|||
}
|
||||
switch (vde->type(vde)) {
|
||||
case VFS_DIRECTORY:
|
||||
printf("mkdir %s\n", fname);
|
||||
fprintf(logfile, "mkdir %s\n", fname);
|
||||
if (mkdir(path, 0755) < 0 && errno != EEXIST) {
|
||||
return false;
|
||||
}
|
||||
|
@ -70,7 +72,7 @@ bool extractArchive(struct VDir* archive, const char* root, bool prefix) {
|
|||
}
|
||||
break;
|
||||
case VFS_FILE:
|
||||
printf("extract %s\n", fname);
|
||||
fprintf(logfile, "extract %s\n", fname);
|
||||
vfIn = archive->openFile(archive, vde->name(vde), O_RDONLY);
|
||||
errno = 0;
|
||||
vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
|
@ -111,13 +113,17 @@ int main(int argc, char* argv[]) {
|
|||
const char* root;
|
||||
int ok = 1;
|
||||
|
||||
mCoreConfigDirectory(bin, sizeof(bin));
|
||||
strncat(bin, "/updater.log", sizeof(bin));
|
||||
logfile = fopen(bin, "w");
|
||||
|
||||
mCoreConfigInit(&config, "updater");
|
||||
if (!mCoreConfigLoad(&config)) {
|
||||
puts("Failed to load config");
|
||||
fputs("Failed to load config", logfile);
|
||||
} else if (!mUpdateGetArchivePath(&config, updateArchive, sizeof(updateArchive)) || !(root = mUpdateGetRoot(&config))) {
|
||||
puts("No pending update found");
|
||||
fputs("No pending update found", logfile);
|
||||
} else if (access(root, W_OK)) {
|
||||
puts("Cannot write to update path");
|
||||
fputs("Cannot write to update path", logfile);
|
||||
} else {
|
||||
#ifdef __APPLE__
|
||||
char subdir[PATH_MAX];
|
||||
|
@ -160,7 +166,7 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
off_t diff = devend - devinfo - 1;
|
||||
memcpy(devpath, &devinfo[1], diff);
|
||||
puts(devpath);
|
||||
fputs(devpath, logfile);
|
||||
break;
|
||||
}
|
||||
int retstat;
|
||||
|
@ -177,11 +183,11 @@ int main(int argc, char* argv[]) {
|
|||
archive = VDirOpenArchive(updateArchive);
|
||||
}
|
||||
if (archive) {
|
||||
puts("Extracting update");
|
||||
fputs("Extracting update", logfile);
|
||||
if (extractArchive(archive, root, prefix)) {
|
||||
ok = 0;
|
||||
} else {
|
||||
puts("An error occurred");
|
||||
fputs("An error occurred", logfile);
|
||||
}
|
||||
archive->close(archive);
|
||||
unlink(updateArchive);
|
||||
|
@ -218,10 +224,10 @@ int main(int argc, char* argv[]) {
|
|||
close(infd);
|
||||
}
|
||||
if (ok == 2) {
|
||||
puts("Cannot move update over old file");
|
||||
fputs("Cannot move update over old file", logfile);
|
||||
}
|
||||
} else {
|
||||
puts("Cannot move update over old file");
|
||||
fputs("Cannot move update over old file", logfile);
|
||||
}
|
||||
} else {
|
||||
ok = 0;
|
||||
|
@ -232,10 +238,10 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
#endif
|
||||
else {
|
||||
puts("Cannot open update archive");
|
||||
fputs("Cannot open update archive", logfile);
|
||||
}
|
||||
if (ok == 0) {
|
||||
puts("Complete");
|
||||
fputs("Complete", logfile);
|
||||
const char* command = mUpdateGetCommand(&config);
|
||||
strlcpy(bin, command, sizeof(bin));
|
||||
mUpdateDeregister(&config);
|
||||
|
@ -260,6 +266,7 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
}
|
||||
mCoreConfigDeinit(&config);
|
||||
fclose(logfile);
|
||||
if (ok == 0) {
|
||||
#ifdef _WIN32
|
||||
char qbin[PATH_MAX + 2] = {0};
|
||||
|
|
|
@ -672,6 +672,8 @@ static void _GBCoreReset(struct mCore* core) {
|
|||
if (core->opts.skipBios) {
|
||||
GBSkipBIOS(core->board);
|
||||
}
|
||||
|
||||
mTimingInterrupt(&gb->timing);
|
||||
}
|
||||
|
||||
static void _GBCoreRunFrame(struct mCore* core) {
|
||||
|
|
|
@ -768,9 +768,11 @@ void GBMemorySerialize(const struct GB* gb, struct GBSerializedState* state) {
|
|||
case GB_TAMA5:
|
||||
STORE_64LE(memory->rtcLastLatch, 0, &state->memory.tama5.lastLatch);
|
||||
state->memory.tama5.reg = memory->mbcState.tama5.reg;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
for (i = 0; i < 4; ++i) {
|
||||
state->tama5Registers.registers[i] = memory->mbcState.tama5.registers[i * 2] & 0xF;
|
||||
state->tama5Registers.registers[i] |= memory->mbcState.tama5.registers[i * 2 + 1] << 4;
|
||||
}
|
||||
for (i = 0; i < 8; ++i) {
|
||||
state->tama5Registers.rtcTimerPage[i] = memory->mbcState.tama5.rtcTimerPage[i * 2] & 0xF;
|
||||
state->tama5Registers.rtcTimerPage[i] |= memory->mbcState.tama5.rtcTimerPage[i * 2 + 1] << 4;
|
||||
state->tama5Registers.rtcAlarmPage[i] = memory->mbcState.tama5.rtcAlarmPage[i * 2] & 0xF;
|
||||
|
@ -893,9 +895,11 @@ void GBMemoryDeserialize(struct GB* gb, const struct GBSerializedState* state) {
|
|||
case GB_TAMA5:
|
||||
LOAD_64LE(memory->rtcLastLatch, 0, &state->memory.tama5.lastLatch);
|
||||
memory->mbcState.tama5.reg = state->memory.tama5.reg;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
for (i = 0; i < 4; ++i) {
|
||||
memory->mbcState.tama5.registers[i * 2] = state->tama5Registers.registers[i] & 0xF;
|
||||
memory->mbcState.tama5.registers[i * 2 + 1] = state->tama5Registers.registers[i] >> 4;
|
||||
}
|
||||
for (i = 0; i < 8; ++i) {
|
||||
memory->mbcState.tama5.rtcTimerPage[i * 2] = state->tama5Registers.rtcTimerPage[i] & 0xF;
|
||||
memory->mbcState.tama5.rtcTimerPage[i * 2 + 1] = state->tama5Registers.rtcTimerPage[i] >> 4;
|
||||
memory->mbcState.tama5.rtcAlarmPage[i * 2] = state->tama5Registers.rtcAlarmPage[i] & 0xF;
|
||||
|
|
|
@ -217,8 +217,7 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
|
|||
|
||||
gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);
|
||||
|
||||
gb->timing.reroot = gb->timing.root;
|
||||
gb->timing.root = NULL;
|
||||
mTimingInterrupt(&gb->timing);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -723,6 +723,8 @@ static void _GBACoreReset(struct mCore* core) {
|
|||
if (forceSkip || (core->opts.skipBios && (gba->romVf || gba->memory.rom))) {
|
||||
GBASkipBIOS(core->board);
|
||||
}
|
||||
|
||||
mTimingInterrupt(&gba->timing);
|
||||
}
|
||||
|
||||
static void _GBACoreRunFrame(struct mCore* core) {
|
||||
|
|
|
@ -74,9 +74,9 @@ const uint8_t hleBios[SIZE_BIOS] = {
|
|||
0xfa, 0x07, 0xa0, 0xe8, 0xfa, 0x07, 0xa0, 0xe8, 0x00, 0x10, 0xa0, 0xe3,
|
||||
0xf0, 0x07, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0xb0, 0x01, 0x00, 0x00,
|
||||
0x04, 0xb0, 0x5b, 0xe2, 0xfd, 0xff, 0xff, 0x8a, 0x1e, 0xff, 0x2f, 0xe1,
|
||||
0xc2, 0x03, 0xa0, 0xe3, 0x03, 0x10, 0x50, 0xe4, 0x00, 0x00, 0x51, 0xe3,
|
||||
0x00, 0x10, 0xa0, 0x13, 0x10, 0xff, 0x2f, 0x11, 0x1c, 0x00, 0x9f, 0xe5,
|
||||
0x00, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x00, 0x10, 0xa0, 0xe3,
|
||||
0x10, 0xff, 0x2f, 0x11, 0xc0, 0x00, 0x40, 0xe2, 0x10, 0xff, 0x2f, 0xe1,
|
||||
0xc2, 0xe3, 0xa0, 0xe3, 0x03, 0x10, 0x5e, 0xe4, 0x00, 0x00, 0x51, 0xe3,
|
||||
0x00, 0x10, 0xa0, 0x13, 0x1e, 0xff, 0x2f, 0x11, 0x1c, 0xe0, 0x9f, 0xe5,
|
||||
0x00, 0x10, 0x9e, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x00, 0x10, 0xa0, 0xe3,
|
||||
0x1e, 0xff, 0x2f, 0x11, 0xc0, 0xe0, 0x4e, 0xe2, 0x1e, 0xff, 0x2f, 0xe1,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1, 0xc0, 0x00, 0x00, 0x02
|
||||
};
|
||||
|
|
|
@ -314,17 +314,17 @@ bhi StallCall
|
|||
bx lr
|
||||
|
||||
resetBase:
|
||||
mov r0, #0x8000003
|
||||
ldrb r1, [r0], #-3
|
||||
mov lr, #0x8000003
|
||||
ldrb r1, [lr], #-3
|
||||
cmp r1, #0
|
||||
movne r1, #0
|
||||
bxne r0
|
||||
ldr r0, =0x20000C0
|
||||
ldr r1, [r0]
|
||||
bxne lr
|
||||
ldr lr, =0x20000C0
|
||||
ldr r1, [lr]
|
||||
cmp r1, #0
|
||||
mov r1, #0
|
||||
bxne r0
|
||||
sub r0, #0xC0
|
||||
bx r0
|
||||
bxne lr
|
||||
sub lr, #0xC0
|
||||
bx lr
|
||||
.word 0
|
||||
.word 0xE129F000
|
||||
|
|
|
@ -585,7 +585,7 @@ void GBASavedataClean(struct GBASavedata* savedata, uint32_t frameCount) {
|
|||
}
|
||||
|
||||
void GBASavedataRTCWrite(struct GBASavedata* savedata) {
|
||||
if (!(savedata->gpio->devices & HW_RTC)) {
|
||||
if (!(savedata->gpio->devices & HW_RTC) || !savedata->vf || savedata->mapMode == MAP_READ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -595,9 +595,18 @@ void GBASavedataRTCWrite(struct GBASavedata* savedata) {
|
|||
buffer.control = savedata->gpio->rtc.control;
|
||||
STORE_64LE(savedata->gpio->rtc.lastLatch, 0, &buffer.lastLatch);
|
||||
|
||||
size_t size = GBASavedataSize(savedata) & ~0xFF;
|
||||
savedata->vf->seek(savedata->vf, size, SEEK_SET);
|
||||
size_t size = GBASavedataSize(savedata);
|
||||
savedata->vf->seek(savedata->vf, size & ~0xFF, SEEK_SET);
|
||||
|
||||
if ((savedata->vf->size(savedata->vf) & 0xFF) != sizeof(buffer)) {
|
||||
// Writing past the end of the file can invalidate the file mapping
|
||||
savedata->vf->unmap(savedata->vf, savedata->data, size);
|
||||
savedata->data = NULL;
|
||||
}
|
||||
savedata->vf->write(savedata->vf, &buffer, sizeof(buffer));
|
||||
if (!savedata->data) {
|
||||
savedata->data = savedata->vf->map(savedata->vf, size, MAP_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t _unBCD(uint8_t byte) {
|
||||
|
@ -605,6 +614,10 @@ static uint8_t _unBCD(uint8_t byte) {
|
|||
}
|
||||
|
||||
void GBASavedataRTCRead(struct GBASavedata* savedata) {
|
||||
if (!savedata->vf) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct GBASavedataRTCBuffer buffer;
|
||||
|
||||
size_t size = GBASavedataSize(savedata) & ~0xFF;
|
||||
|
|
|
@ -211,8 +211,7 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
|||
GBAMatrixDeserialize(gba, state);
|
||||
}
|
||||
|
||||
gba->timing.reroot = gba->timing.root;
|
||||
gba->timing.root = NULL;
|
||||
mTimingInterrupt(&gba->timing);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -12,14 +12,12 @@ CXX_GUARD_START
|
|||
|
||||
#ifdef USE_EPOXY
|
||||
#include <epoxy/gl.h>
|
||||
#elif defined(BUILD_GL)
|
||||
#ifdef __APPLE__
|
||||
#elif defined(__APPLE__)
|
||||
#include <OpenGL/gl3.h>
|
||||
#else
|
||||
#elif defined(BUILD_GL)
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#endif
|
||||
#elif defined(BUILD_GLES3)
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
|
|
|
@ -132,9 +132,17 @@ static enum GUIKeyboardStatus _keyboardRun(struct GUIKeyboardParams* keyboard) {
|
|||
utf16Buffer = params.inputTextBuffer;
|
||||
utf8Buffer = keyboard->result;
|
||||
i = keyboard->maxLen;
|
||||
while (i > 0 && *utf16Buffer) {
|
||||
uint32_t unichar = utf16Char((const uint16_t**) &utf16Buffer, &i);
|
||||
utf8Buffer += toUtf8(unichar, utf8Buffer);
|
||||
size_t bufferSize = sizeof(SceWChar16) * keyboard->maxLen;
|
||||
while (bufferSize && *utf16Buffer) {
|
||||
char buffer[4];
|
||||
uint32_t unichar = utf16Char((const uint16_t**) &utf16Buffer, &bufferSize);
|
||||
size_t bytes = toUtf8(unichar, buffer);
|
||||
if (i < bytes) {
|
||||
break;
|
||||
}
|
||||
memcpy(utf8Buffer, buffer, bytes);
|
||||
utf8Buffer += bytes;
|
||||
i -= bytes;
|
||||
}
|
||||
utf8Buffer[0] = 0;
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ if(NOT ${QT}Widgets_FOUND)
|
|||
endif()
|
||||
|
||||
if(APPLE)
|
||||
execute_process(COMMAND xcrun --show-sdk-version OUTPUT_VARIABLE MACOSX_SDK)
|
||||
if(MACOSX_SDK VERSION_GREATER 10.14)
|
||||
list(APPEND QT_DEFINES USE_SHARE_WIDGET)
|
||||
endif()
|
||||
|
|
|
@ -15,11 +15,8 @@ ColorPicker::ColorPicker() {
|
|||
|
||||
ColorPicker::ColorPicker(QWidget* parent, const QColor& defaultColor)
|
||||
: m_parent(parent)
|
||||
, m_defaultColor(defaultColor)
|
||||
{
|
||||
QPalette palette = parent->palette();
|
||||
palette.setColor(parent->backgroundRole(), defaultColor);
|
||||
parent->setPalette(palette);
|
||||
setColor(defaultColor);
|
||||
parent->installEventFilter(this);
|
||||
}
|
||||
|
||||
|
@ -36,10 +33,7 @@ ColorPicker& ColorPicker::operator=(const ColorPicker& other) {
|
|||
|
||||
void ColorPicker::setColor(const QColor& color) {
|
||||
m_defaultColor = color;
|
||||
|
||||
QPalette palette = m_parent->palette();
|
||||
palette.setColor(m_parent->backgroundRole(), color);
|
||||
m_parent->setPalette(palette);
|
||||
m_parent->setStyleSheet(QString("background-color: %1;").arg(color.name()));
|
||||
}
|
||||
|
||||
bool ColorPicker::eventFilter(QObject* obj, QEvent* event) {
|
||||
|
@ -57,10 +51,7 @@ bool ColorPicker::eventFilter(QObject* obj, QEvent* event) {
|
|||
colorPicker->setCurrentColor(m_defaultColor);
|
||||
colorPicker->open();
|
||||
connect(colorPicker, &QColorDialog::colorSelected, [this, swatch](const QColor& color) {
|
||||
m_defaultColor = color;
|
||||
QPalette palette = swatch->palette();
|
||||
palette.setColor(swatch->backgroundRole(), color);
|
||||
swatch->setPalette(palette);
|
||||
setColor(color);
|
||||
emit colorChanged(color);
|
||||
});
|
||||
return true;
|
||||
|
|
|
@ -83,6 +83,7 @@ void mGLWidget::initializeGL() {
|
|||
m_positionLocation = m_program->attributeLocation("position");
|
||||
|
||||
m_vaoDone = false;
|
||||
m_tex = 0;
|
||||
|
||||
connect(&m_refresh, &QTimer::timeout, this, static_cast<void (QWidget::*)()>(&QWidget::update));
|
||||
}
|
||||
|
@ -115,6 +116,10 @@ void mGLWidget::paintGL() {
|
|||
if (!m_vaoDone && !finalizeVAO()) {
|
||||
return;
|
||||
}
|
||||
if (!m_tex) {
|
||||
m_refresh.start(10);
|
||||
return;
|
||||
}
|
||||
QOpenGLFunctions_Baseline* fn = context()->versionFunctions<QOpenGLFunctions_Baseline>();
|
||||
m_program->bind();
|
||||
m_vao->bind();
|
||||
|
@ -523,7 +528,6 @@ void PainterGL::create() {
|
|||
|
||||
m_finalTexIdx = 0;
|
||||
gl2Backend->finalShader.tex = m_finalTex[m_finalTexIdx];
|
||||
m_widget->setTex(m_finalTex[m_finalTexIdx]);
|
||||
}
|
||||
m_shader.preprocessShader = static_cast<void*>(&reinterpret_cast<mGLES2Context*>(m_backend)->initialShader);
|
||||
}
|
||||
|
|
|
@ -1187,6 +1187,11 @@ void Window::changeRenderer() {
|
|||
m_config->updateOption("videoScale");
|
||||
}
|
||||
} else {
|
||||
std::shared_ptr<VideoProxy> proxy = m_display->videoProxy();
|
||||
if (proxy) {
|
||||
proxy->detach(m_controller.get());
|
||||
m_display->setVideoProxy({});
|
||||
}
|
||||
m_controller->setFramebufferHandle(-1);
|
||||
}
|
||||
}
|
||||
|
@ -1388,7 +1393,6 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
m_actions.addAction(tr("Boot BIOS"), "bootBIOS", this, &Window::bootBIOS, "file");
|
||||
#endif
|
||||
|
||||
addGameAction(tr("Replace ROM..."), "replaceROM", this, &Window::replaceROM, "file");
|
||||
#ifdef M_CORE_GBA
|
||||
Action* scanCard = addGameAction(tr("Scan e-Reader dotcodes..."), "scanCard", this, &Window::scanCard, "file");
|
||||
m_platformActions.insert(mPLATFORM_GBA, scanCard);
|
||||
|
@ -1499,10 +1503,12 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
|
||||
addGameAction(tr("&Reset"), "reset", &CoreController::reset, "emu", QKeySequence("Ctrl+R"));
|
||||
addGameAction(tr("Sh&utdown"), "shutdown", &CoreController::stop, "emu");
|
||||
m_actions.addSeparator("emu");
|
||||
|
||||
addGameAction(tr("Replace ROM..."), "replaceROM", this, &Window::replaceROM, "emu");
|
||||
Action* yank = addGameAction(tr("Yank game pak"), "yank", &CoreController::yankPak, "emu");
|
||||
m_platformActions.insert(mPLATFORM_GBA, yank);
|
||||
m_platformActions.insert(mPLATFORM_GB, yank);
|
||||
|
||||
m_actions.addSeparator("emu");
|
||||
|
||||
Action* pause = m_actions.addBooleanAction(tr("&Pause"), "pause", [this](bool paused) {
|
||||
|
|
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
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
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
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
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
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
|
@ -144,7 +144,7 @@ uint32_t utf8Char(const char** unicode, size_t* length) {
|
|||
if (numBytes == 0) {
|
||||
return 0xFFFD;
|
||||
}
|
||||
if (*length < numBytes) {
|
||||
if (*length + 1 < numBytes) {
|
||||
*length = 0;
|
||||
return 0xFFFD;
|
||||
}
|
||||
|
|
|
@ -8,125 +8,140 @@
|
|||
#include <mgba-util/string.h>
|
||||
|
||||
M_TEST_DEFINE(strlenASCII) {
|
||||
assert_int_equal(utf8strlen(""), 0);
|
||||
assert_int_equal(utf8strlen("a"), 1);
|
||||
assert_int_equal(utf8strlen("aa"), 2);
|
||||
assert_int_equal(utf8strlen("aaa"), 3);
|
||||
assert_int_equal(utf8strlen(""), 0);
|
||||
assert_int_equal(utf8strlen("a"), 1);
|
||||
assert_int_equal(utf8strlen("aa"), 2);
|
||||
assert_int_equal(utf8strlen("aaa"), 3);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(strlenMultibyte) {
|
||||
assert_int_equal(utf8strlen("\300\200"), 1);
|
||||
assert_int_equal(utf8strlen("a\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\300\200a"), 2);
|
||||
assert_int_equal(utf8strlen("a\300\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\300\200"), 1);
|
||||
assert_int_equal(utf8strlen("a\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\300\200a"), 2);
|
||||
assert_int_equal(utf8strlen("a\300\200a"), 3);
|
||||
|
||||
assert_int_equal(utf8strlen("\300\200\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("a\300\200\300\200"), 3);
|
||||
assert_int_equal(utf8strlen("\300\200a\300\200"), 3);
|
||||
assert_int_equal(utf8strlen("\300\200\300\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\300\200\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("a\300\200\300\200"), 3);
|
||||
assert_int_equal(utf8strlen("\300\200a\300\200"), 3);
|
||||
assert_int_equal(utf8strlen("\300\200\300\200a"), 3);
|
||||
|
||||
assert_int_equal(utf8strlen("\340\200\200"), 1);
|
||||
assert_int_equal(utf8strlen("a\340\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200\200a"), 2);
|
||||
assert_int_equal(utf8strlen("a\340\200\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\340\200\200"), 1);
|
||||
assert_int_equal(utf8strlen("a\340\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200\200a"), 2);
|
||||
assert_int_equal(utf8strlen("a\340\200\200a"), 3);
|
||||
|
||||
assert_int_equal(utf8strlen("\340\200\200\340\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("a\340\200\200\340\200\200"), 3);
|
||||
assert_int_equal(utf8strlen("\340\200\200a\340\200\200"), 3);
|
||||
assert_int_equal(utf8strlen("\340\200\200\340\200\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\340\200\200\340\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("a\340\200\200\340\200\200"), 3);
|
||||
assert_int_equal(utf8strlen("\340\200\200a\340\200\200"), 3);
|
||||
assert_int_equal(utf8strlen("\340\200\200\340\200\200a"), 3);
|
||||
|
||||
assert_int_equal(utf8strlen("\340\200\200\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\300\200\340\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200\200\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\300\200\340\200\200"), 2);
|
||||
|
||||
assert_int_equal(utf8strlen("\360\200\200\200"), 1);
|
||||
assert_int_equal(utf8strlen("a\360\200\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200\200\200a"), 2);
|
||||
assert_int_equal(utf8strlen("a\360\200\200\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\360\200\200\200"), 1);
|
||||
assert_int_equal(utf8strlen("a\360\200\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200\200\200a"), 2);
|
||||
assert_int_equal(utf8strlen("a\360\200\200\200a"), 3);
|
||||
|
||||
assert_int_equal(utf8strlen("\360\200\200\200\360\200\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("a\360\200\200\200\360\200\200\200"), 3);
|
||||
assert_int_equal(utf8strlen("\360\200\200\200a\360\200\200\200"), 3);
|
||||
assert_int_equal(utf8strlen("\360\200\200\200\360\200\200\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\360\200\200\200\360\200\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("a\360\200\200\200\360\200\200\200"), 3);
|
||||
assert_int_equal(utf8strlen("\360\200\200\200a\360\200\200\200"), 3);
|
||||
assert_int_equal(utf8strlen("\360\200\200\200\360\200\200\200a"), 3);
|
||||
|
||||
assert_int_equal(utf8strlen("\360\200\200\200\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\300\200\360\200\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200\200\200\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\300\200\360\200\200\200"), 2);
|
||||
|
||||
assert_int_equal(utf8strlen("\360\200\200\200\340\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200\200\360\200\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200\200\200\340\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200\200\360\200\200\200"), 2);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(strlenDegenerate) {
|
||||
assert_int_equal(utf8strlen("\200"), 1);
|
||||
assert_int_equal(utf8strlen("\200a"), 2);
|
||||
assert_int_equal(utf8strlen("\200"), 1);
|
||||
assert_int_equal(utf8strlen("\200a"), 2);
|
||||
|
||||
assert_int_equal(utf8strlen("\300"), 1);
|
||||
assert_int_equal(utf8strlen("\300a"), 2);
|
||||
assert_int_equal(utf8strlen("\300"), 1);
|
||||
assert_int_equal(utf8strlen("\300a"), 2);
|
||||
|
||||
assert_int_equal(utf8strlen("\300\300"), 2);
|
||||
assert_int_equal(utf8strlen("\300\300a"), 3);
|
||||
assert_int_equal(utf8strlen("\300\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\300\300"), 2);
|
||||
assert_int_equal(utf8strlen("\300\300a"), 3);
|
||||
assert_int_equal(utf8strlen("\300\300\200"), 2);
|
||||
|
||||
assert_int_equal(utf8strlen("\300\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\300\200\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\300\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\300\200\200a"), 3);
|
||||
|
||||
assert_int_equal(utf8strlen("\340"), 1);
|
||||
assert_int_equal(utf8strlen("\340a"), 2);
|
||||
assert_int_equal(utf8strlen("\340\300"), 2);
|
||||
assert_int_equal(utf8strlen("\340\300a"), 3);
|
||||
assert_int_equal(utf8strlen("\340\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200"), 1);
|
||||
assert_int_equal(utf8strlen("\340\200a"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200\200\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\340"), 1);
|
||||
assert_int_equal(utf8strlen("\340a"), 2);
|
||||
assert_int_equal(utf8strlen("\340\300"), 2);
|
||||
assert_int_equal(utf8strlen("\340\300a"), 3);
|
||||
assert_int_equal(utf8strlen("\340\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200"), 1);
|
||||
assert_int_equal(utf8strlen("\340\200a"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200\200\200"), 2);
|
||||
assert_int_equal(utf8strlen("\340\200\200\200a"), 3);
|
||||
|
||||
assert_int_equal(utf8strlen("\360"), 1);
|
||||
assert_int_equal(utf8strlen("\360a"), 2);
|
||||
assert_int_equal(utf8strlen("\360\300"), 2);
|
||||
assert_int_equal(utf8strlen("\360\300a"), 3);
|
||||
assert_int_equal(utf8strlen("\360\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200"), 1);
|
||||
assert_int_equal(utf8strlen("\360\200a"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200\300"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200\300a"), 3);
|
||||
assert_int_equal(utf8strlen("\360\200\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200\200"), 1);
|
||||
assert_int_equal(utf8strlen("\360\200\200a"), 2);
|
||||
assert_int_equal(utf8strlen("\360"), 1);
|
||||
assert_int_equal(utf8strlen("\360a"), 2);
|
||||
assert_int_equal(utf8strlen("\360\300"), 2);
|
||||
assert_int_equal(utf8strlen("\360\300a"), 3);
|
||||
assert_int_equal(utf8strlen("\360\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200"), 1);
|
||||
assert_int_equal(utf8strlen("\360\200a"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200\300"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200\300a"), 3);
|
||||
assert_int_equal(utf8strlen("\360\200\300\200"), 2);
|
||||
assert_int_equal(utf8strlen("\360\200\200"), 1);
|
||||
assert_int_equal(utf8strlen("\360\200\200a"), 2);
|
||||
|
||||
assert_int_equal(utf8strlen("\370"), 1);
|
||||
assert_int_equal(utf8strlen("\370a"), 2);
|
||||
assert_int_equal(utf8strlen("\370\200"), 2);
|
||||
assert_int_equal(utf8strlen("\370\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\374"), 1);
|
||||
assert_int_equal(utf8strlen("\374a"), 2);
|
||||
assert_int_equal(utf8strlen("\374\200"), 2);
|
||||
assert_int_equal(utf8strlen("\374\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\376"), 1);
|
||||
assert_int_equal(utf8strlen("\376a"), 2);
|
||||
assert_int_equal(utf8strlen("\376\200"), 2);
|
||||
assert_int_equal(utf8strlen("\376\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\377"), 1);
|
||||
assert_int_equal(utf8strlen("\377a"), 2);
|
||||
assert_int_equal(utf8strlen("\377\200"), 2);
|
||||
assert_int_equal(utf8strlen("\377\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\370"), 1);
|
||||
assert_int_equal(utf8strlen("\370a"), 2);
|
||||
assert_int_equal(utf8strlen("\370\200"), 2);
|
||||
assert_int_equal(utf8strlen("\370\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\374"), 1);
|
||||
assert_int_equal(utf8strlen("\374a"), 2);
|
||||
assert_int_equal(utf8strlen("\374\200"), 2);
|
||||
assert_int_equal(utf8strlen("\374\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\376"), 1);
|
||||
assert_int_equal(utf8strlen("\376a"), 2);
|
||||
assert_int_equal(utf8strlen("\376\200"), 2);
|
||||
assert_int_equal(utf8strlen("\376\200a"), 3);
|
||||
assert_int_equal(utf8strlen("\377"), 1);
|
||||
assert_int_equal(utf8strlen("\377a"), 2);
|
||||
assert_int_equal(utf8strlen("\377\200"), 2);
|
||||
assert_int_equal(utf8strlen("\377\200a"), 3);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(roundtrip) {
|
||||
uint32_t unichar;
|
||||
char buf[8] = {0};
|
||||
for (unichar = 0; unichar < 0x110000; ++unichar) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
size_t len = toUtf8(unichar, buf) + 1;
|
||||
const char* ptr = buf;
|
||||
assert_true(len);
|
||||
assert_false(buf[len]);
|
||||
assert_int_equal(utf8Char(&ptr, &len), unichar);
|
||||
assert_int_equal(len, 1);
|
||||
}
|
||||
uint32_t unichar;
|
||||
char buf[8] = {0};
|
||||
for (unichar = 0; unichar < 0x110000; ++unichar) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
size_t len = toUtf8(unichar, buf) + 1;
|
||||
const char* ptr = buf;
|
||||
assert_true(len);
|
||||
assert_false(buf[len]);
|
||||
assert_int_equal(utf8Char(&ptr, &len), unichar);
|
||||
assert_int_equal(len, 1);
|
||||
}
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(roundtripUnpadded) {
|
||||
uint32_t unichar;
|
||||
char buf[8] = {0};
|
||||
for (unichar = 0; unichar < 0x110000; ++unichar) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
size_t len = toUtf8(unichar, buf);
|
||||
const char* ptr = buf;
|
||||
assert_true(len);
|
||||
assert_false(buf[len]);
|
||||
assert_int_equal(utf8Char(&ptr, &len), unichar);
|
||||
assert_int_equal(len, 0);
|
||||
}
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE(StringUTF8,
|
||||
cmocka_unit_test(strlenASCII),
|
||||
cmocka_unit_test(strlenMultibyte),
|
||||
cmocka_unit_test(strlenDegenerate),
|
||||
cmocka_unit_test(roundtrip),
|
||||
cmocka_unit_test(strlenASCII),
|
||||
cmocka_unit_test(strlenMultibyte),
|
||||
cmocka_unit_test(strlenDegenerate),
|
||||
cmocka_unit_test(roundtrip),
|
||||
cmocka_unit_test(roundtripUnpadded),
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue