Merge branch 'master' (early part) into medusa
4
CHANGES
|
@ -91,6 +91,8 @@ Emulation fixes:
|
|||
- GBA Video: Fix sprite layer priority updating in GL
|
||||
Other fixes:
|
||||
- ARM: Disassemble Thumb mov pseudo-instruction properly
|
||||
- ARM: Disassemble ARM asr/lsr #32 properly
|
||||
- ARM: Disassemble ARM movs properly
|
||||
- Core: Don't attempt to restore rewind diffs past start of rewind
|
||||
- Core: Fix the runloop resuming after a game has crashed (fixes mgba.io/i/2451)
|
||||
- Core: Fix crash if library can't be opened
|
||||
|
@ -98,12 +100,14 @@ Other fixes:
|
|||
- FFmpeg: Fix crash when encoding audio with some containers
|
||||
- FFmpeg: Fix GIF recording (fixes mgba.io/i/2393)
|
||||
- GB: Fix temporary saves
|
||||
- GB: Fix replacing the ROM crashing when accessing ROM base
|
||||
- GB, GBA: Save writeback-pending masked saves on unload (fixes mgba.io/i/2396)
|
||||
- mGUI: Fix FPS counter after closing menu
|
||||
- Qt: Fix some hangs when using the debugger console
|
||||
- Qt: Fix crash when clicking past last tile in viewer
|
||||
- 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
|
||||
- VFS: Failed file mapping should return NULL on POSIX
|
||||
Misc:
|
||||
- Core: Suspend runloop when a core crashes
|
||||
|
|
|
@ -771,6 +771,7 @@ if(ENABLE_SCRIPTING)
|
|||
include_directories(AFTER ${LUA_INCLUDE_DIR})
|
||||
list(APPEND FEATURE_DEFINES LUA_VERSION_ONLY=\"${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}\")
|
||||
list(APPEND DEPENDENCY_LIB ${LUA_LIBRARY})
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},liblua${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}-0")
|
||||
endif()
|
||||
|
||||
if(BUILD_PYTHON)
|
||||
|
|
|
@ -142,11 +142,13 @@ Compiling requires using CMake 3.1 or newer. GCC and Clang are both known to wor
|
|||
|
||||
The recommended way to build for most platforms is to use Docker. Several Docker images are provided that contain the requisite toolchain and dependencies for building mGBA across several platforms.
|
||||
|
||||
Note: If you are on an older Windows system before Windows 10, you may need to configure your Docker to use VirtualBox shared folders to correctly map your current `mgba` checkout directory to the Docker image's working directory. (See issue [#1985](https://mgba.io/i/1985) for details.)
|
||||
|
||||
To use a Docker image to build mGBA, simply run the following command while in the root of an mGBA checkout:
|
||||
|
||||
docker run --rm -t -v $PWD:/home/mgba/src mgba/windows:w32
|
||||
docker run --rm -it -v ${PWD}:/home/mgba/src mgba/windows:w32
|
||||
|
||||
This will produce a `build-win32` directory with the build products. Replace `mgba/windows:w32` with another Docker image for other platforms, which will produce a corresponding other directory. The following Docker images available on Docker Hub:
|
||||
After starting the Docker container, it will produce a `build-win32` directory with the build products. Replace `mgba/windows:w32` with another Docker image for other platforms, which will produce a corresponding other directory. The following Docker images available on Docker Hub:
|
||||
|
||||
- mgba/3ds
|
||||
- mgba/switch
|
||||
|
@ -159,6 +161,8 @@ This will produce a `build-win32` directory with the build products. Replace `mg
|
|||
- mgba/windows:w32
|
||||
- mgba/windows:w64
|
||||
|
||||
If you want to speed up the build process, consider adding the flag `-e MAKEFLAGS=-jN` to do a parallel build for mGBA with `N` number of CPU cores.
|
||||
|
||||
#### *nix building
|
||||
|
||||
To use CMake to build on a Unix-based system, the recommended commands are as follows:
|
||||
|
|
|
@ -88,6 +88,7 @@ struct mCore {
|
|||
bool (*loadSave)(struct mCore*, struct VFile* vf);
|
||||
bool (*loadTemporarySave)(struct mCore*, struct VFile* vf);
|
||||
void (*unloadROM)(struct mCore*);
|
||||
size_t (*romSize)(const struct mCore*);
|
||||
void (*checksum)(const struct mCore*, void* data, enum mCoreChecksumType type);
|
||||
|
||||
bool (*loadBIOS)(struct mCore*, struct VFile* vf, int biosID);
|
||||
|
@ -186,6 +187,8 @@ bool mCoreAutoloadSave(struct mCore* core);
|
|||
bool mCoreAutoloadPatch(struct mCore* core);
|
||||
bool mCoreAutoloadCheats(struct mCore* core);
|
||||
|
||||
bool mCoreLoadSaveFile(struct mCore* core, const char* path, bool temporary);
|
||||
|
||||
bool mCoreSaveState(struct mCore* core, int slot, int flags);
|
||||
bool mCoreLoadState(struct mCore* core, int slot, int flags);
|
||||
struct VFile* mCoreGetState(struct mCore* core, int slot, bool write);
|
||||
|
|
|
@ -36,6 +36,12 @@ struct mLogger {
|
|||
struct mLogFilter* filter;
|
||||
};
|
||||
|
||||
struct mStandardLogger {
|
||||
struct mLogger d;
|
||||
bool logToStdout;
|
||||
struct VFile* logFile;
|
||||
};
|
||||
|
||||
struct mLogger* mLogGetContext(void);
|
||||
void mLogSetDefaultLogger(struct mLogger*);
|
||||
int mLogGenerateCategory(const char*, const char*);
|
||||
|
@ -44,6 +50,10 @@ const char* mLogCategoryId(int);
|
|||
int mLogCategoryById(const char*);
|
||||
|
||||
struct mCoreConfig;
|
||||
void mStandardLoggerInit(struct mStandardLogger*);
|
||||
void mStandardLoggerDeinit(struct mStandardLogger*);
|
||||
void mStandardLoggerConfig(struct mStandardLogger*, struct mCoreConfig* config);
|
||||
|
||||
void mLogFilterInit(struct mLogFilter*);
|
||||
void mLogFilterDeinit(struct mLogFilter*);
|
||||
void mLogFilterLoad(struct mLogFilter*, const struct mCoreConfig*);
|
||||
|
|
|
@ -21,6 +21,7 @@ struct mCoreThread;
|
|||
struct mThreadLogger {
|
||||
struct mLogger d;
|
||||
struct mCoreThread* p;
|
||||
struct mLogger* logger;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
|
|
|
@ -67,10 +67,11 @@ struct ParseTree {
|
|||
};
|
||||
|
||||
size_t lexExpression(struct LexVector* lv, const char* string, size_t length, const char* eol);
|
||||
void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv);
|
||||
|
||||
void lexFree(struct LexVector* lv);
|
||||
|
||||
struct ParseTree* parseTreeCreate(void);
|
||||
void parseFree(struct ParseTree* tree);
|
||||
bool parseLexedExpression(struct ParseTree* tree, struct LexVector* lv);
|
||||
|
||||
struct mDebugger;
|
||||
bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, int32_t* value, int* segment);
|
||||
|
|
|
@ -155,6 +155,7 @@ struct GBAVideoGLRenderer {
|
|||
GLuint vbo;
|
||||
|
||||
GLuint outputTex;
|
||||
bool outputTexDirty;
|
||||
|
||||
GLuint paletteTex;
|
||||
uint16_t shadowPalette[GBA_VIDEO_VERTICAL_PIXELS][512];
|
||||
|
|
|
@ -459,6 +459,7 @@ CXX_GUARD_START
|
|||
#define mSCRIPT_MAKE_S64(VALUE) mSCRIPT_MAKE(S64, VALUE)
|
||||
#define mSCRIPT_MAKE_U64(VALUE) mSCRIPT_MAKE(U64, VALUE)
|
||||
#define mSCRIPT_MAKE_F64(VALUE) mSCRIPT_MAKE(F64, VALUE)
|
||||
#define mSCRIPT_MAKE_BOOL(VALUE) mSCRIPT_MAKE(BOOL, VALUE)
|
||||
#define mSCRIPT_MAKE_CHARP(VALUE) mSCRIPT_MAKE(CHARP, VALUE)
|
||||
#define mSCRIPT_MAKE_S(STRUCT, VALUE) mSCRIPT_MAKE(S(STRUCT), VALUE)
|
||||
#define mSCRIPT_MAKE_CS(STRUCT, VALUE) mSCRIPT_MAKE(CS(STRUCT), VALUE)
|
||||
|
|
|
@ -27,6 +27,7 @@ CXX_GUARD_START
|
|||
#define mSCRIPT_TYPE_C_S64 int64_t
|
||||
#define mSCRIPT_TYPE_C_U64 uint64_t
|
||||
#define mSCRIPT_TYPE_C_F64 double
|
||||
#define mSCRIPT_TYPE_C_BOOL bool
|
||||
#define mSCRIPT_TYPE_C_STR struct mScriptString*
|
||||
#define mSCRIPT_TYPE_C_CHARP const char*
|
||||
#define mSCRIPT_TYPE_C_PTR void*
|
||||
|
@ -55,6 +56,7 @@ CXX_GUARD_START
|
|||
#define mSCRIPT_TYPE_FIELD_S64 s64
|
||||
#define mSCRIPT_TYPE_FIELD_U64 u64
|
||||
#define mSCRIPT_TYPE_FIELD_F64 f64
|
||||
#define mSCRIPT_TYPE_FIELD_BOOL u32
|
||||
#define mSCRIPT_TYPE_FIELD_STR string
|
||||
#define mSCRIPT_TYPE_FIELD_CHARP copaque
|
||||
#define mSCRIPT_TYPE_FIELD_PTR opaque
|
||||
|
@ -82,6 +84,7 @@ CXX_GUARD_START
|
|||
#define mSCRIPT_TYPE_MS_S64 (&mSTSInt64)
|
||||
#define mSCRIPT_TYPE_MS_U64 (&mSTUInt64)
|
||||
#define mSCRIPT_TYPE_MS_F64 (&mSTFloat64)
|
||||
#define mSCRIPT_TYPE_MS_BOOL (&mSTBool)
|
||||
#define mSCRIPT_TYPE_MS_STR (&mSTString)
|
||||
#define mSCRIPT_TYPE_MS_CHARP (&mSTCharPtr)
|
||||
#define mSCRIPT_TYPE_MS_LIST (&mSTList)
|
||||
|
@ -109,6 +112,7 @@ CXX_GUARD_START
|
|||
#define mSCRIPT_TYPE_CMP_U64(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_U64, TYPE)
|
||||
#define mSCRIPT_TYPE_CMP_S64(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_S64, TYPE)
|
||||
#define mSCRIPT_TYPE_CMP_F64(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_F64, TYPE)
|
||||
#define mSCRIPT_TYPE_CMP_BOOL(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_BOOL, TYPE)
|
||||
#define mSCRIPT_TYPE_CMP_STR(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_STR, TYPE)
|
||||
#define mSCRIPT_TYPE_CMP_CHARP(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_CHARP, TYPE)
|
||||
#define mSCRIPT_TYPE_CMP_LIST(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_LIST, TYPE)
|
||||
|
@ -165,6 +169,7 @@ extern const struct mScriptType mSTFloat32;
|
|||
extern const struct mScriptType mSTSInt64;
|
||||
extern const struct mScriptType mSTUInt64;
|
||||
extern const struct mScriptType mSTFloat64;
|
||||
extern const struct mScriptType mSTBool;
|
||||
extern const struct mScriptType mSTString;
|
||||
extern const struct mScriptType mSTCharPtr;
|
||||
extern const struct mScriptType mSTList;
|
||||
|
@ -329,6 +334,7 @@ bool mScriptPopF32(struct mScriptList* list, float* out);
|
|||
bool mScriptPopS64(struct mScriptList* list, int64_t* out);
|
||||
bool mScriptPopU64(struct mScriptList* list, uint64_t* out);
|
||||
bool mScriptPopF64(struct mScriptList* list, double* out);
|
||||
bool mScriptPopBool(struct mScriptList* list, bool* out);
|
||||
bool mScriptPopPointer(struct mScriptList* list, void** out);
|
||||
|
||||
bool mScriptCast(const struct mScriptType* type, const struct mScriptValue* input, struct mScriptValue* output);
|
||||
|
|
After Width: | Height: | Size: 443 B |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 676 B |
After Width: | Height: | Size: 509 B |
After Width: | Height: | Size: 782 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 390 B |
After Width: | Height: | Size: 548 B |
After Width: | Height: | Size: 677 B |
|
@ -19,6 +19,9 @@
|
|||
info->operandFormat |= ARM_OPERAND_SHIFT_REGISTER_3; \
|
||||
} else { \
|
||||
info->op3.shifterImm = (opcode >> 7) & 0x1F; \
|
||||
if (!info->op3.shifterImm && (ARM_SHIFT_ ## OP == ARM_SHIFT_LSR || ARM_SHIFT_ ## OP == ARM_SHIFT_ASR)) { \
|
||||
info->op3.shifterImm = 32; \
|
||||
} \
|
||||
info->operandFormat |= ARM_OPERAND_SHIFT_IMMEDIATE_3; \
|
||||
}
|
||||
|
||||
|
|
|
@ -190,6 +190,9 @@ static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, con
|
|||
case 4:
|
||||
value = cpu->memory.load32(cpu, addrBase, NULL);
|
||||
break;
|
||||
default:
|
||||
// Should never be reached
|
||||
abort();
|
||||
}
|
||||
const char* label = NULL;
|
||||
if (symbols) {
|
||||
|
@ -432,6 +435,7 @@ int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* cpu, c
|
|||
case ARM_MN_LSR:
|
||||
case ARM_MN_MLA:
|
||||
case ARM_MN_MUL:
|
||||
case ARM_MN_MOV:
|
||||
case ARM_MN_MVN:
|
||||
case ARM_MN_ORR:
|
||||
case ARM_MN_ROR:
|
||||
|
|
|
@ -272,6 +272,18 @@ bool mCoreAutoloadCheats(struct mCore* core) {
|
|||
return success;
|
||||
}
|
||||
|
||||
bool mCoreLoadSaveFile(struct mCore* core, const char* path, bool temporary) {
|
||||
struct VFile* vf = VFileOpen(path, O_CREAT | O_RDWR);
|
||||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
if (temporary) {
|
||||
return core->loadTemporarySave(core, vf);
|
||||
} else {
|
||||
return core->loadSave(core, vf);
|
||||
}
|
||||
}
|
||||
|
||||
bool mCoreSaveState(struct mCore* core, int slot, int flags) {
|
||||
struct VFile* vf = mCoreGetState(core, slot, true);
|
||||
if (!vf) {
|
||||
|
@ -370,6 +382,8 @@ bool mCoreTakeScreenshotVF(struct mCore* core, struct VFile* vf) {
|
|||
PNGWriteClose(png, info);
|
||||
return success;
|
||||
#else
|
||||
UNUSED(core);
|
||||
UNUSED(vf);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -10,92 +10,53 @@
|
|||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
void mDirectorySetInit(struct mDirectorySet* dirs) {
|
||||
dirs->base = 0;
|
||||
dirs->archive = 0;
|
||||
dirs->save = 0;
|
||||
dirs->patch = 0;
|
||||
dirs->state = 0;
|
||||
dirs->screenshot = 0;
|
||||
dirs->cheats = 0;
|
||||
dirs->base = NULL;
|
||||
dirs->archive = NULL;
|
||||
dirs->save = NULL;
|
||||
dirs->patch = NULL;
|
||||
dirs->state = NULL;
|
||||
dirs->screenshot = NULL;
|
||||
dirs->cheats = NULL;
|
||||
}
|
||||
|
||||
static void mDirectorySetDetachDir(struct mDirectorySet* dirs, struct VDir* dir) {
|
||||
if (!dir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dirs->base == dir) {
|
||||
dirs->base = NULL;
|
||||
}
|
||||
if (dirs->archive == dir) {
|
||||
dirs->archive = NULL;
|
||||
}
|
||||
if (dirs->save == dir) {
|
||||
dirs->save = NULL;
|
||||
}
|
||||
if (dirs->patch == dir) {
|
||||
dirs->patch = NULL;
|
||||
}
|
||||
if (dirs->state == dir) {
|
||||
dirs->state = NULL;
|
||||
}
|
||||
if (dirs->screenshot == dir) {
|
||||
dirs->screenshot = NULL;
|
||||
}
|
||||
if (dirs->cheats == dir) {
|
||||
dirs->cheats = NULL;
|
||||
}
|
||||
|
||||
dir->close(dir);
|
||||
}
|
||||
|
||||
void mDirectorySetDeinit(struct mDirectorySet* dirs) {
|
||||
mDirectorySetDetachBase(dirs);
|
||||
|
||||
if (dirs->archive) {
|
||||
if (dirs->archive == dirs->save) {
|
||||
dirs->save = NULL;
|
||||
}
|
||||
if (dirs->archive == dirs->patch) {
|
||||
dirs->patch = NULL;
|
||||
}
|
||||
if (dirs->archive == dirs->state) {
|
||||
dirs->state = NULL;
|
||||
}
|
||||
if (dirs->archive == dirs->screenshot) {
|
||||
dirs->screenshot = NULL;
|
||||
}
|
||||
if (dirs->archive == dirs->cheats) {
|
||||
dirs->cheats = NULL;
|
||||
}
|
||||
dirs->archive->close(dirs->archive);
|
||||
dirs->archive = NULL;
|
||||
}
|
||||
|
||||
if (dirs->save) {
|
||||
if (dirs->save == dirs->patch) {
|
||||
dirs->patch = NULL;
|
||||
}
|
||||
if (dirs->save == dirs->state) {
|
||||
dirs->state = NULL;
|
||||
}
|
||||
if (dirs->save == dirs->screenshot) {
|
||||
dirs->screenshot = NULL;
|
||||
}
|
||||
if (dirs->save == dirs->cheats) {
|
||||
dirs->cheats = NULL;
|
||||
}
|
||||
dirs->save->close(dirs->save);
|
||||
dirs->save = NULL;
|
||||
}
|
||||
|
||||
if (dirs->patch) {
|
||||
if (dirs->patch == dirs->state) {
|
||||
dirs->state = NULL;
|
||||
}
|
||||
if (dirs->patch == dirs->screenshot) {
|
||||
dirs->screenshot = NULL;
|
||||
}
|
||||
if (dirs->patch == dirs->cheats) {
|
||||
dirs->cheats = NULL;
|
||||
}
|
||||
dirs->patch->close(dirs->patch);
|
||||
dirs->patch = NULL;
|
||||
}
|
||||
|
||||
if (dirs->state) {
|
||||
if (dirs->state == dirs->screenshot) {
|
||||
dirs->state = NULL;
|
||||
}
|
||||
if (dirs->state == dirs->cheats) {
|
||||
dirs->cheats = NULL;
|
||||
}
|
||||
dirs->state->close(dirs->state);
|
||||
dirs->state = NULL;
|
||||
}
|
||||
|
||||
if (dirs->screenshot) {
|
||||
if (dirs->screenshot == dirs->cheats) {
|
||||
dirs->cheats = NULL;
|
||||
}
|
||||
dirs->screenshot->close(dirs->screenshot);
|
||||
dirs->screenshot = NULL;
|
||||
}
|
||||
|
||||
if (dirs->cheats) {
|
||||
dirs->cheats->close(dirs->cheats);
|
||||
dirs->cheats = NULL;
|
||||
}
|
||||
mDirectorySetDetachDir(dirs, dirs->archive);
|
||||
mDirectorySetDetachDir(dirs, dirs->save);
|
||||
mDirectorySetDetachDir(dirs, dirs->patch);
|
||||
mDirectorySetDetachDir(dirs, dirs->state);
|
||||
mDirectorySetDetachDir(dirs, dirs->screenshot);
|
||||
mDirectorySetDetachDir(dirs, dirs->cheats);
|
||||
}
|
||||
|
||||
void mDirectorySetAttachBase(struct mDirectorySet* dirs, struct VDir* base) {
|
||||
|
@ -118,36 +79,20 @@ void mDirectorySetAttachBase(struct mDirectorySet* dirs, struct VDir* base) {
|
|||
}
|
||||
|
||||
void mDirectorySetDetachBase(struct mDirectorySet* dirs) {
|
||||
if (dirs->save == dirs->base) {
|
||||
dirs->save = NULL;
|
||||
}
|
||||
if (dirs->patch == dirs->base) {
|
||||
dirs->patch = NULL;
|
||||
}
|
||||
if (dirs->state == dirs->base) {
|
||||
dirs->state = NULL;
|
||||
}
|
||||
if (dirs->screenshot == dirs->base) {
|
||||
dirs->screenshot = NULL;
|
||||
}
|
||||
if (dirs->cheats == dirs->base) {
|
||||
dirs->cheats = NULL;
|
||||
}
|
||||
|
||||
if (dirs->base) {
|
||||
dirs->base->close(dirs->base);
|
||||
dirs->base = NULL;
|
||||
}
|
||||
mDirectorySetDetachDir(dirs, dirs->archive);
|
||||
mDirectorySetDetachDir(dirs, dirs->base);
|
||||
}
|
||||
|
||||
struct VFile* mDirectorySetOpenPath(struct mDirectorySet* dirs, const char* path, bool (*filter)(struct VFile*)) {
|
||||
dirs->archive = VDirOpenArchive(path);
|
||||
struct VDir* archive = VDirOpenArchive(path);
|
||||
struct VFile* file;
|
||||
if (dirs->archive) {
|
||||
file = VDirFindFirst(dirs->archive, filter);
|
||||
if (archive) {
|
||||
file = VDirFindFirst(archive, filter);
|
||||
if (!file) {
|
||||
dirs->archive->close(dirs->archive);
|
||||
dirs->archive = 0;
|
||||
archive->close(archive);
|
||||
} else {
|
||||
mDirectorySetDetachDir(dirs, dirs->archive);
|
||||
dirs->archive = archive;
|
||||
}
|
||||
} else {
|
||||
file = VFileOpen(path, O_RDONLY);
|
||||
|
|
|
@ -243,9 +243,11 @@ void mLibraryLoadDirectory(struct mLibrary* library, const char* base, bool recu
|
|||
struct VFile* vf = dir->openFile(dir, current->filename, O_RDONLY);
|
||||
_mLibraryDeleteEntry(library, current);
|
||||
if (!vf) {
|
||||
mLibraryEntryFree(current);
|
||||
continue;
|
||||
}
|
||||
_mLibraryAddEntry(library, current->filename, base, vf);
|
||||
mLibraryEntryFree(current);
|
||||
}
|
||||
mLibraryListingDeinit(&entries);
|
||||
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
|
||||
#include <mgba/core/config.h>
|
||||
#include <mgba/core/thread.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
#define MAX_CATEGORY 64
|
||||
#define MAX_LOG_BUF 1024
|
||||
|
||||
static struct mLogger* _defaultLogger = NULL;
|
||||
|
||||
|
@ -183,4 +185,63 @@ int mLogFilterLevels(const struct mLogFilter* filter , int category) {
|
|||
return value;
|
||||
}
|
||||
|
||||
void _mCoreStandardLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
|
||||
struct mStandardLogger* stdlog = (struct mStandardLogger*) logger;
|
||||
|
||||
if (!mLogFilterTest(logger->filter, category, level)) {
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[MAX_LOG_BUF];
|
||||
|
||||
// Prepare the string
|
||||
size_t length = snprintf(buffer, sizeof(buffer), "%s: ", mLogCategoryName(category));
|
||||
if (length < sizeof(buffer)) {
|
||||
length += vsnprintf(buffer + length, sizeof(buffer) - length, format, args);
|
||||
}
|
||||
if (length < sizeof(buffer)) {
|
||||
length += snprintf(buffer + length, sizeof(buffer) - length, "\n");
|
||||
}
|
||||
|
||||
// Make sure the length doesn't exceed the size of the buffer when actually writing
|
||||
if (length > sizeof(buffer)) {
|
||||
length = sizeof(buffer);
|
||||
}
|
||||
|
||||
if (stdlog->logToStdout) {
|
||||
printf("%s", buffer);
|
||||
}
|
||||
|
||||
if (stdlog->logFile) {
|
||||
stdlog->logFile->write(stdlog->logFile, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
void mStandardLoggerInit(struct mStandardLogger* logger) {
|
||||
logger->d.log = _mCoreStandardLog;
|
||||
logger->d.filter = malloc(sizeof(struct mLogFilter));
|
||||
mLogFilterInit(logger->d.filter);
|
||||
}
|
||||
|
||||
void mStandardLoggerDeinit(struct mStandardLogger* logger) {
|
||||
if (logger->d.filter) {
|
||||
mLogFilterDeinit(logger->d.filter);
|
||||
free(logger->d.filter);
|
||||
logger->d.filter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void mStandardLoggerConfig(struct mStandardLogger* logger, struct mCoreConfig* config) {
|
||||
bool logToFile = false;
|
||||
const char* logFile = mCoreConfigGetValue(config, "logFile");
|
||||
mCoreConfigGetBoolValue(config, "logToStdout", &logger->logToStdout);
|
||||
mCoreConfigGetBoolValue(config, "logToFile", &logToFile);
|
||||
|
||||
if (logToFile && logFile) {
|
||||
logger->logFile = VFileOpen(logFile, O_WRONLY | O_CREAT | O_APPEND);
|
||||
}
|
||||
|
||||
mLogFilterLoad(logger->d.filter, config);
|
||||
}
|
||||
|
||||
mLOG_DEFINE_CATEGORY(STATUS, "Status", "core.status")
|
||||
|
|
|
@ -215,19 +215,19 @@ static struct mScriptValue* mScriptMemoryDomainReadRange(struct mScriptMemoryDom
|
|||
static void mScriptMemoryDomainWrite8(struct mScriptMemoryDomain* adapter, uint32_t address, uint8_t value) {
|
||||
CALCULATE_SEGMENT_INFO;
|
||||
CALCULATE_SEGMENT_ADDRESS;
|
||||
adapter->core->rawWrite8(adapter->core, address, segmentAddress, value);
|
||||
adapter->core->rawWrite8(adapter->core, segmentAddress, segment, value);
|
||||
}
|
||||
|
||||
static void mScriptMemoryDomainWrite16(struct mScriptMemoryDomain* adapter, uint32_t address, uint16_t value) {
|
||||
CALCULATE_SEGMENT_INFO;
|
||||
CALCULATE_SEGMENT_ADDRESS;
|
||||
adapter->core->rawWrite16(adapter->core, address, segmentAddress, value);
|
||||
adapter->core->rawWrite16(adapter->core, segmentAddress, segment, value);
|
||||
}
|
||||
|
||||
static void mScriptMemoryDomainWrite32(struct mScriptMemoryDomain* adapter, uint32_t address, uint32_t value) {
|
||||
CALCULATE_SEGMENT_INFO;
|
||||
CALCULATE_SEGMENT_ADDRESS;
|
||||
adapter->core->rawWrite32(adapter->core, address, segmentAddress, value);
|
||||
adapter->core->rawWrite32(adapter->core, segmentAddress, segment, value);
|
||||
}
|
||||
|
||||
static uint32_t mScriptMemoryDomainBase(struct mScriptMemoryDomain* adapter) {
|
||||
|
@ -373,6 +373,16 @@ static struct mScriptValue* _mScriptCoreSaveState(struct mCore* core, int32_t fl
|
|||
return value;
|
||||
}
|
||||
|
||||
static int _mScriptCoreSaveStateFile(struct mCore* core, const char* path, int flags) {
|
||||
struct VFile* vf = VFileOpen(path, O_WRONLY | O_TRUNC | O_CREAT);
|
||||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
bool ok = mCoreSaveStateNamed(core, vf, flags);
|
||||
vf->close(vf);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int32_t _mScriptCoreLoadState(struct mCore* core, struct mScriptString* buffer, int32_t flags) {
|
||||
struct VFile* vf = VFileFromConstMemory(buffer->buffer, buffer->size);
|
||||
int ret = mCoreLoadStateNamed(core, vf, flags);
|
||||
|
@ -380,6 +390,15 @@ static int32_t _mScriptCoreLoadState(struct mCore* core, struct mScriptString* b
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int _mScriptCoreLoadStateFile(struct mCore* core, const char* path, int flags) {
|
||||
struct VFile* vf = VFileOpen(path, O_RDONLY);
|
||||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
bool ok = mCoreLoadStateNamed(core, vf, flags);
|
||||
vf->close(vf);
|
||||
return ok;
|
||||
}
|
||||
static void _mScriptCoreTakeScreenshot(struct mCore* core, const char* filename) {
|
||||
if (filename) {
|
||||
struct VFile* vf = VFileOpen(filename, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
|
@ -393,6 +412,11 @@ static void _mScriptCoreTakeScreenshot(struct mCore* core, const char* filename)
|
|||
}
|
||||
}
|
||||
|
||||
// Loading functions
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, loadFile, mCoreLoadFile, 1, CHARP, path);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, autoloadSave, mCoreAutoloadSave, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, loadSaveFile, mCoreLoadSaveFile, 2, CHARP, path, BOOL, temporary);
|
||||
|
||||
// Info functions
|
||||
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, S32, platform, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, U32, frameCounter, 0);
|
||||
|
@ -400,6 +424,7 @@ mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, S32, frameCycles, 0);
|
|||
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, S32, frequency, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD(mCore, WSTR, getGameTitle, _mScriptCoreGetGameTitle, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD(mCore, WSTR, getGameCode, _mScriptCoreGetGameCode, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, S64, romSize, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD_WITH_DEFAULTS(mCore, WSTR, checksum, _mScriptCoreChecksum, 1, S32, type);
|
||||
|
||||
// Run functions
|
||||
|
@ -430,10 +455,12 @@ mSCRIPT_DECLARE_STRUCT_METHOD(mCore, WSTR, readRegister, _mScriptCoreReadRegiste
|
|||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mCore, writeRegister, _mScriptCoreWriteRegister, 2, CHARP, regName, S32, value);
|
||||
|
||||
// Savestate functions
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, saveStateSlot, mCoreSaveState, 2, S32, slot, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, saveStateSlot, mCoreSaveState, 2, S32, slot, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, WSTR, saveStateBuffer, _mScriptCoreSaveState, 1, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateSlot, mCoreLoadState, 2, S32, slot, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateBuffer, _mScriptCoreLoadState, 2, STR, buffer, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, saveStateFile, _mScriptCoreSaveStateFile, 2, CHARP, path, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateSlot, mCoreLoadState, 2, S32, slot, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateBuffer, _mScriptCoreLoadState, 2, STR, buffer, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateFile, _mScriptCoreLoadStateFile, 2, CHARP, path, S32, flags);
|
||||
|
||||
// Miscellaneous functions
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD_WITH_DEFAULTS(mCore, screenshot, _mScriptCoreTakeScreenshot, 1, CHARP, filename);
|
||||
|
@ -442,6 +469,13 @@ mSCRIPT_DEFINE_STRUCT(mCore)
|
|||
mSCRIPT_DEFINE_CLASS_DOCSTRING(
|
||||
"An instance of an emulator core."
|
||||
)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load a ROM file into the current state of this core")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadFile)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load the save data associated with the currently loaded ROM file")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, autoloadSave)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load save data from the given path. If the `temporary` flag is set, the given save data will not be written back to disk")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadSaveFile)
|
||||
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get which platform is being emulated. See C.PLATFORM for possible values")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, platform)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get the number of the current frame")
|
||||
|
@ -450,6 +484,8 @@ mSCRIPT_DEFINE_STRUCT(mCore)
|
|||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, frameCycles)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get the number of cycles per second")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, frequency)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get the size of the loaded ROM")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, romSize)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get the checksum of the loaded ROM")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, checksum)
|
||||
|
||||
|
@ -504,10 +540,14 @@ mSCRIPT_DEFINE_STRUCT(mCore)
|
|||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateSlot)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Save state and return as a buffer. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateBuffer)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Save state to the given path. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateFile)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load state from the slot number. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateSlot)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load state a buffer. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load state from a buffer. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateBuffer)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load state from the given path. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateFile)
|
||||
|
||||
mSCRIPT_DEFINE_DOCSTRING("Save a screenshot")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, screenshot)
|
||||
|
@ -522,16 +562,26 @@ mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, saveStateSlot)
|
|||
mSCRIPT_S32(SAVESTATE_ALL)
|
||||
mSCRIPT_DEFINE_DEFAULTS_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, saveStateBuffer)
|
||||
mSCRIPT_S32(SAVESTATE_ALL)
|
||||
mSCRIPT_DEFINE_DEFAULTS_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, saveStateFile)
|
||||
mSCRIPT_NO_DEFAULT,
|
||||
mSCRIPT_S32(SAVESTATE_ALL)
|
||||
mSCRIPT_DEFINE_DEFAULTS_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateSlot)
|
||||
mSCRIPT_NO_DEFAULT,
|
||||
mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA)
|
||||
mSCRIPT_DEFINE_DEFAULTS_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, saveStateBuffer)
|
||||
mSCRIPT_S32(SAVESTATE_ALL)
|
||||
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateBuffer)
|
||||
mSCRIPT_NO_DEFAULT,
|
||||
mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA)
|
||||
mSCRIPT_DEFINE_DEFAULTS_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateBuffer)
|
||||
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateFile)
|
||||
mSCRIPT_NO_DEFAULT,
|
||||
mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA)
|
||||
mSCRIPT_DEFINE_DEFAULTS_END;
|
||||
|
|
|
@ -253,10 +253,13 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
core->setSync(core, &threadContext->impl->sync);
|
||||
|
||||
struct mLogFilter filter;
|
||||
if (!threadContext->logger.d.filter) {
|
||||
threadContext->logger.d.filter = &filter;
|
||||
mLogFilterInit(threadContext->logger.d.filter);
|
||||
mLogFilterLoad(threadContext->logger.d.filter, &core->config);
|
||||
struct mLogger* logger = &threadContext->logger.d;
|
||||
if (threadContext->logger.logger) {
|
||||
logger->filter = threadContext->logger.logger->filter;
|
||||
} else {
|
||||
logger->filter = &filter;
|
||||
mLogFilterInit(logger->filter);
|
||||
mLogFilterLoad(logger->filter, &core->config);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
|
@ -431,10 +434,10 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
#endif
|
||||
core->clearCoreCallbacks(core);
|
||||
|
||||
if (threadContext->logger.d.filter == &filter) {
|
||||
if (logger->filter == &filter) {
|
||||
mLogFilterDeinit(&filter);
|
||||
}
|
||||
threadContext->logger.d.filter = NULL;
|
||||
logger->filter = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -444,10 +447,8 @@ bool mCoreThreadStart(struct mCoreThread* threadContext) {
|
|||
threadContext->impl->state = mTHREAD_INITIALIZED;
|
||||
threadContext->impl->requested = 0;
|
||||
threadContext->logger.p = threadContext;
|
||||
if (!threadContext->logger.d.log) {
|
||||
threadContext->logger.d.log = _mCoreLog;
|
||||
threadContext->logger.d.filter = NULL;
|
||||
}
|
||||
|
||||
if (!threadContext->impl->sync.fpsTarget) {
|
||||
threadContext->impl->sync.fpsTarget = _defaultFPSTarget;
|
||||
|
@ -718,14 +719,17 @@ struct mCoreThread* mCoreThreadGet(void) {
|
|||
}
|
||||
|
||||
static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
|
||||
UNUSED(logger);
|
||||
UNUSED(level);
|
||||
struct mThreadLogger* threadLogger = (struct mThreadLogger*) logger;
|
||||
if (level == mLOG_FATAL) {
|
||||
mCoreThreadMarkCrashed(threadLogger->p);
|
||||
}
|
||||
if (!threadLogger->p->logger.logger) {
|
||||
printf("%s: ", mLogCategoryName(category));
|
||||
vprintf(format, args);
|
||||
printf("\n");
|
||||
struct mCoreThread* thread = mCoreThreadGet();
|
||||
if (thread && level == mLOG_FATAL) {
|
||||
mCoreThreadMarkCrashed(thread);
|
||||
} else {
|
||||
logger = threadLogger->p->logger.logger;
|
||||
logger->log(logger, category, level, format, args);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -588,7 +588,7 @@ static struct ParseTree* _parseTree(const char** string) {
|
|||
}
|
||||
struct ParseTree* tree = NULL;
|
||||
if (!error) {
|
||||
tree = malloc(sizeof(*tree));
|
||||
tree = parseTreeCreate();
|
||||
parseLexedExpression(tree, &lv);
|
||||
}
|
||||
lexFree(&lv);
|
||||
|
@ -796,17 +796,16 @@ struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* stri
|
|||
dvTemp.type = CLIDV_ERROR_TYPE;
|
||||
}
|
||||
|
||||
struct ParseTree tree;
|
||||
parseLexedExpression(&tree, &lv);
|
||||
if (tree.token.type == TOKEN_ERROR_TYPE) {
|
||||
struct ParseTree* tree = parseTreeCreate();
|
||||
if (!parseLexedExpression(tree, &lv)) {
|
||||
dvTemp.type = CLIDV_ERROR_TYPE;
|
||||
} else {
|
||||
if (!mDebuggerEvaluateParseTree(&debugger->d, &tree, &dvTemp.intValue, &dvTemp.segmentValue)) {
|
||||
if (!mDebuggerEvaluateParseTree(&debugger->d, tree, &dvTemp.intValue, &dvTemp.segmentValue)) {
|
||||
dvTemp.type = CLIDV_ERROR_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
parseFree(&tree);
|
||||
parseFree(tree);
|
||||
|
||||
lexFree(&lv);
|
||||
LexVectorDeinit(&lv);
|
||||
|
|
|
@ -495,7 +495,7 @@ static const int _operatorPrecedence[] = {
|
|||
[OP_DEREFERENCE] = 2,
|
||||
};
|
||||
|
||||
static struct ParseTree* _parseTreeCreate(void) {
|
||||
struct ParseTree* parseTreeCreate(void) {
|
||||
struct ParseTree* tree = malloc(sizeof(struct ParseTree));
|
||||
tree->token.type = TOKEN_ERROR_TYPE;
|
||||
tree->p = NULL;
|
||||
|
@ -529,12 +529,12 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, int
|
|||
}
|
||||
break;
|
||||
case TOKEN_SEGMENT_TYPE:
|
||||
tree->lhs = _parseTreeCreate();
|
||||
tree->lhs = parseTreeCreate();
|
||||
tree->lhs->token.type = TOKEN_UINT_TYPE;
|
||||
tree->lhs->token.uintValue = token->uintValue;
|
||||
tree->lhs->p = tree;
|
||||
tree->lhs->precedence = precedence;
|
||||
tree->rhs = _parseTreeCreate();
|
||||
tree->rhs = parseTreeCreate();
|
||||
tree->rhs->p = tree;
|
||||
tree->rhs->precedence = precedence;
|
||||
tree->token.type = TOKEN_SEGMENT_TYPE;
|
||||
|
@ -572,7 +572,7 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, int
|
|||
}
|
||||
newPrecedence = _operatorPrecedence[token->operatorValue];
|
||||
if (newPrecedence < precedence) {
|
||||
newTree = _parseTreeCreate();
|
||||
newTree = parseTreeCreate();
|
||||
memcpy(newTree, tree, sizeof(*tree));
|
||||
if (newTree->lhs) {
|
||||
newTree->lhs->p = newTree;
|
||||
|
@ -582,7 +582,7 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, int
|
|||
}
|
||||
newTree->p = tree;
|
||||
tree->lhs = newTree;
|
||||
tree->rhs = _parseTreeCreate();
|
||||
tree->rhs = parseTreeCreate();
|
||||
tree->rhs->p = tree;
|
||||
tree->rhs->precedence = newPrecedence;
|
||||
precedence = newPrecedence;
|
||||
|
@ -617,9 +617,9 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, int
|
|||
return i;
|
||||
}
|
||||
|
||||
void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv) {
|
||||
bool parseLexedExpression(struct ParseTree* tree, struct LexVector* lv) {
|
||||
if (!tree) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
tree->token.type = TOKEN_ERROR_TYPE;
|
||||
|
@ -636,6 +636,7 @@ void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv) {
|
|||
}
|
||||
tree->token.type = TOKEN_ERROR_TYPE;
|
||||
}
|
||||
return tree->token.type != TOKEN_ERROR_TYPE;
|
||||
}
|
||||
|
||||
void lexFree(struct LexVector* lv) {
|
||||
|
@ -782,7 +783,8 @@ bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tr
|
|||
struct IntList stack;
|
||||
int nextBranch;
|
||||
bool ok = true;
|
||||
int32_t tmpVal, tmpSegment;
|
||||
int32_t tmpVal = 0;
|
||||
int32_t tmpSegment = -1;
|
||||
|
||||
IntListInit(&stack, 0);
|
||||
while (ok) {
|
||||
|
|
|
@ -260,8 +260,16 @@ bool NoIntroDBLoadClrMamePro(struct NoIntroDB* db, struct VFile* vf) {
|
|||
|
||||
free((void*) buffer.name);
|
||||
free((void*) buffer.romName);
|
||||
free((void*) dbType);
|
||||
free((void*) dbVersion);
|
||||
|
||||
if (dbType) {
|
||||
free(dbType);
|
||||
}
|
||||
if (dbVersion) {
|
||||
free(dbVersion);
|
||||
}
|
||||
if (fieldName) {
|
||||
free(fieldName);
|
||||
}
|
||||
|
||||
sqlite3_finalize(gamedbTable);
|
||||
sqlite3_finalize(gamedbDrop);
|
||||
|
|
|
@ -92,7 +92,7 @@ bool mUpdaterInit(struct mUpdaterContext* context, const char* manifest) {
|
|||
ConfigurationInit(&context->manifest);
|
||||
|
||||
struct VFile* vf = VFileFromConstMemory(manifest, strlen(manifest) + 1);
|
||||
bool success = vf && ConfigurationReadVFile(&context->manifest, vf);
|
||||
bool success = ConfigurationReadVFile(&context->manifest, vf);
|
||||
vf->close(vf);
|
||||
if (!success) {
|
||||
ConfigurationDeinit(&context->manifest);
|
||||
|
|
|
@ -485,8 +485,16 @@ static void _GBCoreUnloadROM(struct mCore* core) {
|
|||
GBUnloadROM(core->board);
|
||||
}
|
||||
|
||||
static size_t _GBCoreROMSize(const struct mCore* core) {
|
||||
const struct GB* gb = (const struct GB*) core->board;
|
||||
if (gb->romVf) {
|
||||
return gb->romVf->size(gb->romVf);
|
||||
}
|
||||
return gb->pristineRomSize;
|
||||
}
|
||||
|
||||
static void _GBCoreChecksum(const struct mCore* core, void* data, enum mCoreChecksumType type) {
|
||||
struct GB* gb = (struct GB*) core->board;
|
||||
const struct GB* gb = (const struct GB*) core->board;
|
||||
switch (type) {
|
||||
case mCHECKSUM_CRC32:
|
||||
memcpy(data, &gb->romCrc32, sizeof(gb->romCrc32));
|
||||
|
@ -888,59 +896,59 @@ static bool _GBCoreReadRegister(const struct mCore* core, const char* name, void
|
|||
uint16_t* value16 = out;
|
||||
uint8_t* value8 = out;
|
||||
|
||||
if (strcmp(name, "b") == 0) {
|
||||
if (strcasecmp(name, "b") == 0) {
|
||||
*value8 = cpu->b;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "c") == 0) {
|
||||
if (strcasecmp(name, "c") == 0) {
|
||||
*value8 = cpu->c;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "d") == 0) {
|
||||
if (strcasecmp(name, "d") == 0) {
|
||||
*value8 = cpu->d;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "e") == 0) {
|
||||
if (strcasecmp(name, "e") == 0) {
|
||||
*value8 = cpu->e;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "a") == 0) {
|
||||
if (strcasecmp(name, "a") == 0) {
|
||||
*value8 = cpu->a;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "f") == 0) {
|
||||
if (strcasecmp(name, "f") == 0) {
|
||||
*value8 = cpu->f.packed;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "h") == 0) {
|
||||
if (strcasecmp(name, "h") == 0) {
|
||||
*value8 = cpu->h;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "l") == 0) {
|
||||
if (strcasecmp(name, "l") == 0) {
|
||||
*value8 = cpu->l;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "bc") == 0) {
|
||||
if (strcasecmp(name, "bc") == 0) {
|
||||
*value16 = cpu->bc;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "de") == 0) {
|
||||
if (strcasecmp(name, "de") == 0) {
|
||||
*value16 = cpu->de;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "hl") == 0) {
|
||||
if (strcasecmp(name, "hl") == 0) {
|
||||
*value16 = cpu->hl;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "af") == 0) {
|
||||
if (strcasecmp(name, "af") == 0) {
|
||||
*value16 = cpu->af;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "pc") == 0) {
|
||||
if (strcasecmp(name, "pc") == 0) {
|
||||
*value16 = cpu->pc;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "sp") == 0) {
|
||||
if (strcasecmp(name, "sp") == 0) {
|
||||
*value16 = cpu->sp;
|
||||
return true;
|
||||
}
|
||||
|
@ -1260,6 +1268,7 @@ struct mCore* GBCoreCreate(void) {
|
|||
core->loadTemporarySave = _GBCoreLoadTemporarySave;
|
||||
core->loadPatch = _GBCoreLoadPatch;
|
||||
core->unloadROM = _GBCoreUnloadROM;
|
||||
core->romSize = _GBCoreROMSize;
|
||||
core->checksum = _GBCoreChecksum;
|
||||
core->reset = _GBCoreReset;
|
||||
core->runFrame = _GBCoreRunFrame;
|
||||
|
|
|
@ -189,6 +189,9 @@ bool GBLoadROM(struct GB* gb, struct VFile* vf) {
|
|||
|
||||
if (gb->cpu) {
|
||||
struct SM83Core* cpu = gb->cpu;
|
||||
if (!gb->memory.romBase) {
|
||||
GBMBCSwitchBank0(gb, 0);
|
||||
}
|
||||
cpu->memory.setActiveRegion(cpu, cpu->pc);
|
||||
}
|
||||
|
||||
|
|
|
@ -454,6 +454,7 @@ static void _GBACoreSetVideoGLTex(struct mCore* core, unsigned texid) {
|
|||
#ifdef BUILD_GLES3
|
||||
struct GBACore* gbacore = (struct GBACore*) core;
|
||||
gbacore->glRenderer.outputTex = texid;
|
||||
gbacore->glRenderer.outputTexDirty = true;
|
||||
#else
|
||||
UNUSED(core);
|
||||
UNUSED(texid);
|
||||
|
@ -579,8 +580,16 @@ static void _GBACoreUnloadROM(struct mCore* core) {
|
|||
GBAUnloadROM(core->board);
|
||||
}
|
||||
|
||||
static size_t _GBACoreROMSize(const struct mCore* core) {
|
||||
const struct GBA* gba = (const struct GBA*) core->board;
|
||||
if (gba->romVf) {
|
||||
return gba->romVf->size(gba->romVf);
|
||||
}
|
||||
return gba->pristineRomSize;
|
||||
}
|
||||
|
||||
static void _GBACoreChecksum(const struct mCore* core, void* data, enum mCoreChecksumType type) {
|
||||
struct GBA* gba = (struct GBA*) core->board;
|
||||
const struct GBA* gba = (const struct GBA*) core->board;
|
||||
switch (type) {
|
||||
case mCHECKSUM_CRC32:
|
||||
memcpy(data, &gba->romCrc32, sizeof(gba->romCrc32));
|
||||
|
@ -1384,6 +1393,7 @@ struct mCore* GBACoreCreate(void) {
|
|||
core->loadTemporarySave = _GBACoreLoadTemporarySave;
|
||||
core->loadPatch = _GBACoreLoadPatch;
|
||||
core->unloadROM = _GBACoreUnloadROM;
|
||||
core->romSize = _GBACoreROMSize;
|
||||
core->checksum = _GBACoreChecksum;
|
||||
core->reset = _GBACoreReset;
|
||||
core->runFrame = _GBACoreRunFrame;
|
||||
|
|
|
@ -257,7 +257,7 @@ void GBAReset(struct ARMCore* cpu) {
|
|||
memset(gba->debugString, 0, sizeof(gba->debugString));
|
||||
|
||||
|
||||
if (gba->romVf && gba->pristineRomSize > SIZE_CART0) {
|
||||
if (gba->romVf && gba->romVf->size(gba->romVf) > SIZE_CART0) {
|
||||
char ident;
|
||||
gba->romVf->seek(gba->romVf, 0xAC, SEEK_SET);
|
||||
gba->romVf->read(gba->romVf, &ident, 1);
|
||||
|
@ -399,14 +399,15 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
|
|||
}
|
||||
GBAUnloadROM(gba);
|
||||
gba->romVf = vf;
|
||||
gba->isPristine = true;
|
||||
gba->pristineRomSize = vf->size(vf);
|
||||
vf->seek(vf, 0, SEEK_SET);
|
||||
if (gba->pristineRomSize > SIZE_CART0) {
|
||||
gba->isPristine = false;
|
||||
char ident;
|
||||
vf->seek(vf, 0xAC, SEEK_SET);
|
||||
vf->read(vf, &ident, 1);
|
||||
if (ident == 'M') {
|
||||
gba->isPristine = false;
|
||||
gba->memory.romSize = 0x01000000;
|
||||
#ifdef FIXED_ROM_BUFFER
|
||||
gba->memory.rom = romBuffer;
|
||||
|
@ -417,8 +418,8 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
|
|||
gba->memory.rom = vf->map(vf, SIZE_CART0, MAP_READ);
|
||||
gba->memory.romSize = SIZE_CART0;
|
||||
}
|
||||
gba->pristineRomSize = SIZE_CART0;
|
||||
} else {
|
||||
gba->isPristine = true;
|
||||
gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ);
|
||||
gba->memory.romSize = gba->pristineRomSize;
|
||||
}
|
||||
|
@ -582,6 +583,10 @@ void GBADebug(struct GBA* gba, uint16_t flags) {
|
|||
}
|
||||
|
||||
bool GBAIsROM(struct VFile* vf) {
|
||||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_ELF
|
||||
struct ELF* elf = ELFOpen(vf);
|
||||
if (elf) {
|
||||
|
@ -593,9 +598,6 @@ bool GBAIsROM(struct VFile* vf) {
|
|||
return isGBA;
|
||||
}
|
||||
#endif
|
||||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t signature[sizeof(GBA_ROM_MAGIC) + sizeof(GBA_ROM_MAGIC2)];
|
||||
if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) {
|
||||
|
|
|
@ -779,6 +779,7 @@ static void _initFramebuffers(struct GBAVideoGLRenderer* glRenderer) {
|
|||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_OUTPUT]);
|
||||
_initFramebufferTexture(glRenderer->outputTex, GL_RGB, GL_COLOR_ATTACHMENT0, glRenderer->scale);
|
||||
glRenderer->outputTexDirty = false;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
|
@ -1684,6 +1685,10 @@ static void GBAVideoGLRendererWriteBLDCNT(struct GBAVideoGLRenderer* renderer, u
|
|||
void _finalizeLayers(struct GBAVideoGLRenderer* renderer) {
|
||||
const GLuint* uniforms = renderer->finalizeShader.uniforms;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OUTPUT]);
|
||||
if (renderer->outputTexDirty) {
|
||||
_initFramebufferTexture(renderer->outputTex, GL_RGB, GL_COLOR_ATTACHMENT0, renderer->scale);
|
||||
renderer->outputTexDirty = false;
|
||||
}
|
||||
glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
|
||||
glScissor(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
|
||||
if (GBARegisterDISPCNTIsForcedBlank(renderer->dispcnt)) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AboutScreen</class>
|
||||
<widget class="QWidget" name="AboutScreen">
|
||||
<class>QGBA::AboutScreen</class>
|
||||
<widget class="QWidget" name="QGBA::AboutScreen">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ApplicationUpdatePrompt</class>
|
||||
<widget class="QDialog" name="ApplicationUpdatePrompt">
|
||||
<class>QGBA::ApplicationUpdatePrompt</class>
|
||||
<widget class="QDialog" name="QGBA::ApplicationUpdatePrompt">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -58,7 +58,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ApplicationUpdatePrompt</receiver>
|
||||
<receiver>QGBA::ApplicationUpdatePrompt</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ArchiveInspector</class>
|
||||
<widget class="QDialog" name="ArchiveInspector">
|
||||
<class>QGBA::ArchiveInspector</class>
|
||||
<widget class="QDialog" name="QGBA::ArchiveInspector">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -46,7 +46,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ArchiveInspector</receiver>
|
||||
<receiver>QGBA::ArchiveInspector</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
@ -62,7 +62,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ArchiveInspector</receiver>
|
||||
<receiver>QGBA::ArchiveInspector</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -82,6 +82,9 @@ void AssetTile::setBoundary(int boundary, int set0, int set1) {
|
|||
}
|
||||
|
||||
void AssetTile::selectIndex(int index) {
|
||||
if (index > m_maxTile) {
|
||||
return;
|
||||
}
|
||||
m_index = index;
|
||||
const color_t* data;
|
||||
mTileCache* tileCache = m_tileCaches[index >= m_boundary];
|
||||
|
@ -141,3 +144,7 @@ void AssetTile::selectColor(int index) {
|
|||
m_ui.g->setText(tr("0x%0 (%1)").arg(g, 2, 16, QChar('0')).arg(g, 2, 10, QChar('0')));
|
||||
m_ui.b->setText(tr("0x%0 (%1)").arg(b, 2, 16, QChar('0')).arg(b, 2, 10, QChar('0')));
|
||||
}
|
||||
|
||||
void AssetTile::setMaxTile(int tile) {
|
||||
m_maxTile = tile;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ public slots:
|
|||
void selectIndex(int);
|
||||
void setFlip(bool h, bool v);
|
||||
void selectColor(int);
|
||||
void setMaxTile(int);
|
||||
|
||||
protected:
|
||||
int customLocation(const QString& id = {}) override;
|
||||
|
@ -45,6 +46,7 @@ private:
|
|||
int m_addressBase;
|
||||
int m_boundary;
|
||||
int m_boundaryBase;
|
||||
int m_maxTile;
|
||||
bool m_flipH = false;
|
||||
bool m_flipV = false;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AssetTile</class>
|
||||
<widget class="QGBA::AssetInfo" name="AssetTile">
|
||||
<class>QGBA::AssetTile</class>
|
||||
<widget class="QGBA::AssetInfo" name="QGBA::AssetTile">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BattleChipView</class>
|
||||
<widget class="QDialog" name="BattleChipView">
|
||||
<class>QGBA::BattleChipView</class>
|
||||
<widget class="QDialog" name="QGBA::BattleChipView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -238,7 +238,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>BattleChipView</receiver>
|
||||
<receiver>QGBA::BattleChipView</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -333,9 +333,9 @@ if(${QT}LinguistTools_FOUND)
|
|||
file(GLOB TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/ts/${BINARY_NAME}-*.ts")
|
||||
if(UPDATE_TRANSLATIONS)
|
||||
if(TARGET Qt6::Core)
|
||||
qt_create_translation(TRANSLATION_FILES ${SOURCE_FILES} ${UI_FILES} ${TS_FILES} OPTIONS -locations absolute -no-obsolete)
|
||||
qt_create_translation(TRANSLATION_FILES ${SOURCE_FILES} ${AUDIO_SRC} ${PLATFORM_SRC} ${UI_FILES} ${TS_FILES} OPTIONS -locations absolute -no-obsolete -I "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
else()
|
||||
qt5_create_translation(TRANSLATION_FILES ${SOURCE_FILES} ${UI_FILES} ${TS_FILES} OPTIONS -locations absolute -no-obsolete)
|
||||
qt5_create_translation(TRANSLATION_FILES ${SOURCE_FILES} ${AUDIO_SRC} ${PLATFORM_SRC} ${UI_FILES} ${TS_FILES} OPTIONS -locations absolute -no-obsolete -I "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
endif()
|
||||
list(REMOVE_ITEM TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/ts/${BINARY_NAME}-template.ts")
|
||||
else()
|
||||
|
@ -361,9 +361,14 @@ if(${QT}LinguistTools_FOUND)
|
|||
endforeach()
|
||||
list(APPEND TRANSLATION_FILES ${QT_QM_FILES})
|
||||
endif()
|
||||
add_custom_command(OUTPUT ${TRANSLATION_QRC}
|
||||
COMMAND ${CMAKE_COMMAND} -DTRANSLATION_QRC:FILEPATH="${TRANSLATION_QRC}" -DQM_BASE="${CMAKE_CURRENT_BINARY_DIR}" "-DTRANSLATION_FILES='${TRANSLATION_FILES}'" -P "${CMAKE_CURRENT_SOURCE_DIR}/ts.cmake"
|
||||
DEPENDS ${TRANSLATION_FILES})
|
||||
|
||||
file(WRITE ${TRANSLATION_QRC} "<RCC>\n\t<qresource prefix=\"/translations/\">\n")
|
||||
foreach(TS ${TRANSLATION_FILES})
|
||||
get_filename_component(TS_BASE "${TS}" NAME)
|
||||
file(APPEND ${TRANSLATION_QRC} "\t\t<file alias=\"${TS_BASE}\">${TS}</file>\n")
|
||||
endforeach()
|
||||
file(APPEND ${TRANSLATION_QRC} "\t</qresource>\n</RCC>")
|
||||
|
||||
if(TARGET Qt6::Core)
|
||||
qt_add_resources(TRANSLATION_RESOURCES ${TRANSLATION_QRC})
|
||||
else()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CheatsView</class>
|
||||
<widget class="QWidget" name="CheatsView">
|
||||
<class>QGBA::CheatsView</class>
|
||||
<widget class="QWidget" name="QGBA::CheatsView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -144,19 +144,19 @@ CoreController::CoreController(mCore* core, QObject* parent)
|
|||
QMetaObject::invokeMethod(controller, "unpaused");
|
||||
};
|
||||
|
||||
m_threadContext.logger.d.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
|
||||
mThreadLogger* logContext = reinterpret_cast<mThreadLogger*>(logger);
|
||||
mCoreThread* context = logContext->p;
|
||||
m_logger.self = this;
|
||||
m_logger.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
|
||||
CoreLogger* logContext = static_cast<CoreLogger*>(logger);
|
||||
|
||||
static const char* savestateMessage = "State %i saved";
|
||||
static const char* loadstateMessage = "State %i loaded";
|
||||
static const char* savestateFailedMessage = "State %i failed to load";
|
||||
static int biosCat = -1;
|
||||
static int statusCat = -1;
|
||||
if (!context) {
|
||||
if (!logContext) {
|
||||
return;
|
||||
}
|
||||
CoreController* controller = static_cast<CoreController*>(context->userData);
|
||||
CoreController* controller = logContext->self;
|
||||
QString message;
|
||||
if (biosCat < 0) {
|
||||
biosCat = mLogCategoryById("gba.bios");
|
||||
|
@ -201,10 +201,10 @@ CoreController::CoreController(mCore* core, QObject* parent)
|
|||
message = QString::vasprintf(format, args);
|
||||
QMetaObject::invokeMethod(controller, "logPosted", Q_ARG(int, level), Q_ARG(int, category), Q_ARG(const QString&, message));
|
||||
if (level == mLOG_FATAL) {
|
||||
mCoreThreadMarkCrashed(controller->thread());
|
||||
QMetaObject::invokeMethod(controller, "crashed", Q_ARG(const QString&, message));
|
||||
}
|
||||
};
|
||||
m_threadContext.logger.logger = &m_logger;
|
||||
}
|
||||
|
||||
CoreController::~CoreController() {
|
||||
|
@ -429,7 +429,7 @@ void CoreController::setInputController(InputController* inputController) {
|
|||
void CoreController::setLogger(LogController* logger) {
|
||||
disconnect(m_log);
|
||||
m_log = logger;
|
||||
m_threadContext.logger.d.filter = logger->filter();
|
||||
m_logger.filter = logger->filter();
|
||||
connect(this, &CoreController::logPosted, m_log, &LogController::postLog);
|
||||
}
|
||||
|
||||
|
@ -1218,24 +1218,21 @@ void CoreController::updateFastForward() {
|
|||
if (m_fastForwardMute >= 0) {
|
||||
m_threadContext.core->opts.mute = m_fastForwardMute || m_mute;
|
||||
}
|
||||
setSync(false);
|
||||
|
||||
// If we aren't holding the fast forward button
|
||||
// then use the non "(held)" ratio
|
||||
if(!m_fastForward) {
|
||||
if (m_fastForwardRatio > 0) {
|
||||
m_threadContext.impl->sync.fpsTarget = m_fpsTarget * m_fastForwardRatio;
|
||||
setSync(true);
|
||||
} else {
|
||||
setSync(false);
|
||||
m_threadContext.impl->sync.audioWait = true;
|
||||
}
|
||||
} else {
|
||||
// If we are holding the fast forward button,
|
||||
// then use the held ratio
|
||||
if (m_fastForwardHeldRatio > 0) {
|
||||
m_threadContext.impl->sync.fpsTarget = m_fpsTarget * m_fastForwardHeldRatio;
|
||||
setSync(true);
|
||||
} else {
|
||||
setSync(false);
|
||||
m_threadContext.impl->sync.audioWait = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1338,3 +1335,7 @@ void CoreController::Interrupter::resume(CoreController* controller) {
|
|||
|
||||
mCoreThreadContinue(controller->thread());
|
||||
}
|
||||
|
||||
bool CoreController::Interrupter::held() const {
|
||||
return m_parent && m_parent->thread()->impl;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@ public:
|
|||
void interrupt(std::shared_ptr<CoreController>);
|
||||
void resume();
|
||||
|
||||
bool held() const;
|
||||
|
||||
private:
|
||||
void interrupt();
|
||||
void resume(CoreController*);
|
||||
|
@ -238,6 +240,9 @@ private:
|
|||
void updateROMInfo();
|
||||
|
||||
mCoreThread m_threadContext{};
|
||||
struct CoreLogger : public mLogger {
|
||||
CoreController* self;
|
||||
} m_logger{};
|
||||
|
||||
bool m_patched = false;
|
||||
bool m_preload = false;
|
||||
|
|
|
@ -62,13 +62,16 @@ CoreController* CoreManager::loadGame(const QString& path) {
|
|||
VFile* vfOriginal = VDirFindFirst(archive, [](VFile* vf) {
|
||||
return mCoreIsCompatible(vf) != mPLATFORM_NONE;
|
||||
});
|
||||
ssize_t size;
|
||||
if (vfOriginal && (size = vfOriginal->size(vfOriginal)) > 0) {
|
||||
if (vfOriginal) {
|
||||
ssize_t size = vfOriginal->size(vfOriginal);
|
||||
if (size > 0) {
|
||||
void* mem = vfOriginal->map(vfOriginal, size, MAP_READ);
|
||||
vf = VFileMemChunk(mem, size);
|
||||
vfOriginal->unmap(vfOriginal, mem, size);
|
||||
}
|
||||
vfOriginal->close(vfOriginal);
|
||||
}
|
||||
archive->close(archive);
|
||||
}
|
||||
QDir dir(info.dir());
|
||||
if (!vf) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DebuggerConsole</class>
|
||||
<widget class="QWidget" name="DebuggerConsole">
|
||||
<class>QGBA::DebuggerConsole</class>
|
||||
<widget class="QWidget" name="QGBA::DebuggerConsole">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -288,7 +288,7 @@ void DisplayGL::stopDrawing() {
|
|||
m_isDrawing = false;
|
||||
m_hasStarted = false;
|
||||
CoreController::Interrupter interrupter(m_context);
|
||||
QMetaObject::invokeMethod(m_painter.get(), "stop", Qt::BlockingQueuedConnection);
|
||||
m_painter->stop();
|
||||
if (m_gl) {
|
||||
hide();
|
||||
}
|
||||
|
@ -460,8 +460,7 @@ void PainterGL::create() {
|
|||
m_paintDev = std::make_unique<QOpenGLPaintDevice>();
|
||||
|
||||
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||
auto version = m_format.version();
|
||||
if (version >= qMakePair(2, 0)) {
|
||||
if (m_supportsShaders) {
|
||||
gl2Backend = static_cast<mGLES2Context*>(malloc(sizeof(mGLES2Context)));
|
||||
mGLES2ContextCreate(gl2Backend);
|
||||
m_backend = &gl2Backend->d;
|
||||
|
@ -629,6 +628,15 @@ void PainterGL::draw() {
|
|||
if (!m_started || m_queue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_interrupter.held()) {
|
||||
// A resize event is pending; that needs to happen first
|
||||
if (!m_drawTimer.isActive()) {
|
||||
m_drawTimer.start(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mCoreSync* sync = &m_context->thread()->impl->sync;
|
||||
if (!mCoreSyncWaitFrameStart(sync)) {
|
||||
mCoreSyncWaitFrameEnd(sync);
|
||||
|
@ -679,6 +687,11 @@ void PainterGL::forceDraw() {
|
|||
}
|
||||
|
||||
void PainterGL::stop() {
|
||||
m_started = false;
|
||||
QMetaObject::invokeMethod(this, "doStop", Qt::BlockingQueuedConnection);
|
||||
}
|
||||
|
||||
void PainterGL::doStop() {
|
||||
m_drawTimer.stop();
|
||||
m_active = false;
|
||||
m_started = false;
|
||||
|
|
|
@ -135,6 +135,8 @@ public:
|
|||
void setMessagePainter(MessagePainter*);
|
||||
void enqueue(const uint32_t* backing);
|
||||
|
||||
void stop();
|
||||
|
||||
bool supportsShaders() const { return m_supportsShaders; }
|
||||
int glTex();
|
||||
|
||||
|
@ -148,7 +150,6 @@ public slots:
|
|||
void forceDraw();
|
||||
void draw();
|
||||
void start();
|
||||
void stop();
|
||||
void pause();
|
||||
void unpause();
|
||||
void resize(const QSize& size);
|
||||
|
@ -167,6 +168,9 @@ public slots:
|
|||
signals:
|
||||
void started();
|
||||
|
||||
private slots:
|
||||
void doStop();
|
||||
|
||||
private:
|
||||
void makeCurrent();
|
||||
void performDraw();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DolphinConnector</class>
|
||||
<widget class="QDialog" name="DolphinConnector">
|
||||
<class>QGBA::DolphinConnector</class>
|
||||
<widget class="QDialog" name="QGBA::DolphinConnector">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -98,7 +98,7 @@
|
|||
<connection>
|
||||
<sender>close</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>DolphinConnector</receiver>
|
||||
<receiver>QGBA::DolphinConnector</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FrameView</class>
|
||||
<widget class="QWidget" name="FrameView">
|
||||
<class>QGBA::FrameView</class>
|
||||
<widget class="QWidget" name="QGBA::FrameView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GIFView</class>
|
||||
<widget class="QWidget" name="GIFView">
|
||||
<class>QGBA::GIFView</class>
|
||||
<widget class="QWidget" name="QGBA::GIFView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -180,7 +180,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>GIFView</receiver>
|
||||
<receiver>QGBA::GIFView</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -44,9 +44,7 @@ static const QList<GBMemoryBankControllerType> s_mbcList{
|
|||
static QMap<GBModel, QString> s_gbModelNames;
|
||||
static QMap<GBMemoryBankControllerType, QString> s_mbcNames;
|
||||
|
||||
static QString tr(const char* str) {
|
||||
return QCoreApplication::translate("Game Boy", str);
|
||||
}
|
||||
#define tr(STR) QCoreApplication::translate("QGBA::GameBoy", STR)
|
||||
|
||||
QList<GBModel> GameBoy::modelList() {
|
||||
return s_gbModelList;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>IOViewer</class>
|
||||
<widget class="QWidget" name="IOViewer">
|
||||
<class>QGBA::IOViewer</class>
|
||||
<widget class="QWidget" name="QGBA::IOViewer">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LoadSaveState</class>
|
||||
<widget class="QWidget" name="LoadSaveState">
|
||||
<class>QGBA::LoadSaveState</class>
|
||||
<widget class="QWidget" name="QGBA::LoadSaveState">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LogView</class>
|
||||
<widget class="QWidget" name="LogView">
|
||||
<class>QGBA::LogView</class>
|
||||
<widget class="QWidget" name="QGBA::LogView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -42,6 +42,7 @@ MapView::MapView(std::shared_ptr<CoreController> controller, QWidget* parent)
|
|||
#ifdef M_CORE_GBA
|
||||
case mPLATFORM_GBA:
|
||||
m_boundary = 2048;
|
||||
m_ui.tile->setMaxTile(3096);
|
||||
m_addressBase = BASE_VRAM;
|
||||
m_addressWidth = 8;
|
||||
m_ui.bgInfo->addCustomProperty("priority", tr("Priority"));
|
||||
|
@ -55,6 +56,7 @@ MapView::MapView(std::shared_ptr<CoreController> controller, QWidget* parent)
|
|||
#ifdef M_CORE_GB
|
||||
case mPLATFORM_GB:
|
||||
m_boundary = 1024;
|
||||
m_ui.tile->setMaxTile(512);
|
||||
m_addressBase = GB_BASE_VRAM;
|
||||
m_addressWidth = 4;
|
||||
m_ui.bgInfo->addCustomProperty("screenBase", tr("Map base"));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MapView</class>
|
||||
<widget class="QWidget" name="MapView">
|
||||
<class>QGBA::MapView</class>
|
||||
<widget class="QWidget" name="QGBA::MapView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MemoryDump</class>
|
||||
<widget class="QDialog" name="MemoryDump">
|
||||
<class>QGBA::MemoryDump</class>
|
||||
<widget class="QDialog" name="QGBA::MemoryDump">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -126,7 +126,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>MemoryDump</receiver>
|
||||
<receiver>QGBA::MemoryDump</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
@ -142,7 +142,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MemoryDump</receiver>
|
||||
<receiver>QGBA::MemoryDump</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MemorySearch</class>
|
||||
<widget class="QWidget" name="MemorySearch">
|
||||
<class>QGBA::MemorySearch</class>
|
||||
<widget class="QWidget" name="QGBA::MemorySearch">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -367,7 +367,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MemorySearch</receiver>
|
||||
<receiver>QGBA::MemorySearch</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MemoryView</class>
|
||||
<widget class="QWidget" name="MemoryView">
|
||||
<class>QGBA::MemoryView</class>
|
||||
<widget class="QWidget" name="QGBA::MemoryView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -116,14 +116,16 @@ void ObjView::updateTilesGBA(bool force) {
|
|||
if (GBAObjAttributesAIs256Color(obj->a)) {
|
||||
m_ui.palette->setText("256-color");
|
||||
m_ui.tile->setBoundary(1024, 1, 3);
|
||||
m_ui.tile->setPalette(0);
|
||||
m_boundary = 1024;
|
||||
tileBase *= 2;
|
||||
m_ui.tile->setMaxTile(1536);
|
||||
m_ui.tile->setPalette(0);
|
||||
} else {
|
||||
m_ui.palette->setText(QString::number(newInfo.paletteId));
|
||||
m_ui.tile->setBoundary(2048, 0, 2);
|
||||
m_ui.tile->setPalette(newInfo.paletteId);
|
||||
m_boundary = 2048;
|
||||
m_ui.tile->setMaxTile(3072);
|
||||
m_ui.tile->setPalette(newInfo.paletteId);
|
||||
}
|
||||
if (newInfo != m_objInfo) {
|
||||
force = true;
|
||||
|
@ -225,6 +227,7 @@ void ObjView::updateTilesGB(bool force) {
|
|||
m_objInfo = newInfo;
|
||||
m_tileOffset = tile;
|
||||
m_boundary = 1024;
|
||||
m_ui.tile->setMaxTile(512);
|
||||
|
||||
int i = 0;
|
||||
m_ui.tile->setPalette(newInfo.paletteId);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ObjView</class>
|
||||
<widget class="QWidget" name="ObjView">
|
||||
<class>QGBA::ObjView</class>
|
||||
<widget class="QWidget" name="QGBA::ObjView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OverrideView</class>
|
||||
<widget class="QWidget" name="OverrideView">
|
||||
<class>QGBA::OverrideView</class>
|
||||
<widget class="QWidget" name="QGBA::OverrideView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PaletteView</class>
|
||||
<widget class="QWidget" name="PaletteView">
|
||||
<class>QGBA::PaletteView</class>
|
||||
<widget class="QWidget" name="QGBA::PaletteView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PlacementControl</class>
|
||||
<widget class="QDialog" name="PlacementControl">
|
||||
<class>QGBA::PlacementControl</class>
|
||||
<widget class="QDialog" name="QGBA::PlacementControl">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PrinterView</class>
|
||||
<widget class="QWidget" name="PrinterView">
|
||||
<class>QGBA::PrinterView</class>
|
||||
<widget class="QWidget" name="QGBA::PrinterView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -250,7 +250,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>PrinterView</receiver>
|
||||
<receiver>QGBA::PrinterView</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -9,12 +9,6 @@
|
|||
#include "CoreController.h"
|
||||
|
||||
#include <mgba/core/core.h>
|
||||
#ifdef M_CORE_GB
|
||||
#include <mgba/internal/gb/gb.h>
|
||||
#endif
|
||||
#ifdef M_CORE_GBA
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
#endif
|
||||
#ifdef USE_SQLITE3
|
||||
#include "feature/sqlite3/no-intro.h"
|
||||
#endif
|
||||
|
@ -46,25 +40,8 @@ ROMInfo::ROMInfo(std::shared_ptr<CoreController> controller, QWidget* parent)
|
|||
|
||||
core->checksum(core, &crc32, mCHECKSUM_CRC32);
|
||||
|
||||
switch (controller->thread()->core->platform(controller->thread()->core)) {
|
||||
#ifdef M_CORE_GBA
|
||||
case mPLATFORM_GBA: {
|
||||
GBA* gba = static_cast<GBA*>(core->board);
|
||||
m_ui.size->setText(QString::number(gba->pristineRomSize) + tr(" bytes"));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef M_CORE_GB
|
||||
case mPLATFORM_GB: {
|
||||
GB* gb = static_cast<GB*>(core->board);
|
||||
m_ui.size->setText(QString::number(gb->pristineRomSize) + tr(" bytes"));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
m_ui.size->setText(tr("(unknown)"));
|
||||
break;
|
||||
}
|
||||
m_ui.size->setText(QString::number(core->romSize(core)) + tr(" bytes"));
|
||||
|
||||
if (crc32) {
|
||||
m_ui.crc->setText(QString::number(crc32, 16));
|
||||
#ifdef USE_SQLITE3
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ROMInfo</class>
|
||||
<widget class="QDialog" name="ROMInfo">
|
||||
<class>QGBA::ROMInfo</class>
|
||||
<widget class="QDialog" name="QGBA::ROMInfo">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ReportView</class>
|
||||
<widget class="QDialog" name="ReportView">
|
||||
<class>QGBA::ReportView</class>
|
||||
<widget class="QDialog" name="QGBA::ReportView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -163,7 +163,7 @@
|
|||
<connection>
|
||||
<sender>openList</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>ReportView</receiver>
|
||||
<receiver>QGBA::ReportView</receiver>
|
||||
<slot>openBugReportPage()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
@ -179,7 +179,7 @@
|
|||
<connection>
|
||||
<sender>generate</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>ReportView</receiver>
|
||||
<receiver>QGBA::ReportView</receiver>
|
||||
<slot>generateReport()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
@ -195,7 +195,7 @@
|
|||
<connection>
|
||||
<sender>save</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>ReportView</receiver>
|
||||
<receiver>QGBA::ReportView</receiver>
|
||||
<slot>save()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -447,14 +447,14 @@ SaveConverter::AnnotatedSave::operator QString() const {
|
|||
QString typeFormat("%1");
|
||||
QString endianStr;
|
||||
QString saveType;
|
||||
QString format = QCoreApplication::translate("SaveConverter", "%1 %2 save game");
|
||||
QString format = QCoreApplication::translate("QGBA::SaveConverter", "%1 %2 save game");
|
||||
|
||||
switch (endianness) {
|
||||
case Endian::LITTLE:
|
||||
endianStr = QCoreApplication::translate("SaveConverter", "little endian");
|
||||
endianStr = QCoreApplication::translate("QGBA::SaveConverter", "little endian");
|
||||
break;
|
||||
case Endian::BIG:
|
||||
endianStr = QCoreApplication::translate("SaveConverter", "big endian");
|
||||
endianStr = QCoreApplication::translate("QGBA::SaveConverter", "big endian");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -465,15 +465,15 @@ SaveConverter::AnnotatedSave::operator QString() const {
|
|||
case mPLATFORM_GBA:
|
||||
switch (gba.type) {
|
||||
case SAVEDATA_SRAM:
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "SRAM");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "SRAM");
|
||||
break;
|
||||
case SAVEDATA_FLASH512:
|
||||
case SAVEDATA_FLASH1M:
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "%1 flash");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 flash");
|
||||
break;
|
||||
case SAVEDATA_EEPROM:
|
||||
case SAVEDATA_EEPROM512:
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "%1 EEPROM");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 EEPROM");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -485,29 +485,29 @@ SaveConverter::AnnotatedSave::operator QString() const {
|
|||
switch (gb.type) {
|
||||
case GB_MBC_AUTODETECT:
|
||||
if (size & 0xFF) {
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "%1 SRAM + RTC");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 SRAM + RTC");
|
||||
} else {
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "%1 SRAM");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 SRAM");
|
||||
}
|
||||
break;
|
||||
case GB_MBC2:
|
||||
if (size == 0x100) {
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "packed MBC2");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "packed MBC2");
|
||||
} else {
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "unpacked MBC2");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "unpacked MBC2");
|
||||
}
|
||||
break;
|
||||
case GB_MBC6:
|
||||
if (size == GB_SIZE_MBC6_FLASH) {
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "MBC6 flash");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "MBC6 flash");
|
||||
} else if (size > GB_SIZE_MBC6_FLASH) {
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "MBC6 combined SRAM + flash");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "MBC6 combined SRAM + flash");
|
||||
} else {
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "MBC6 SRAM");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "MBC6 SRAM");
|
||||
}
|
||||
break;
|
||||
case GB_TAMA5:
|
||||
typeFormat = QCoreApplication::translate("SaveConverter", "TAMA5");
|
||||
typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "TAMA5");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -519,17 +519,17 @@ SaveConverter::AnnotatedSave::operator QString() const {
|
|||
}
|
||||
saveType = typeFormat.arg(sizeStr);
|
||||
if (!endianStr.isEmpty()) {
|
||||
saveType = QCoreApplication::translate("SaveConverter", "%1 (%2)").arg(saveType).arg(endianStr);
|
||||
saveType = QCoreApplication::translate("QGBA::SaveConverter", "%1 (%2)").arg(saveType).arg(endianStr);
|
||||
}
|
||||
switch (container) {
|
||||
case Container::SAVESTATE:
|
||||
format = QCoreApplication::translate("SaveConverter", "%1 save state with embedded %2 save game");
|
||||
format = QCoreApplication::translate("QGBA::SaveConverter", "%1 save state with embedded %2 save game");
|
||||
break;
|
||||
case Container::SHARKPORT:
|
||||
format = QCoreApplication::translate("SaveConverter", "%1 SharkPort %2 save game");
|
||||
format = QCoreApplication::translate("QGBA::SaveConverter", "%1 SharkPort %2 save game");
|
||||
break;
|
||||
case Container::GSV:
|
||||
format = QCoreApplication::translate("SaveConverter", "%1 GameShark Advance SP %2 save game");
|
||||
format = QCoreApplication::translate("QGBA::SaveConverter", "%1 GameShark Advance SP %2 save game");
|
||||
break;
|
||||
case Container::NONE:
|
||||
break;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SaveConverter</class>
|
||||
<widget class="QDialog" name="SaveConverter">
|
||||
<class>QGBA::SaveConverter</class>
|
||||
<widget class="QDialog" name="QGBA::SaveConverter">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -91,7 +91,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>SaveConverter</receiver>
|
||||
<receiver>QGBA::SaveConverter</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
@ -107,7 +107,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>SaveConverter</receiver>
|
||||
<receiver>QGBA::SaveConverter</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SensorView</class>
|
||||
<widget class="QWidget" name="SensorView">
|
||||
<class>QGBA::SensorView</class>
|
||||
<widget class="QWidget" name="QGBA::SensorView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -35,16 +35,17 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
m_ui.setupUi(this);
|
||||
|
||||
m_pageIndex[Page::AV] = 0;
|
||||
m_pageIndex[Page::INTERFACE] = 1;
|
||||
m_pageIndex[Page::UPDATE] = 2;
|
||||
m_pageIndex[Page::EMULATION] = 3;
|
||||
m_pageIndex[Page::ENHANCEMENTS] = 4;
|
||||
m_pageIndex[Page::BIOS] = 5;
|
||||
m_pageIndex[Page::PATHS] = 6;
|
||||
m_pageIndex[Page::LOGGING] = 7;
|
||||
m_pageIndex[Page::GAMEPLAY] = 1;
|
||||
m_pageIndex[Page::INTERFACE] = 2;
|
||||
m_pageIndex[Page::UPDATE] = 3;
|
||||
m_pageIndex[Page::EMULATION] = 4;
|
||||
m_pageIndex[Page::ENHANCEMENTS] = 5;
|
||||
m_pageIndex[Page::BIOS] = 6;
|
||||
m_pageIndex[Page::PATHS] = 7;
|
||||
m_pageIndex[Page::LOGGING] = 8;
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
m_pageIndex[Page::GB] = 8;
|
||||
m_pageIndex[Page::GB] = 9;
|
||||
|
||||
for (auto model : GameBoy::modelList()) {
|
||||
m_ui.gbModel->addItem(GameBoy::modelName(model), model);
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
enum class Page {
|
||||
AV,
|
||||
INTERFACE,
|
||||
GAMEPLAY,
|
||||
UPDATE,
|
||||
EMULATION,
|
||||
ENHANCEMENTS,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsView</class>
|
||||
<widget class="QWidget" name="SettingsView">
|
||||
<class>QGBA::SettingsView</class>
|
||||
<widget class="QWidget" name="QGBA::SettingsView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -45,6 +45,11 @@
|
|||
<string>Audio/Video</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Gameplay</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
|
@ -87,23 +92,19 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>9</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="av">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
|
||||
<layout class="QVBoxLayout" name="formLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Audio</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_12">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
|
@ -238,14 +239,14 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Volume:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QSlider" name="volume">
|
||||
|
@ -278,14 +279,14 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_34">
|
||||
<property name="text">
|
||||
<string>Fast forward volume:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="5" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_17">
|
||||
<item>
|
||||
<widget class="QSlider" name="volumeFf">
|
||||
|
@ -318,14 +319,14 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_43">
|
||||
<property name="text">
|
||||
<string>Audio in multiplayer:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QRadioButton" name="multiplayerAudioAll">
|
||||
<property name="text">
|
||||
<string>All windows</string>
|
||||
|
@ -338,7 +339,7 @@
|
|||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="8" column="1">
|
||||
<widget class="QRadioButton" name="multiplayerAudio1">
|
||||
<property name="text">
|
||||
<string>Player 1 window only</string>
|
||||
|
@ -348,7 +349,7 @@
|
|||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="QRadioButton" name="multiplayerAudioActive">
|
||||
<property name="text">
|
||||
<string>Currently active player window</string>
|
||||
|
@ -358,21 +359,37 @@
|
|||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="Line" name="line_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="Line" name="line_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Video</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_13">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Display driver:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="displayDriver">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
|
@ -382,14 +399,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Frameskip:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_12">
|
||||
|
@ -410,14 +427,56 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="lockAspectRatio">
|
||||
<property name="text">
|
||||
<string>Lock aspect ratio</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="lockIntegerScaling">
|
||||
<property name="text">
|
||||
<string>Force integer scaling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="interframeBlending">
|
||||
<property name="text">
|
||||
<string>Interframe blending</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="resampleVideo">
|
||||
<property name="text">
|
||||
<string>Bilinear filtering</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="Line" name="line_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="gameplay">
|
||||
<layout class="QFormLayout" name="formLayout_14">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>FPS target:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="fpsTarget">
|
||||
|
@ -444,28 +503,21 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="nativeGB">
|
||||
<property name="text">
|
||||
<string>Native (59.7275)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0" colspan="2">
|
||||
<widget class="Line" name="line_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Sync:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="videoSync">
|
||||
|
@ -483,31 +535,160 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QCheckBox" name="lockAspectRatio">
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="Line" name="line_16">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Lock aspect ratio</string>
|
||||
<string>On loading a game:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="autoload">
|
||||
<property name="text">
|
||||
<string>Load last state</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="cheatAutoload">
|
||||
<property name="text">
|
||||
<string>Load cheats</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="Line" name="line_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="autosave">
|
||||
<property name="text">
|
||||
<string>Periodically autosave state</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QCheckBox" name="cheatAutosave">
|
||||
<property name="text">
|
||||
<string>Save entered cheats</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="Line" name="line_21">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_51">
|
||||
<property name="text">
|
||||
<string>Save state extra data:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QCheckBox" name="saveStateScreenshot">
|
||||
<property name="text">
|
||||
<string>Screenshot</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QCheckBox" name="saveStateSave">
|
||||
<property name="text">
|
||||
<string>Save game</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QCheckBox" name="saveStateCheats">
|
||||
<property name="text">
|
||||
<string>Cheat codes</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0" colspan="2">
|
||||
<widget class="Line" name="line_22">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="label_52">
|
||||
<property name="text">
|
||||
<string>Load state extra data:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QCheckBox" name="loadStateScreenshot">
|
||||
<property name="text">
|
||||
<string>Screenshot</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QCheckBox" name="loadStateSave">
|
||||
<property name="text">
|
||||
<string>Save game</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="QCheckBox" name="lockIntegerScaling">
|
||||
<widget class="QCheckBox" name="loadStateCheats">
|
||||
<property name="text">
|
||||
<string>Force integer scaling</string>
|
||||
<string>Cheat codes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="1">
|
||||
<widget class="QCheckBox" name="interframeBlending">
|
||||
<property name="text">
|
||||
<string>Interframe blending</string>
|
||||
<item row="17" column="0" colspan="2">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="1">
|
||||
<widget class="QCheckBox" name="resampleVideo">
|
||||
<widget class="QCheckBox" name="useDiscordPresence">
|
||||
<property name="text">
|
||||
<string>Bilinear filtering</string>
|
||||
<string>Enable Discord Rich Presence</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -726,67 +907,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="18" column="1">
|
||||
<widget class="QCheckBox" name="useDiscordPresence">
|
||||
<property name="text">
|
||||
<string>Enable Discord Rich Presence</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="19" column="0" colspan="2">
|
||||
<widget class="Line" name="line_13">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="20" column="1">
|
||||
<widget class="QCheckBox" name="autosave">
|
||||
<property name="text">
|
||||
<string>Automatically save state</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="21" column="1">
|
||||
<widget class="QCheckBox" name="autoload">
|
||||
<property name="text">
|
||||
<string>Automatically load state</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="22" column="0" colspan="2">
|
||||
<widget class="Line" name="line_16">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="23" column="1">
|
||||
<widget class="QCheckBox" name="cheatAutosave">
|
||||
<property name="text">
|
||||
<string>Automatically save cheats</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="24" column="1">
|
||||
<widget class="QCheckBox" name="cheatAutoload">
|
||||
<property name="text">
|
||||
<string>Automatically load cheats</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="update">
|
||||
|
@ -1097,88 +1217,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="2">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Save state extra data:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QCheckBox" name="saveStateScreenshot">
|
||||
<property name="text">
|
||||
<string>Screenshot</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QCheckBox" name="saveStateSave">
|
||||
<property name="text">
|
||||
<string>Save game</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QCheckBox" name="saveStateCheats">
|
||||
<property name="text">
|
||||
<string>Cheat codes</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0" colspan="2">
|
||||
<widget class="Line" name="line_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>Load state extra data:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="QCheckBox" name="loadStateScreenshot">
|
||||
<property name="text">
|
||||
<string>Screenshot</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="1">
|
||||
<widget class="QCheckBox" name="loadStateSave">
|
||||
<property name="text">
|
||||
<string>Save game</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="1">
|
||||
<widget class="QCheckBox" name="loadStateCheats">
|
||||
<property name="text">
|
||||
<string>Cheat codes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="enhancements">
|
||||
|
@ -2226,6 +2264,13 @@
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
@ -2233,7 +2278,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>SettingsView</receiver>
|
||||
<receiver>QGBA::SettingsView</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
@ -2249,7 +2294,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>SettingsView</receiver>
|
||||
<receiver>QGBA::SettingsView</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ShaderSelector</class>
|
||||
<widget class="QDialog" name="ShaderSelector">
|
||||
<class>QGBA::ShaderSelector</class>
|
||||
<widget class="QDialog" name="QGBA::ShaderSelector">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ShortcutView</class>
|
||||
<widget class="QWidget" name="ShortcutView">
|
||||
<class>QGBA::ShortcutView</class>
|
||||
<widget class="QWidget" name="QGBA::ShortcutView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -51,6 +51,7 @@ TileView::TileView(std::shared_ptr<CoreController> controller, QWidget* parent)
|
|||
#ifdef M_CORE_GBA
|
||||
case mPLATFORM_GBA:
|
||||
m_ui.tile->setBoundary(2048, 0, 2);
|
||||
m_ui.tile->setMaxTile(3096);
|
||||
break;
|
||||
#endif
|
||||
#ifdef M_CORE_GB
|
||||
|
@ -60,6 +61,7 @@ TileView::TileView(std::shared_ptr<CoreController> controller, QWidget* parent)
|
|||
m_ui.tilesBoth->setEnabled(false);
|
||||
m_ui.palette256->setEnabled(false);
|
||||
m_ui.tile->setBoundary(1024, 0, 0);
|
||||
m_ui.tile->setMaxTile(512);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -74,6 +76,7 @@ TileView::TileView(std::shared_ptr<CoreController> controller, QWidget* parent)
|
|||
#ifdef M_CORE_GBA
|
||||
case mPLATFORM_GBA:
|
||||
m_ui.tile->setBoundary(2048 >> selected, selected, selected + 2);
|
||||
m_ui.tile->setMaxTile(3096 >> selected);
|
||||
break;
|
||||
#endif
|
||||
#ifdef M_CORE_GB
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TileView</class>
|
||||
<widget class="QWidget" name="TileView">
|
||||
<class>QGBA::TileView</class>
|
||||
<widget class="QWidget" name="QGBA::TileView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>VideoView</class>
|
||||
<widget class="QWidget" name="VideoView">
|
||||
<class>QGBA::VideoView</class>
|
||||
<widget class="QWidget" name="QGBA::VideoView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
|
|
@ -1382,10 +1382,6 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
#ifdef M_CORE_GBA
|
||||
Action* scanCard = addGameAction(tr("Scan e-Reader dotcodes..."), "scanCard", this, &Window::scanCard, "file");
|
||||
m_platformActions.insert(mPLATFORM_GBA, scanCard);
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
m_actions.addAction(tr("Convert e-Reader card image to raw..."), "parseCard", this, &Window::parseCard, "file");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
addGameAction(tr("ROM &info..."), "romInfo", openControllerTView<ROMInfo>(), "file");
|
||||
|
@ -1739,6 +1735,9 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
m_actions.addAction(tr("Game Pak sensors..."), "sensorWindow", openNamedControllerTView<SensorView>(&m_sensorView, &m_inputController), "tools");
|
||||
|
||||
addGameAction(tr("&Cheats..."), "cheatsWindow", openControllerTView<CheatsView>(), "tools");
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
m_actions.addAction(tr("Scripting..."), "scripting", this, &Window::scriptingOpen, "tools");
|
||||
#endif
|
||||
|
||||
m_actions.addSeparator("tools");
|
||||
m_actions.addAction(tr("Settings..."), "settings", this, &Window::openSettingsWindow, "tools")->setRole(Action::Role::SETTINGS);
|
||||
|
@ -1752,17 +1751,15 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
m_platformActions.insert(mPLATFORM_GBA, gdbWindow);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
m_actions.addAction(tr("Scripting..."), "scripting", this, &Window::scriptingOpen, "tools");
|
||||
#endif
|
||||
#if defined(USE_DEBUGGERS) || defined(ENABLE_SCRIPTING)
|
||||
m_actions.addSeparator("tools");
|
||||
#endif
|
||||
|
||||
addGameAction(tr("View &palette..."), "paletteWindow", openControllerTView<PaletteView>(), "tools");
|
||||
addGameAction(tr("View &sprites..."), "spriteWindow", openControllerTView<ObjView>(), "tools");
|
||||
addGameAction(tr("View &tiles..."), "tileWindow", openControllerTView<TileView>(), "tools");
|
||||
addGameAction(tr("View &map..."), "mapWindow", openControllerTView<MapView>(), "tools");
|
||||
m_actions.addMenu(tr("Game state views"), "stateViews", "tools");
|
||||
addGameAction(tr("View &palette..."), "paletteWindow", openControllerTView<PaletteView>(), "stateViews");
|
||||
addGameAction(tr("View &sprites..."), "spriteWindow", openControllerTView<ObjView>(), "stateViews");
|
||||
addGameAction(tr("View &tiles..."), "tileWindow", openControllerTView<TileView>(), "stateViews");
|
||||
addGameAction(tr("View &map..."), "mapWindow", openControllerTView<MapView>(), "stateViews");
|
||||
|
||||
addGameAction(tr("&Frame inspector..."), "frameWindow", [this]() {
|
||||
if (!m_frameView) {
|
||||
|
@ -1778,11 +1775,16 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
m_frameView->setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
m_frameView->show();
|
||||
}, "tools");
|
||||
}, "stateViews");
|
||||
|
||||
addGameAction(tr("View memory..."), "memoryView", openControllerTView<MemoryView>(), "tools");
|
||||
addGameAction(tr("Search memory..."), "memorySearch", openControllerTView<MemorySearch>(), "tools");
|
||||
addGameAction(tr("View &I/O registers..."), "ioViewer", openControllerTView<IOViewer>(), "tools");
|
||||
addGameAction(tr("View memory..."), "memoryView", openControllerTView<MemoryView>(), "stateViews");
|
||||
addGameAction(tr("Search memory..."), "memorySearch", openControllerTView<MemorySearch>(), "stateViews");
|
||||
addGameAction(tr("View &I/O registers..."), "ioViewer", openControllerTView<IOViewer>(), "stateViews");
|
||||
|
||||
#if defined(USE_FFMPEG) && defined(M_CORE_GBA)
|
||||
m_actions.addSeparator("tools");
|
||||
m_actions.addAction(tr("Convert e-Reader card image to raw..."), "parseCard", this, &Window::parseCard, "tools");
|
||||
#endif
|
||||
|
||||
m_actions.addSeparator("tools");
|
||||
addGameAction(tr("Record debug video log..."), "recordVL", this, &Window::startVideoLog, "tools");
|
||||
|
|
|
@ -48,11 +48,11 @@ LibraryTree::LibraryTree(LibraryController* parent)
|
|||
m_widget->setAlternatingRowColors(true);
|
||||
|
||||
QTreeWidgetItem* header = new QTreeWidgetItem({
|
||||
QApplication::translate("LibraryTree", "Name", nullptr),
|
||||
QApplication::translate("LibraryTree", "Location", nullptr),
|
||||
QApplication::translate("LibraryTree", "Platform", nullptr),
|
||||
QApplication::translate("LibraryTree", "Size", nullptr),
|
||||
QApplication::translate("LibraryTree", "CRC32", nullptr),
|
||||
QApplication::translate("QGBA::LibraryTree", "Name", nullptr),
|
||||
QApplication::translate("QGBA::LibraryTree", "Location", nullptr),
|
||||
QApplication::translate("QGBA::LibraryTree", "Platform", nullptr),
|
||||
QApplication::translate("QGBA::LibraryTree", "Size", nullptr),
|
||||
QApplication::translate("QGBA::LibraryTree", "CRC32", nullptr),
|
||||
});
|
||||
header->setTextAlignment(3, Qt::AlignTrailing | Qt::AlignVCenter);
|
||||
m_widget->setHeaderItem(header);
|
||||
|
|
|
@ -61,6 +61,9 @@ void ScriptingController::setController(std::shared_ptr<CoreController> controll
|
|||
|
||||
bool ScriptingController::loadFile(const QString& path) {
|
||||
VFileDevice vf(path, QIODevice::ReadOnly);
|
||||
if (!vf.isOpen()) {
|
||||
return false;
|
||||
}
|
||||
return load(vf, path);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,37 +1,56 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ScriptingView</class>
|
||||
<widget class="QMainWindow" name="ScriptingView">
|
||||
<class>QGBA::ScriptingView</class>
|
||||
<widget class="QMainWindow" name="QGBA::ScriptingView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
<width>843</width>
|
||||
<height>637</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Scripting</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" rowspan="3">
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QListView" name="buffers">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>90</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>180</width>
|
||||
<width>200</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLineEdit" name="prompt"/>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="runButton">
|
||||
<property name="text">
|
||||
<string>Run</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QSplitter" name="splitter_1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QPlainTextEdit" name="buffer">
|
||||
<property name="lineWrapMode">
|
||||
<enum>QPlainTextEdit::NoWrap</enum>
|
||||
|
@ -40,8 +59,6 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QGBA::LogWidget" name="log">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
|
@ -53,15 +70,10 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="prompt"/>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="runButton">
|
||||
<property name="text">
|
||||
<string>Run</string>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
file(WRITE ${TRANSLATION_QRC} "<RCC>\n\t<qresource prefix=\"/translations/\">\n")
|
||||
foreach(TS ${TRANSLATION_FILES})
|
||||
get_filename_component(TS_BASE "${TS}" NAME)
|
||||
file(APPEND ${TRANSLATION_QRC} "\t\t<file alias=\"${TS_BASE}\">${TS}</file>\n")
|
||||
endforeach()
|
||||
file(APPEND ${TRANSLATION_QRC} "\t</qresource>\n</RCC>")
|