Merge branch 'master' (early part) into medusa

This commit is contained in:
Vicki Pfau 2022-08-23 21:03:43 -07:00
commit 77e811acaf
114 changed files with 49551 additions and 44806 deletions

View File

@ -91,6 +91,8 @@ Emulation fixes:
- GBA Video: Fix sprite layer priority updating in GL - GBA Video: Fix sprite layer priority updating in GL
Other fixes: Other fixes:
- ARM: Disassemble Thumb mov pseudo-instruction properly - 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: 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 the runloop resuming after a game has crashed (fixes mgba.io/i/2451)
- Core: Fix crash if library can't be opened - 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 crash when encoding audio with some containers
- FFmpeg: Fix GIF recording (fixes mgba.io/i/2393) - FFmpeg: Fix GIF recording (fixes mgba.io/i/2393)
- GB: Fix temporary saves - 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) - GB, GBA: Save writeback-pending masked saves on unload (fixes mgba.io/i/2396)
- mGUI: Fix FPS counter after closing menu - mGUI: Fix FPS counter after closing menu
- Qt: Fix some hangs when using the debugger console - Qt: Fix some hangs when using the debugger console
- Qt: Fix crash when clicking past last tile in viewer - Qt: Fix crash when clicking past last tile in viewer
- Qt: Fix preloading for ROM replacing - Qt: Fix preloading for ROM replacing
- Qt: Fix screen not displaying on Wayland (fixes mgba.io/i/2190) - 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 - VFS: Failed file mapping should return NULL on POSIX
Misc: Misc:
- Core: Suspend runloop when a core crashes - Core: Suspend runloop when a core crashes

View File

@ -771,6 +771,7 @@ if(ENABLE_SCRIPTING)
include_directories(AFTER ${LUA_INCLUDE_DIR}) include_directories(AFTER ${LUA_INCLUDE_DIR})
list(APPEND FEATURE_DEFINES LUA_VERSION_ONLY=\"${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}\") list(APPEND FEATURE_DEFINES LUA_VERSION_ONLY=\"${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}\")
list(APPEND DEPENDENCY_LIB ${LUA_LIBRARY}) list(APPEND DEPENDENCY_LIB ${LUA_LIBRARY})
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},liblua${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}-0")
endif() endif()
if(BUILD_PYTHON) if(BUILD_PYTHON)

View File

@ -140,13 +140,15 @@ Compiling requires using CMake 3.1 or newer. GCC and Clang are both known to wor
#### Docker building #### Docker building
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. 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: 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/3ds
- mgba/switch - mgba/switch
@ -159,6 +161,8 @@ This will produce a `build-win32` directory with the build products. Replace `mg
- mgba/windows:w32 - mgba/windows:w32
- mgba/windows:w64 - 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 #### *nix building
To use CMake to build on a Unix-based system, the recommended commands are as follows: To use CMake to build on a Unix-based system, the recommended commands are as follows:

View File

@ -88,6 +88,7 @@ struct mCore {
bool (*loadSave)(struct mCore*, struct VFile* vf); bool (*loadSave)(struct mCore*, struct VFile* vf);
bool (*loadTemporarySave)(struct mCore*, struct VFile* vf); bool (*loadTemporarySave)(struct mCore*, struct VFile* vf);
void (*unloadROM)(struct mCore*); void (*unloadROM)(struct mCore*);
size_t (*romSize)(const struct mCore*);
void (*checksum)(const struct mCore*, void* data, enum mCoreChecksumType type); void (*checksum)(const struct mCore*, void* data, enum mCoreChecksumType type);
bool (*loadBIOS)(struct mCore*, struct VFile* vf, int biosID); bool (*loadBIOS)(struct mCore*, struct VFile* vf, int biosID);
@ -186,6 +187,8 @@ bool mCoreAutoloadSave(struct mCore* core);
bool mCoreAutoloadPatch(struct mCore* core); bool mCoreAutoloadPatch(struct mCore* core);
bool mCoreAutoloadCheats(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 mCoreSaveState(struct mCore* core, int slot, int flags);
bool mCoreLoadState(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); struct VFile* mCoreGetState(struct mCore* core, int slot, bool write);

View File

@ -36,6 +36,12 @@ struct mLogger {
struct mLogFilter* filter; struct mLogFilter* filter;
}; };
struct mStandardLogger {
struct mLogger d;
bool logToStdout;
struct VFile* logFile;
};
struct mLogger* mLogGetContext(void); struct mLogger* mLogGetContext(void);
void mLogSetDefaultLogger(struct mLogger*); void mLogSetDefaultLogger(struct mLogger*);
int mLogGenerateCategory(const char*, const char*); int mLogGenerateCategory(const char*, const char*);
@ -44,6 +50,10 @@ const char* mLogCategoryId(int);
int mLogCategoryById(const char*); int mLogCategoryById(const char*);
struct mCoreConfig; struct mCoreConfig;
void mStandardLoggerInit(struct mStandardLogger*);
void mStandardLoggerDeinit(struct mStandardLogger*);
void mStandardLoggerConfig(struct mStandardLogger*, struct mCoreConfig* config);
void mLogFilterInit(struct mLogFilter*); void mLogFilterInit(struct mLogFilter*);
void mLogFilterDeinit(struct mLogFilter*); void mLogFilterDeinit(struct mLogFilter*);
void mLogFilterLoad(struct mLogFilter*, const struct mCoreConfig*); void mLogFilterLoad(struct mLogFilter*, const struct mCoreConfig*);

View File

@ -21,6 +21,7 @@ struct mCoreThread;
struct mThreadLogger { struct mThreadLogger {
struct mLogger d; struct mLogger d;
struct mCoreThread* p; struct mCoreThread* p;
struct mLogger* logger;
}; };
#ifdef ENABLE_SCRIPTING #ifdef ENABLE_SCRIPTING

View File

@ -67,10 +67,11 @@ struct ParseTree {
}; };
size_t lexExpression(struct LexVector* lv, const char* string, size_t length, const char* eol); 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); void lexFree(struct LexVector* lv);
struct ParseTree* parseTreeCreate(void);
void parseFree(struct ParseTree* tree); void parseFree(struct ParseTree* tree);
bool parseLexedExpression(struct ParseTree* tree, struct LexVector* lv);
struct mDebugger; struct mDebugger;
bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, int32_t* value, int* segment); bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, int32_t* value, int* segment);

View File

@ -155,6 +155,7 @@ struct GBAVideoGLRenderer {
GLuint vbo; GLuint vbo;
GLuint outputTex; GLuint outputTex;
bool outputTexDirty;
GLuint paletteTex; GLuint paletteTex;
uint16_t shadowPalette[GBA_VIDEO_VERTICAL_PIXELS][512]; uint16_t shadowPalette[GBA_VIDEO_VERTICAL_PIXELS][512];

View File

@ -459,6 +459,7 @@ CXX_GUARD_START
#define mSCRIPT_MAKE_S64(VALUE) mSCRIPT_MAKE(S64, VALUE) #define mSCRIPT_MAKE_S64(VALUE) mSCRIPT_MAKE(S64, VALUE)
#define mSCRIPT_MAKE_U64(VALUE) mSCRIPT_MAKE(U64, VALUE) #define mSCRIPT_MAKE_U64(VALUE) mSCRIPT_MAKE(U64, VALUE)
#define mSCRIPT_MAKE_F64(VALUE) mSCRIPT_MAKE(F64, 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_CHARP(VALUE) mSCRIPT_MAKE(CHARP, VALUE)
#define mSCRIPT_MAKE_S(STRUCT, VALUE) mSCRIPT_MAKE(S(STRUCT), VALUE) #define mSCRIPT_MAKE_S(STRUCT, VALUE) mSCRIPT_MAKE(S(STRUCT), VALUE)
#define mSCRIPT_MAKE_CS(STRUCT, VALUE) mSCRIPT_MAKE(CS(STRUCT), VALUE) #define mSCRIPT_MAKE_CS(STRUCT, VALUE) mSCRIPT_MAKE(CS(STRUCT), VALUE)

View File

@ -27,6 +27,7 @@ CXX_GUARD_START
#define mSCRIPT_TYPE_C_S64 int64_t #define mSCRIPT_TYPE_C_S64 int64_t
#define mSCRIPT_TYPE_C_U64 uint64_t #define mSCRIPT_TYPE_C_U64 uint64_t
#define mSCRIPT_TYPE_C_F64 double #define mSCRIPT_TYPE_C_F64 double
#define mSCRIPT_TYPE_C_BOOL bool
#define mSCRIPT_TYPE_C_STR struct mScriptString* #define mSCRIPT_TYPE_C_STR struct mScriptString*
#define mSCRIPT_TYPE_C_CHARP const char* #define mSCRIPT_TYPE_C_CHARP const char*
#define mSCRIPT_TYPE_C_PTR void* #define mSCRIPT_TYPE_C_PTR void*
@ -55,6 +56,7 @@ CXX_GUARD_START
#define mSCRIPT_TYPE_FIELD_S64 s64 #define mSCRIPT_TYPE_FIELD_S64 s64
#define mSCRIPT_TYPE_FIELD_U64 u64 #define mSCRIPT_TYPE_FIELD_U64 u64
#define mSCRIPT_TYPE_FIELD_F64 f64 #define mSCRIPT_TYPE_FIELD_F64 f64
#define mSCRIPT_TYPE_FIELD_BOOL u32
#define mSCRIPT_TYPE_FIELD_STR string #define mSCRIPT_TYPE_FIELD_STR string
#define mSCRIPT_TYPE_FIELD_CHARP copaque #define mSCRIPT_TYPE_FIELD_CHARP copaque
#define mSCRIPT_TYPE_FIELD_PTR opaque #define mSCRIPT_TYPE_FIELD_PTR opaque
@ -82,6 +84,7 @@ CXX_GUARD_START
#define mSCRIPT_TYPE_MS_S64 (&mSTSInt64) #define mSCRIPT_TYPE_MS_S64 (&mSTSInt64)
#define mSCRIPT_TYPE_MS_U64 (&mSTUInt64) #define mSCRIPT_TYPE_MS_U64 (&mSTUInt64)
#define mSCRIPT_TYPE_MS_F64 (&mSTFloat64) #define mSCRIPT_TYPE_MS_F64 (&mSTFloat64)
#define mSCRIPT_TYPE_MS_BOOL (&mSTBool)
#define mSCRIPT_TYPE_MS_STR (&mSTString) #define mSCRIPT_TYPE_MS_STR (&mSTString)
#define mSCRIPT_TYPE_MS_CHARP (&mSTCharPtr) #define mSCRIPT_TYPE_MS_CHARP (&mSTCharPtr)
#define mSCRIPT_TYPE_MS_LIST (&mSTList) #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_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_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_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_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_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) #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 mSTSInt64;
extern const struct mScriptType mSTUInt64; extern const struct mScriptType mSTUInt64;
extern const struct mScriptType mSTFloat64; extern const struct mScriptType mSTFloat64;
extern const struct mScriptType mSTBool;
extern const struct mScriptType mSTString; extern const struct mScriptType mSTString;
extern const struct mScriptType mSTCharPtr; extern const struct mScriptType mSTCharPtr;
extern const struct mScriptType mSTList; 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 mScriptPopS64(struct mScriptList* list, int64_t* out);
bool mScriptPopU64(struct mScriptList* list, uint64_t* out); bool mScriptPopU64(struct mScriptList* list, uint64_t* out);
bool mScriptPopF64(struct mScriptList* list, double* out); bool mScriptPopF64(struct mScriptList* list, double* out);
bool mScriptPopBool(struct mScriptList* list, bool* out);
bool mScriptPopPointer(struct mScriptList* list, void** out); bool mScriptPopPointer(struct mScriptList* list, void** out);
bool mScriptCast(const struct mScriptType* type, const struct mScriptValue* input, struct mScriptValue* output); bool mScriptCast(const struct mScriptType* type, const struct mScriptValue* input, struct mScriptValue* output);

BIN
res/gb-icon-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

BIN
res/gb-icon-24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

BIN
res/gb-icon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

BIN
res/gba-icon-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

BIN
res/gba-icon-24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 B

BIN
res/gba-icon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
res/gbc-icon-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

BIN
res/gbc-icon-24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

BIN
res/gbc-icon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

View File

@ -19,6 +19,9 @@
info->operandFormat |= ARM_OPERAND_SHIFT_REGISTER_3; \ info->operandFormat |= ARM_OPERAND_SHIFT_REGISTER_3; \
} else { \ } else { \
info->op3.shifterImm = (opcode >> 7) & 0x1F; \ 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; \ info->operandFormat |= ARM_OPERAND_SHIFT_IMMEDIATE_3; \
} }

View File

@ -190,6 +190,9 @@ static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, con
case 4: case 4:
value = cpu->memory.load32(cpu, addrBase, NULL); value = cpu->memory.load32(cpu, addrBase, NULL);
break; break;
default:
// Should never be reached
abort();
} }
const char* label = NULL; const char* label = NULL;
if (symbols) { if (symbols) {
@ -432,6 +435,7 @@ int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* cpu, c
case ARM_MN_LSR: case ARM_MN_LSR:
case ARM_MN_MLA: case ARM_MN_MLA:
case ARM_MN_MUL: case ARM_MN_MUL:
case ARM_MN_MOV:
case ARM_MN_MVN: case ARM_MN_MVN:
case ARM_MN_ORR: case ARM_MN_ORR:
case ARM_MN_ROR: case ARM_MN_ROR:

View File

@ -272,6 +272,18 @@ bool mCoreAutoloadCheats(struct mCore* core) {
return success; 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) { bool mCoreSaveState(struct mCore* core, int slot, int flags) {
struct VFile* vf = mCoreGetState(core, slot, true); struct VFile* vf = mCoreGetState(core, slot, true);
if (!vf) { if (!vf) {
@ -370,6 +382,8 @@ bool mCoreTakeScreenshotVF(struct mCore* core, struct VFile* vf) {
PNGWriteClose(png, info); PNGWriteClose(png, info);
return success; return success;
#else #else
UNUSED(core);
UNUSED(vf);
return false; return false;
#endif #endif
} }

View File

@ -10,92 +10,53 @@
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
void mDirectorySetInit(struct mDirectorySet* dirs) { void mDirectorySetInit(struct mDirectorySet* dirs) {
dirs->base = 0; dirs->base = NULL;
dirs->archive = 0; dirs->archive = NULL;
dirs->save = 0; dirs->save = NULL;
dirs->patch = 0; dirs->patch = NULL;
dirs->state = 0; dirs->state = NULL;
dirs->screenshot = 0; dirs->screenshot = NULL;
dirs->cheats = 0; 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) { void mDirectorySetDeinit(struct mDirectorySet* dirs) {
mDirectorySetDetachBase(dirs); mDirectorySetDetachBase(dirs);
mDirectorySetDetachDir(dirs, dirs->archive);
if (dirs->archive) { mDirectorySetDetachDir(dirs, dirs->save);
if (dirs->archive == dirs->save) { mDirectorySetDetachDir(dirs, dirs->patch);
dirs->save = NULL; mDirectorySetDetachDir(dirs, dirs->state);
} mDirectorySetDetachDir(dirs, dirs->screenshot);
if (dirs->archive == dirs->patch) { mDirectorySetDetachDir(dirs, dirs->cheats);
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;
}
} }
void mDirectorySetAttachBase(struct mDirectorySet* dirs, struct VDir* base) { 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) { void mDirectorySetDetachBase(struct mDirectorySet* dirs) {
if (dirs->save == dirs->base) { mDirectorySetDetachDir(dirs, dirs->archive);
dirs->save = NULL; mDirectorySetDetachDir(dirs, dirs->base);
}
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;
}
} }
struct VFile* mDirectorySetOpenPath(struct mDirectorySet* dirs, const char* path, bool (*filter)(struct VFile*)) { 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; struct VFile* file;
if (dirs->archive) { if (archive) {
file = VDirFindFirst(dirs->archive, filter); file = VDirFindFirst(archive, filter);
if (!file) { if (!file) {
dirs->archive->close(dirs->archive); archive->close(archive);
dirs->archive = 0; } else {
mDirectorySetDetachDir(dirs, dirs->archive);
dirs->archive = archive;
} }
} else { } else {
file = VFileOpen(path, O_RDONLY); file = VFileOpen(path, O_RDONLY);

View File

@ -243,9 +243,11 @@ void mLibraryLoadDirectory(struct mLibrary* library, const char* base, bool recu
struct VFile* vf = dir->openFile(dir, current->filename, O_RDONLY); struct VFile* vf = dir->openFile(dir, current->filename, O_RDONLY);
_mLibraryDeleteEntry(library, current); _mLibraryDeleteEntry(library, current);
if (!vf) { if (!vf) {
mLibraryEntryFree(current);
continue; continue;
} }
_mLibraryAddEntry(library, current->filename, base, vf); _mLibraryAddEntry(library, current->filename, base, vf);
mLibraryEntryFree(current);
} }
mLibraryListingDeinit(&entries); mLibraryListingDeinit(&entries);

View File

@ -7,8 +7,10 @@
#include <mgba/core/config.h> #include <mgba/core/config.h>
#include <mgba/core/thread.h> #include <mgba/core/thread.h>
#include <mgba-util/vfs.h>
#define MAX_CATEGORY 64 #define MAX_CATEGORY 64
#define MAX_LOG_BUF 1024
static struct mLogger* _defaultLogger = NULL; static struct mLogger* _defaultLogger = NULL;
@ -183,4 +185,63 @@ int mLogFilterLevels(const struct mLogFilter* filter , int category) {
return value; 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") mLOG_DEFINE_CATEGORY(STATUS, "Status", "core.status")

View File

@ -215,19 +215,19 @@ static struct mScriptValue* mScriptMemoryDomainReadRange(struct mScriptMemoryDom
static void mScriptMemoryDomainWrite8(struct mScriptMemoryDomain* adapter, uint32_t address, uint8_t value) { static void mScriptMemoryDomainWrite8(struct mScriptMemoryDomain* adapter, uint32_t address, uint8_t value) {
CALCULATE_SEGMENT_INFO; CALCULATE_SEGMENT_INFO;
CALCULATE_SEGMENT_ADDRESS; 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) { static void mScriptMemoryDomainWrite16(struct mScriptMemoryDomain* adapter, uint32_t address, uint16_t value) {
CALCULATE_SEGMENT_INFO; CALCULATE_SEGMENT_INFO;
CALCULATE_SEGMENT_ADDRESS; 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) { static void mScriptMemoryDomainWrite32(struct mScriptMemoryDomain* adapter, uint32_t address, uint32_t value) {
CALCULATE_SEGMENT_INFO; CALCULATE_SEGMENT_INFO;
CALCULATE_SEGMENT_ADDRESS; 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) { static uint32_t mScriptMemoryDomainBase(struct mScriptMemoryDomain* adapter) {
@ -373,6 +373,16 @@ static struct mScriptValue* _mScriptCoreSaveState(struct mCore* core, int32_t fl
return value; 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) { static int32_t _mScriptCoreLoadState(struct mCore* core, struct mScriptString* buffer, int32_t flags) {
struct VFile* vf = VFileFromConstMemory(buffer->buffer, buffer->size); struct VFile* vf = VFileFromConstMemory(buffer->buffer, buffer->size);
int ret = mCoreLoadStateNamed(core, vf, flags); int ret = mCoreLoadStateNamed(core, vf, flags);
@ -380,6 +390,15 @@ static int32_t _mScriptCoreLoadState(struct mCore* core, struct mScriptString* b
return ret; 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) { static void _mScriptCoreTakeScreenshot(struct mCore* core, const char* filename) {
if (filename) { if (filename) {
struct VFile* vf = VFileOpen(filename, O_WRONLY | O_CREAT | O_TRUNC); 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 // Info functions
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, S32, platform, 0); mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, S32, platform, 0);
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, U32, frameCounter, 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_CD_METHOD(mCore, S32, frequency, 0);
mSCRIPT_DECLARE_STRUCT_C_METHOD(mCore, WSTR, getGameTitle, _mScriptCoreGetGameTitle, 0); mSCRIPT_DECLARE_STRUCT_C_METHOD(mCore, WSTR, getGameTitle, _mScriptCoreGetGameTitle, 0);
mSCRIPT_DECLARE_STRUCT_C_METHOD(mCore, WSTR, getGameCode, _mScriptCoreGetGameCode, 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); mSCRIPT_DECLARE_STRUCT_C_METHOD_WITH_DEFAULTS(mCore, WSTR, checksum, _mScriptCoreChecksum, 1, S32, type);
// Run functions // 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); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mCore, writeRegister, _mScriptCoreWriteRegister, 2, CHARP, regName, S32, value);
// Savestate functions // 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, 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, BOOL, saveStateFile, _mScriptCoreSaveStateFile, 2, CHARP, path, 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, 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 // Miscellaneous functions
mSCRIPT_DECLARE_STRUCT_VOID_METHOD_WITH_DEFAULTS(mCore, screenshot, _mScriptCoreTakeScreenshot, 1, CHARP, filename); 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( mSCRIPT_DEFINE_CLASS_DOCSTRING(
"An instance of an emulator core." "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_DOCSTRING("Get which platform is being emulated. See C.PLATFORM for possible values")
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, platform) mSCRIPT_DEFINE_STRUCT_METHOD(mCore, platform)
mSCRIPT_DEFINE_DOCSTRING("Get the number of the current frame") 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_STRUCT_METHOD(mCore, frameCycles)
mSCRIPT_DEFINE_DOCSTRING("Get the number of cycles per second") mSCRIPT_DEFINE_DOCSTRING("Get the number of cycles per second")
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, frequency) 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_DOCSTRING("Get the checksum of the loaded ROM")
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, checksum) mSCRIPT_DEFINE_STRUCT_METHOD(mCore, checksum)
@ -504,10 +540,14 @@ mSCRIPT_DEFINE_STRUCT(mCore)
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateSlot) 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_DOCSTRING("Save state and return as a buffer. See C.SAVESTATE for possible values for `flags`")
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateBuffer) 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_DOCSTRING("Load state from the slot number. See C.SAVESTATE for possible values for `flags`")
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateSlot) 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_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_DOCSTRING("Save a screenshot")
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, screenshot) mSCRIPT_DEFINE_STRUCT_METHOD(mCore, screenshot)
@ -522,16 +562,26 @@ mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, saveStateSlot)
mSCRIPT_S32(SAVESTATE_ALL) mSCRIPT_S32(SAVESTATE_ALL)
mSCRIPT_DEFINE_DEFAULTS_END; 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_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateSlot)
mSCRIPT_NO_DEFAULT, mSCRIPT_NO_DEFAULT,
mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA) mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA)
mSCRIPT_DEFINE_DEFAULTS_END; mSCRIPT_DEFINE_DEFAULTS_END;
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, saveStateBuffer) mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateBuffer)
mSCRIPT_S32(SAVESTATE_ALL) mSCRIPT_NO_DEFAULT,
mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA)
mSCRIPT_DEFINE_DEFAULTS_END; mSCRIPT_DEFINE_DEFAULTS_END;
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateBuffer) mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateFile)
mSCRIPT_NO_DEFAULT, mSCRIPT_NO_DEFAULT,
mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA) mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA)
mSCRIPT_DEFINE_DEFAULTS_END; mSCRIPT_DEFINE_DEFAULTS_END;

View File

@ -253,10 +253,13 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
core->setSync(core, &threadContext->impl->sync); core->setSync(core, &threadContext->impl->sync);
struct mLogFilter filter; struct mLogFilter filter;
if (!threadContext->logger.d.filter) { struct mLogger* logger = &threadContext->logger.d;
threadContext->logger.d.filter = &filter; if (threadContext->logger.logger) {
mLogFilterInit(threadContext->logger.d.filter); logger->filter = threadContext->logger.logger->filter;
mLogFilterLoad(threadContext->logger.d.filter, &core->config); } else {
logger->filter = &filter;
mLogFilterInit(logger->filter);
mLogFilterLoad(logger->filter, &core->config);
} }
#ifdef ENABLE_SCRIPTING #ifdef ENABLE_SCRIPTING
@ -431,10 +434,10 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
#endif #endif
core->clearCoreCallbacks(core); core->clearCoreCallbacks(core);
if (threadContext->logger.d.filter == &filter) { if (logger->filter == &filter) {
mLogFilterDeinit(&filter); mLogFilterDeinit(&filter);
} }
threadContext->logger.d.filter = NULL; logger->filter = NULL;
return 0; return 0;
} }
@ -444,10 +447,8 @@ bool mCoreThreadStart(struct mCoreThread* threadContext) {
threadContext->impl->state = mTHREAD_INITIALIZED; threadContext->impl->state = mTHREAD_INITIALIZED;
threadContext->impl->requested = 0; threadContext->impl->requested = 0;
threadContext->logger.p = threadContext; threadContext->logger.p = threadContext;
if (!threadContext->logger.d.log) { threadContext->logger.d.log = _mCoreLog;
threadContext->logger.d.log = _mCoreLog; threadContext->logger.d.filter = NULL;
threadContext->logger.d.filter = NULL;
}
if (!threadContext->impl->sync.fpsTarget) { if (!threadContext->impl->sync.fpsTarget) {
threadContext->impl->sync.fpsTarget = _defaultFPSTarget; 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) { static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
UNUSED(logger); struct mThreadLogger* threadLogger = (struct mThreadLogger*) logger;
UNUSED(level); if (level == mLOG_FATAL) {
printf("%s: ", mLogCategoryName(category)); mCoreThreadMarkCrashed(threadLogger->p);
vprintf(format, args); }
printf("\n"); if (!threadLogger->p->logger.logger) {
struct mCoreThread* thread = mCoreThreadGet(); printf("%s: ", mLogCategoryName(category));
if (thread && level == mLOG_FATAL) { vprintf(format, args);
mCoreThreadMarkCrashed(thread); printf("\n");
} else {
logger = threadLogger->p->logger.logger;
logger->log(logger, category, level, format, args);
} }
} }
#else #else

View File

@ -588,7 +588,7 @@ static struct ParseTree* _parseTree(const char** string) {
} }
struct ParseTree* tree = NULL; struct ParseTree* tree = NULL;
if (!error) { if (!error) {
tree = malloc(sizeof(*tree)); tree = parseTreeCreate();
parseLexedExpression(tree, &lv); parseLexedExpression(tree, &lv);
} }
lexFree(&lv); lexFree(&lv);
@ -796,17 +796,16 @@ struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* stri
dvTemp.type = CLIDV_ERROR_TYPE; dvTemp.type = CLIDV_ERROR_TYPE;
} }
struct ParseTree tree; struct ParseTree* tree = parseTreeCreate();
parseLexedExpression(&tree, &lv); if (!parseLexedExpression(tree, &lv)) {
if (tree.token.type == TOKEN_ERROR_TYPE) {
dvTemp.type = CLIDV_ERROR_TYPE; dvTemp.type = CLIDV_ERROR_TYPE;
} else { } else {
if (!mDebuggerEvaluateParseTree(&debugger->d, &tree, &dvTemp.intValue, &dvTemp.segmentValue)) { if (!mDebuggerEvaluateParseTree(&debugger->d, tree, &dvTemp.intValue, &dvTemp.segmentValue)) {
dvTemp.type = CLIDV_ERROR_TYPE; dvTemp.type = CLIDV_ERROR_TYPE;
} }
} }
parseFree(&tree); parseFree(tree);
lexFree(&lv); lexFree(&lv);
LexVectorDeinit(&lv); LexVectorDeinit(&lv);

View File

@ -495,7 +495,7 @@ static const int _operatorPrecedence[] = {
[OP_DEREFERENCE] = 2, [OP_DEREFERENCE] = 2,
}; };
static struct ParseTree* _parseTreeCreate(void) { struct ParseTree* parseTreeCreate(void) {
struct ParseTree* tree = malloc(sizeof(struct ParseTree)); struct ParseTree* tree = malloc(sizeof(struct ParseTree));
tree->token.type = TOKEN_ERROR_TYPE; tree->token.type = TOKEN_ERROR_TYPE;
tree->p = NULL; tree->p = NULL;
@ -529,12 +529,12 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, int
} }
break; break;
case TOKEN_SEGMENT_TYPE: case TOKEN_SEGMENT_TYPE:
tree->lhs = _parseTreeCreate(); tree->lhs = parseTreeCreate();
tree->lhs->token.type = TOKEN_UINT_TYPE; tree->lhs->token.type = TOKEN_UINT_TYPE;
tree->lhs->token.uintValue = token->uintValue; tree->lhs->token.uintValue = token->uintValue;
tree->lhs->p = tree; tree->lhs->p = tree;
tree->lhs->precedence = precedence; tree->lhs->precedence = precedence;
tree->rhs = _parseTreeCreate(); tree->rhs = parseTreeCreate();
tree->rhs->p = tree; tree->rhs->p = tree;
tree->rhs->precedence = precedence; tree->rhs->precedence = precedence;
tree->token.type = TOKEN_SEGMENT_TYPE; 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]; newPrecedence = _operatorPrecedence[token->operatorValue];
if (newPrecedence < precedence) { if (newPrecedence < precedence) {
newTree = _parseTreeCreate(); newTree = parseTreeCreate();
memcpy(newTree, tree, sizeof(*tree)); memcpy(newTree, tree, sizeof(*tree));
if (newTree->lhs) { if (newTree->lhs) {
newTree->lhs->p = newTree; newTree->lhs->p = newTree;
@ -582,7 +582,7 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, int
} }
newTree->p = tree; newTree->p = tree;
tree->lhs = newTree; tree->lhs = newTree;
tree->rhs = _parseTreeCreate(); tree->rhs = parseTreeCreate();
tree->rhs->p = tree; tree->rhs->p = tree;
tree->rhs->precedence = newPrecedence; tree->rhs->precedence = newPrecedence;
precedence = newPrecedence; precedence = newPrecedence;
@ -617,9 +617,9 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, int
return i; return i;
} }
void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv) { bool parseLexedExpression(struct ParseTree* tree, struct LexVector* lv) {
if (!tree) { if (!tree) {
return; return false;
} }
tree->token.type = TOKEN_ERROR_TYPE; tree->token.type = TOKEN_ERROR_TYPE;
@ -636,6 +636,7 @@ void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv) {
} }
tree->token.type = TOKEN_ERROR_TYPE; tree->token.type = TOKEN_ERROR_TYPE;
} }
return tree->token.type != TOKEN_ERROR_TYPE;
} }
void lexFree(struct LexVector* lv) { void lexFree(struct LexVector* lv) {
@ -782,7 +783,8 @@ bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tr
struct IntList stack; struct IntList stack;
int nextBranch; int nextBranch;
bool ok = true; bool ok = true;
int32_t tmpVal, tmpSegment; int32_t tmpVal = 0;
int32_t tmpSegment = -1;
IntListInit(&stack, 0); IntListInit(&stack, 0);
while (ok) { while (ok) {

View File

@ -260,8 +260,16 @@ bool NoIntroDBLoadClrMamePro(struct NoIntroDB* db, struct VFile* vf) {
free((void*) buffer.name); free((void*) buffer.name);
free((void*) buffer.romName); 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(gamedbTable);
sqlite3_finalize(gamedbDrop); sqlite3_finalize(gamedbDrop);

View File

@ -92,7 +92,7 @@ bool mUpdaterInit(struct mUpdaterContext* context, const char* manifest) {
ConfigurationInit(&context->manifest); ConfigurationInit(&context->manifest);
struct VFile* vf = VFileFromConstMemory(manifest, strlen(manifest) + 1); struct VFile* vf = VFileFromConstMemory(manifest, strlen(manifest) + 1);
bool success = vf && ConfigurationReadVFile(&context->manifest, vf); bool success = ConfigurationReadVFile(&context->manifest, vf);
vf->close(vf); vf->close(vf);
if (!success) { if (!success) {
ConfigurationDeinit(&context->manifest); ConfigurationDeinit(&context->manifest);

View File

@ -485,8 +485,16 @@ static void _GBCoreUnloadROM(struct mCore* core) {
GBUnloadROM(core->board); 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) { 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) { switch (type) {
case mCHECKSUM_CRC32: case mCHECKSUM_CRC32:
memcpy(data, &gb->romCrc32, sizeof(gb->romCrc32)); 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; uint16_t* value16 = out;
uint8_t* value8 = out; uint8_t* value8 = out;
if (strcmp(name, "b") == 0) { if (strcasecmp(name, "b") == 0) {
*value8 = cpu->b; *value8 = cpu->b;
return true; return true;
} }
if (strcmp(name, "c") == 0) { if (strcasecmp(name, "c") == 0) {
*value8 = cpu->c; *value8 = cpu->c;
return true; return true;
} }
if (strcmp(name, "d") == 0) { if (strcasecmp(name, "d") == 0) {
*value8 = cpu->d; *value8 = cpu->d;
return true; return true;
} }
if (strcmp(name, "e") == 0) { if (strcasecmp(name, "e") == 0) {
*value8 = cpu->e; *value8 = cpu->e;
return true; return true;
} }
if (strcmp(name, "a") == 0) { if (strcasecmp(name, "a") == 0) {
*value8 = cpu->a; *value8 = cpu->a;
return true; return true;
} }
if (strcmp(name, "f") == 0) { if (strcasecmp(name, "f") == 0) {
*value8 = cpu->f.packed; *value8 = cpu->f.packed;
return true; return true;
} }
if (strcmp(name, "h") == 0) { if (strcasecmp(name, "h") == 0) {
*value8 = cpu->h; *value8 = cpu->h;
return true; return true;
} }
if (strcmp(name, "l") == 0) { if (strcasecmp(name, "l") == 0) {
*value8 = cpu->l; *value8 = cpu->l;
return true; return true;
} }
if (strcmp(name, "bc") == 0) { if (strcasecmp(name, "bc") == 0) {
*value16 = cpu->bc; *value16 = cpu->bc;
return true; return true;
} }
if (strcmp(name, "de") == 0) { if (strcasecmp(name, "de") == 0) {
*value16 = cpu->de; *value16 = cpu->de;
return true; return true;
} }
if (strcmp(name, "hl") == 0) { if (strcasecmp(name, "hl") == 0) {
*value16 = cpu->hl; *value16 = cpu->hl;
return true; return true;
} }
if (strcmp(name, "af") == 0) { if (strcasecmp(name, "af") == 0) {
*value16 = cpu->af; *value16 = cpu->af;
return true; return true;
} }
if (strcmp(name, "pc") == 0) { if (strcasecmp(name, "pc") == 0) {
*value16 = cpu->pc; *value16 = cpu->pc;
return true; return true;
} }
if (strcmp(name, "sp") == 0) { if (strcasecmp(name, "sp") == 0) {
*value16 = cpu->sp; *value16 = cpu->sp;
return true; return true;
} }
@ -1260,6 +1268,7 @@ struct mCore* GBCoreCreate(void) {
core->loadTemporarySave = _GBCoreLoadTemporarySave; core->loadTemporarySave = _GBCoreLoadTemporarySave;
core->loadPatch = _GBCoreLoadPatch; core->loadPatch = _GBCoreLoadPatch;
core->unloadROM = _GBCoreUnloadROM; core->unloadROM = _GBCoreUnloadROM;
core->romSize = _GBCoreROMSize;
core->checksum = _GBCoreChecksum; core->checksum = _GBCoreChecksum;
core->reset = _GBCoreReset; core->reset = _GBCoreReset;
core->runFrame = _GBCoreRunFrame; core->runFrame = _GBCoreRunFrame;

View File

@ -189,6 +189,9 @@ bool GBLoadROM(struct GB* gb, struct VFile* vf) {
if (gb->cpu) { if (gb->cpu) {
struct SM83Core* cpu = gb->cpu; struct SM83Core* cpu = gb->cpu;
if (!gb->memory.romBase) {
GBMBCSwitchBank0(gb, 0);
}
cpu->memory.setActiveRegion(cpu, cpu->pc); cpu->memory.setActiveRegion(cpu, cpu->pc);
} }

View File

@ -454,6 +454,7 @@ static void _GBACoreSetVideoGLTex(struct mCore* core, unsigned texid) {
#ifdef BUILD_GLES3 #ifdef BUILD_GLES3
struct GBACore* gbacore = (struct GBACore*) core; struct GBACore* gbacore = (struct GBACore*) core;
gbacore->glRenderer.outputTex = texid; gbacore->glRenderer.outputTex = texid;
gbacore->glRenderer.outputTexDirty = true;
#else #else
UNUSED(core); UNUSED(core);
UNUSED(texid); UNUSED(texid);
@ -579,8 +580,16 @@ static void _GBACoreUnloadROM(struct mCore* core) {
GBAUnloadROM(core->board); 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) { 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) { switch (type) {
case mCHECKSUM_CRC32: case mCHECKSUM_CRC32:
memcpy(data, &gba->romCrc32, sizeof(gba->romCrc32)); memcpy(data, &gba->romCrc32, sizeof(gba->romCrc32));
@ -1384,6 +1393,7 @@ struct mCore* GBACoreCreate(void) {
core->loadTemporarySave = _GBACoreLoadTemporarySave; core->loadTemporarySave = _GBACoreLoadTemporarySave;
core->loadPatch = _GBACoreLoadPatch; core->loadPatch = _GBACoreLoadPatch;
core->unloadROM = _GBACoreUnloadROM; core->unloadROM = _GBACoreUnloadROM;
core->romSize = _GBACoreROMSize;
core->checksum = _GBACoreChecksum; core->checksum = _GBACoreChecksum;
core->reset = _GBACoreReset; core->reset = _GBACoreReset;
core->runFrame = _GBACoreRunFrame; core->runFrame = _GBACoreRunFrame;

View File

@ -257,7 +257,7 @@ void GBAReset(struct ARMCore* cpu) {
memset(gba->debugString, 0, sizeof(gba->debugString)); 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; char ident;
gba->romVf->seek(gba->romVf, 0xAC, SEEK_SET); gba->romVf->seek(gba->romVf, 0xAC, SEEK_SET);
gba->romVf->read(gba->romVf, &ident, 1); gba->romVf->read(gba->romVf, &ident, 1);
@ -399,14 +399,15 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
} }
GBAUnloadROM(gba); GBAUnloadROM(gba);
gba->romVf = vf; gba->romVf = vf;
gba->isPristine = true;
gba->pristineRomSize = vf->size(vf); gba->pristineRomSize = vf->size(vf);
vf->seek(vf, 0, SEEK_SET); vf->seek(vf, 0, SEEK_SET);
if (gba->pristineRomSize > SIZE_CART0) { if (gba->pristineRomSize > SIZE_CART0) {
gba->isPristine = false;
char ident; char ident;
vf->seek(vf, 0xAC, SEEK_SET); vf->seek(vf, 0xAC, SEEK_SET);
vf->read(vf, &ident, 1); vf->read(vf, &ident, 1);
if (ident == 'M') { if (ident == 'M') {
gba->isPristine = false;
gba->memory.romSize = 0x01000000; gba->memory.romSize = 0x01000000;
#ifdef FIXED_ROM_BUFFER #ifdef FIXED_ROM_BUFFER
gba->memory.rom = romBuffer; 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.rom = vf->map(vf, SIZE_CART0, MAP_READ);
gba->memory.romSize = SIZE_CART0; gba->memory.romSize = SIZE_CART0;
} }
gba->pristineRomSize = SIZE_CART0;
} else { } else {
gba->isPristine = true;
gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ); gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ);
gba->memory.romSize = gba->pristineRomSize; gba->memory.romSize = gba->pristineRomSize;
} }
@ -582,6 +583,10 @@ void GBADebug(struct GBA* gba, uint16_t flags) {
} }
bool GBAIsROM(struct VFile* vf) { bool GBAIsROM(struct VFile* vf) {
if (!vf) {
return false;
}
#ifdef USE_ELF #ifdef USE_ELF
struct ELF* elf = ELFOpen(vf); struct ELF* elf = ELFOpen(vf);
if (elf) { if (elf) {
@ -593,9 +598,6 @@ bool GBAIsROM(struct VFile* vf) {
return isGBA; return isGBA;
} }
#endif #endif
if (!vf) {
return false;
}
uint8_t signature[sizeof(GBA_ROM_MAGIC) + sizeof(GBA_ROM_MAGIC2)]; uint8_t signature[sizeof(GBA_ROM_MAGIC) + sizeof(GBA_ROM_MAGIC2)];
if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) { if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) {

View File

@ -779,6 +779,7 @@ static void _initFramebuffers(struct GBAVideoGLRenderer* glRenderer) {
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_OUTPUT]); glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_OUTPUT]);
_initFramebufferTexture(glRenderer->outputTex, GL_RGB, GL_COLOR_ATTACHMENT0, glRenderer->scale); _initFramebufferTexture(glRenderer->outputTex, GL_RGB, GL_COLOR_ATTACHMENT0, glRenderer->scale);
glRenderer->outputTexDirty = false;
int i; int i;
for (i = 0; i < 4; ++i) { for (i = 0; i < 4; ++i) {
@ -1684,6 +1685,10 @@ static void GBAVideoGLRendererWriteBLDCNT(struct GBAVideoGLRenderer* renderer, u
void _finalizeLayers(struct GBAVideoGLRenderer* renderer) { void _finalizeLayers(struct GBAVideoGLRenderer* renderer) {
const GLuint* uniforms = renderer->finalizeShader.uniforms; const GLuint* uniforms = renderer->finalizeShader.uniforms;
glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OUTPUT]); 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); 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); glScissor(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
if (GBARegisterDISPCNTIsForcedBlank(renderer->dispcnt)) { if (GBARegisterDISPCNTIsForcedBlank(renderer->dispcnt)) {

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>AboutScreen</class> <class>QGBA::AboutScreen</class>
<widget class="QWidget" name="AboutScreen"> <widget class="QWidget" name="QGBA::AboutScreen">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ApplicationUpdatePrompt</class> <class>QGBA::ApplicationUpdatePrompt</class>
<widget class="QDialog" name="ApplicationUpdatePrompt"> <widget class="QDialog" name="QGBA::ApplicationUpdatePrompt">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -58,7 +58,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>ApplicationUpdatePrompt</receiver> <receiver>QGBA::ApplicationUpdatePrompt</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ArchiveInspector</class> <class>QGBA::ArchiveInspector</class>
<widget class="QDialog" name="ArchiveInspector"> <widget class="QDialog" name="QGBA::ArchiveInspector">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -46,7 +46,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>ArchiveInspector</receiver> <receiver>QGBA::ArchiveInspector</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -62,7 +62,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>ArchiveInspector</receiver> <receiver>QGBA::ArchiveInspector</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -82,6 +82,9 @@ void AssetTile::setBoundary(int boundary, int set0, int set1) {
} }
void AssetTile::selectIndex(int index) { void AssetTile::selectIndex(int index) {
if (index > m_maxTile) {
return;
}
m_index = index; m_index = index;
const color_t* data; const color_t* data;
mTileCache* tileCache = m_tileCaches[index >= m_boundary]; 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.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'))); 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;
}

View File

@ -29,6 +29,7 @@ public slots:
void selectIndex(int); void selectIndex(int);
void setFlip(bool h, bool v); void setFlip(bool h, bool v);
void selectColor(int); void selectColor(int);
void setMaxTile(int);
protected: protected:
int customLocation(const QString& id = {}) override; int customLocation(const QString& id = {}) override;
@ -45,6 +46,7 @@ private:
int m_addressBase; int m_addressBase;
int m_boundary; int m_boundary;
int m_boundaryBase; int m_boundaryBase;
int m_maxTile;
bool m_flipH = false; bool m_flipH = false;
bool m_flipV = false; bool m_flipV = false;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>AssetTile</class> <class>QGBA::AssetTile</class>
<widget class="QGBA::AssetInfo" name="AssetTile"> <widget class="QGBA::AssetInfo" name="QGBA::AssetTile">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>BattleChipView</class> <class>QGBA::BattleChipView</class>
<widget class="QDialog" name="BattleChipView"> <widget class="QDialog" name="QGBA::BattleChipView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -238,7 +238,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>BattleChipView</receiver> <receiver>QGBA::BattleChipView</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -333,9 +333,9 @@ if(${QT}LinguistTools_FOUND)
file(GLOB TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/ts/${BINARY_NAME}-*.ts") file(GLOB TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/ts/${BINARY_NAME}-*.ts")
if(UPDATE_TRANSLATIONS) if(UPDATE_TRANSLATIONS)
if(TARGET Qt6::Core) 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() 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() endif()
list(REMOVE_ITEM TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/ts/${BINARY_NAME}-template.ts") list(REMOVE_ITEM TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/ts/${BINARY_NAME}-template.ts")
else() else()
@ -361,9 +361,14 @@ if(${QT}LinguistTools_FOUND)
endforeach() endforeach()
list(APPEND TRANSLATION_FILES ${QT_QM_FILES}) list(APPEND TRANSLATION_FILES ${QT_QM_FILES})
endif() 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" file(WRITE ${TRANSLATION_QRC} "<RCC>\n\t<qresource prefix=\"/translations/\">\n")
DEPENDS ${TRANSLATION_FILES}) 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) if(TARGET Qt6::Core)
qt_add_resources(TRANSLATION_RESOURCES ${TRANSLATION_QRC}) qt_add_resources(TRANSLATION_RESOURCES ${TRANSLATION_QRC})
else() else()

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>CheatsView</class> <class>QGBA::CheatsView</class>
<widget class="QWidget" name="CheatsView"> <widget class="QWidget" name="QGBA::CheatsView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -144,19 +144,19 @@ CoreController::CoreController(mCore* core, QObject* parent)
QMetaObject::invokeMethod(controller, "unpaused"); QMetaObject::invokeMethod(controller, "unpaused");
}; };
m_threadContext.logger.d.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { m_logger.self = this;
mThreadLogger* logContext = reinterpret_cast<mThreadLogger*>(logger); m_logger.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
mCoreThread* context = logContext->p; CoreLogger* logContext = static_cast<CoreLogger*>(logger);
static const char* savestateMessage = "State %i saved"; static const char* savestateMessage = "State %i saved";
static const char* loadstateMessage = "State %i loaded"; static const char* loadstateMessage = "State %i loaded";
static const char* savestateFailedMessage = "State %i failed to load"; static const char* savestateFailedMessage = "State %i failed to load";
static int biosCat = -1; static int biosCat = -1;
static int statusCat = -1; static int statusCat = -1;
if (!context) { if (!logContext) {
return; return;
} }
CoreController* controller = static_cast<CoreController*>(context->userData); CoreController* controller = logContext->self;
QString message; QString message;
if (biosCat < 0) { if (biosCat < 0) {
biosCat = mLogCategoryById("gba.bios"); biosCat = mLogCategoryById("gba.bios");
@ -201,10 +201,10 @@ CoreController::CoreController(mCore* core, QObject* parent)
message = QString::vasprintf(format, args); message = QString::vasprintf(format, args);
QMetaObject::invokeMethod(controller, "logPosted", Q_ARG(int, level), Q_ARG(int, category), Q_ARG(const QString&, message)); QMetaObject::invokeMethod(controller, "logPosted", Q_ARG(int, level), Q_ARG(int, category), Q_ARG(const QString&, message));
if (level == mLOG_FATAL) { if (level == mLOG_FATAL) {
mCoreThreadMarkCrashed(controller->thread());
QMetaObject::invokeMethod(controller, "crashed", Q_ARG(const QString&, message)); QMetaObject::invokeMethod(controller, "crashed", Q_ARG(const QString&, message));
} }
}; };
m_threadContext.logger.logger = &m_logger;
} }
CoreController::~CoreController() { CoreController::~CoreController() {
@ -429,7 +429,7 @@ void CoreController::setInputController(InputController* inputController) {
void CoreController::setLogger(LogController* logger) { void CoreController::setLogger(LogController* logger) {
disconnect(m_log); disconnect(m_log);
m_log = logger; m_log = logger;
m_threadContext.logger.d.filter = logger->filter(); m_logger.filter = logger->filter();
connect(this, &CoreController::logPosted, m_log, &LogController::postLog); connect(this, &CoreController::logPosted, m_log, &LogController::postLog);
} }
@ -1218,24 +1218,21 @@ void CoreController::updateFastForward() {
if (m_fastForwardMute >= 0) { if (m_fastForwardMute >= 0) {
m_threadContext.core->opts.mute = m_fastForwardMute || m_mute; m_threadContext.core->opts.mute = m_fastForwardMute || m_mute;
} }
setSync(false);
// If we aren't holding the fast forward button // If we aren't holding the fast forward button
// then use the non "(held)" ratio // then use the non "(held)" ratio
if(!m_fastForward) { if(!m_fastForward) {
if (m_fastForwardRatio > 0) { if (m_fastForwardRatio > 0) {
m_threadContext.impl->sync.fpsTarget = m_fpsTarget * m_fastForwardRatio; m_threadContext.impl->sync.fpsTarget = m_fpsTarget * m_fastForwardRatio;
setSync(true); m_threadContext.impl->sync.audioWait = true;
} else {
setSync(false);
} }
} else { } else {
// If we are holding the fast forward button, // If we are holding the fast forward button,
// then use the held ratio // then use the held ratio
if (m_fastForwardHeldRatio > 0) { if (m_fastForwardHeldRatio > 0) {
m_threadContext.impl->sync.fpsTarget = m_fpsTarget * m_fastForwardHeldRatio; m_threadContext.impl->sync.fpsTarget = m_fpsTarget * m_fastForwardHeldRatio;
setSync(true); m_threadContext.impl->sync.audioWait = true;
} else {
setSync(false);
} }
} }
} else { } else {
@ -1338,3 +1335,7 @@ void CoreController::Interrupter::resume(CoreController* controller) {
mCoreThreadContinue(controller->thread()); mCoreThreadContinue(controller->thread());
} }
bool CoreController::Interrupter::held() const {
return m_parent && m_parent->thread()->impl;
}

View File

@ -68,6 +68,8 @@ public:
void interrupt(std::shared_ptr<CoreController>); void interrupt(std::shared_ptr<CoreController>);
void resume(); void resume();
bool held() const;
private: private:
void interrupt(); void interrupt();
void resume(CoreController*); void resume(CoreController*);
@ -238,6 +240,9 @@ private:
void updateROMInfo(); void updateROMInfo();
mCoreThread m_threadContext{}; mCoreThread m_threadContext{};
struct CoreLogger : public mLogger {
CoreController* self;
} m_logger{};
bool m_patched = false; bool m_patched = false;
bool m_preload = false; bool m_preload = false;

View File

@ -62,13 +62,16 @@ CoreController* CoreManager::loadGame(const QString& path) {
VFile* vfOriginal = VDirFindFirst(archive, [](VFile* vf) { VFile* vfOriginal = VDirFindFirst(archive, [](VFile* vf) {
return mCoreIsCompatible(vf) != mPLATFORM_NONE; return mCoreIsCompatible(vf) != mPLATFORM_NONE;
}); });
ssize_t size; if (vfOriginal) {
if (vfOriginal && (size = vfOriginal->size(vfOriginal)) > 0) { ssize_t size = vfOriginal->size(vfOriginal);
void* mem = vfOriginal->map(vfOriginal, size, MAP_READ); if (size > 0) {
vf = VFileMemChunk(mem, size); void* mem = vfOriginal->map(vfOriginal, size, MAP_READ);
vfOriginal->unmap(vfOriginal, mem, size); vf = VFileMemChunk(mem, size);
vfOriginal->unmap(vfOriginal, mem, size);
}
vfOriginal->close(vfOriginal); vfOriginal->close(vfOriginal);
} }
archive->close(archive);
} }
QDir dir(info.dir()); QDir dir(info.dir());
if (!vf) { if (!vf) {

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>DebuggerConsole</class> <class>QGBA::DebuggerConsole</class>
<widget class="QWidget" name="DebuggerConsole"> <widget class="QWidget" name="QGBA::DebuggerConsole">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -288,7 +288,7 @@ void DisplayGL::stopDrawing() {
m_isDrawing = false; m_isDrawing = false;
m_hasStarted = false; m_hasStarted = false;
CoreController::Interrupter interrupter(m_context); CoreController::Interrupter interrupter(m_context);
QMetaObject::invokeMethod(m_painter.get(), "stop", Qt::BlockingQueuedConnection); m_painter->stop();
if (m_gl) { if (m_gl) {
hide(); hide();
} }
@ -460,8 +460,7 @@ void PainterGL::create() {
m_paintDev = std::make_unique<QOpenGLPaintDevice>(); m_paintDev = std::make_unique<QOpenGLPaintDevice>();
#if defined(BUILD_GLES2) || defined(BUILD_GLES3) #if defined(BUILD_GLES2) || defined(BUILD_GLES3)
auto version = m_format.version(); if (m_supportsShaders) {
if (version >= qMakePair(2, 0)) {
gl2Backend = static_cast<mGLES2Context*>(malloc(sizeof(mGLES2Context))); gl2Backend = static_cast<mGLES2Context*>(malloc(sizeof(mGLES2Context)));
mGLES2ContextCreate(gl2Backend); mGLES2ContextCreate(gl2Backend);
m_backend = &gl2Backend->d; m_backend = &gl2Backend->d;
@ -629,6 +628,15 @@ void PainterGL::draw() {
if (!m_started || m_queue.isEmpty()) { if (!m_started || m_queue.isEmpty()) {
return; 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; mCoreSync* sync = &m_context->thread()->impl->sync;
if (!mCoreSyncWaitFrameStart(sync)) { if (!mCoreSyncWaitFrameStart(sync)) {
mCoreSyncWaitFrameEnd(sync); mCoreSyncWaitFrameEnd(sync);
@ -679,6 +687,11 @@ void PainterGL::forceDraw() {
} }
void PainterGL::stop() { void PainterGL::stop() {
m_started = false;
QMetaObject::invokeMethod(this, "doStop", Qt::BlockingQueuedConnection);
}
void PainterGL::doStop() {
m_drawTimer.stop(); m_drawTimer.stop();
m_active = false; m_active = false;
m_started = false; m_started = false;

View File

@ -135,6 +135,8 @@ public:
void setMessagePainter(MessagePainter*); void setMessagePainter(MessagePainter*);
void enqueue(const uint32_t* backing); void enqueue(const uint32_t* backing);
void stop();
bool supportsShaders() const { return m_supportsShaders; } bool supportsShaders() const { return m_supportsShaders; }
int glTex(); int glTex();
@ -148,7 +150,6 @@ public slots:
void forceDraw(); void forceDraw();
void draw(); void draw();
void start(); void start();
void stop();
void pause(); void pause();
void unpause(); void unpause();
void resize(const QSize& size); void resize(const QSize& size);
@ -167,6 +168,9 @@ public slots:
signals: signals:
void started(); void started();
private slots:
void doStop();
private: private:
void makeCurrent(); void makeCurrent();
void performDraw(); void performDraw();

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>DolphinConnector</class> <class>QGBA::DolphinConnector</class>
<widget class="QDialog" name="DolphinConnector"> <widget class="QDialog" name="QGBA::DolphinConnector">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -98,7 +98,7 @@
<connection> <connection>
<sender>close</sender> <sender>close</sender>
<signal>clicked()</signal> <signal>clicked()</signal>
<receiver>DolphinConnector</receiver> <receiver>QGBA::DolphinConnector</receiver>
<slot>close()</slot> <slot>close()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>FrameView</class> <class>QGBA::FrameView</class>
<widget class="QWidget" name="FrameView"> <widget class="QWidget" name="QGBA::FrameView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>GIFView</class> <class>QGBA::GIFView</class>
<widget class="QWidget" name="GIFView"> <widget class="QWidget" name="QGBA::GIFView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -180,7 +180,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>GIFView</receiver> <receiver>QGBA::GIFView</receiver>
<slot>close()</slot> <slot>close()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -44,9 +44,7 @@ static const QList<GBMemoryBankControllerType> s_mbcList{
static QMap<GBModel, QString> s_gbModelNames; static QMap<GBModel, QString> s_gbModelNames;
static QMap<GBMemoryBankControllerType, QString> s_mbcNames; static QMap<GBMemoryBankControllerType, QString> s_mbcNames;
static QString tr(const char* str) { #define tr(STR) QCoreApplication::translate("QGBA::GameBoy", STR)
return QCoreApplication::translate("Game Boy", str);
}
QList<GBModel> GameBoy::modelList() { QList<GBModel> GameBoy::modelList() {
return s_gbModelList; return s_gbModelList;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>IOViewer</class> <class>QGBA::IOViewer</class>
<widget class="QWidget" name="IOViewer"> <widget class="QWidget" name="QGBA::IOViewer">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>LoadSaveState</class> <class>QGBA::LoadSaveState</class>
<widget class="QWidget" name="LoadSaveState"> <widget class="QWidget" name="QGBA::LoadSaveState">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>LogView</class> <class>QGBA::LogView</class>
<widget class="QWidget" name="LogView"> <widget class="QWidget" name="QGBA::LogView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -42,6 +42,7 @@ MapView::MapView(std::shared_ptr<CoreController> controller, QWidget* parent)
#ifdef M_CORE_GBA #ifdef M_CORE_GBA
case mPLATFORM_GBA: case mPLATFORM_GBA:
m_boundary = 2048; m_boundary = 2048;
m_ui.tile->setMaxTile(3096);
m_addressBase = BASE_VRAM; m_addressBase = BASE_VRAM;
m_addressWidth = 8; m_addressWidth = 8;
m_ui.bgInfo->addCustomProperty("priority", tr("Priority")); m_ui.bgInfo->addCustomProperty("priority", tr("Priority"));
@ -55,6 +56,7 @@ MapView::MapView(std::shared_ptr<CoreController> controller, QWidget* parent)
#ifdef M_CORE_GB #ifdef M_CORE_GB
case mPLATFORM_GB: case mPLATFORM_GB:
m_boundary = 1024; m_boundary = 1024;
m_ui.tile->setMaxTile(512);
m_addressBase = GB_BASE_VRAM; m_addressBase = GB_BASE_VRAM;
m_addressWidth = 4; m_addressWidth = 4;
m_ui.bgInfo->addCustomProperty("screenBase", tr("Map base")); m_ui.bgInfo->addCustomProperty("screenBase", tr("Map base"));

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>MapView</class> <class>QGBA::MapView</class>
<widget class="QWidget" name="MapView"> <widget class="QWidget" name="QGBA::MapView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>MemoryDump</class> <class>QGBA::MemoryDump</class>
<widget class="QDialog" name="MemoryDump"> <widget class="QDialog" name="QGBA::MemoryDump">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -126,7 +126,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>MemoryDump</receiver> <receiver>QGBA::MemoryDump</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -142,7 +142,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>MemoryDump</receiver> <receiver>QGBA::MemoryDump</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>MemorySearch</class> <class>QGBA::MemorySearch</class>
<widget class="QWidget" name="MemorySearch"> <widget class="QWidget" name="QGBA::MemorySearch">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -367,7 +367,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>MemorySearch</receiver> <receiver>QGBA::MemorySearch</receiver>
<slot>close()</slot> <slot>close()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>MemoryView</class> <class>QGBA::MemoryView</class>
<widget class="QWidget" name="MemoryView"> <widget class="QWidget" name="QGBA::MemoryView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -116,14 +116,16 @@ void ObjView::updateTilesGBA(bool force) {
if (GBAObjAttributesAIs256Color(obj->a)) { if (GBAObjAttributesAIs256Color(obj->a)) {
m_ui.palette->setText("256-color"); m_ui.palette->setText("256-color");
m_ui.tile->setBoundary(1024, 1, 3); m_ui.tile->setBoundary(1024, 1, 3);
m_ui.tile->setPalette(0);
m_boundary = 1024; m_boundary = 1024;
tileBase *= 2; tileBase *= 2;
m_ui.tile->setMaxTile(1536);
m_ui.tile->setPalette(0);
} else { } else {
m_ui.palette->setText(QString::number(newInfo.paletteId)); m_ui.palette->setText(QString::number(newInfo.paletteId));
m_ui.tile->setBoundary(2048, 0, 2); m_ui.tile->setBoundary(2048, 0, 2);
m_ui.tile->setPalette(newInfo.paletteId);
m_boundary = 2048; m_boundary = 2048;
m_ui.tile->setMaxTile(3072);
m_ui.tile->setPalette(newInfo.paletteId);
} }
if (newInfo != m_objInfo) { if (newInfo != m_objInfo) {
force = true; force = true;
@ -225,6 +227,7 @@ void ObjView::updateTilesGB(bool force) {
m_objInfo = newInfo; m_objInfo = newInfo;
m_tileOffset = tile; m_tileOffset = tile;
m_boundary = 1024; m_boundary = 1024;
m_ui.tile->setMaxTile(512);
int i = 0; int i = 0;
m_ui.tile->setPalette(newInfo.paletteId); m_ui.tile->setPalette(newInfo.paletteId);

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ObjView</class> <class>QGBA::ObjView</class>
<widget class="QWidget" name="ObjView"> <widget class="QWidget" name="QGBA::ObjView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>OverrideView</class> <class>QGBA::OverrideView</class>
<widget class="QWidget" name="OverrideView"> <widget class="QWidget" name="QGBA::OverrideView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>PaletteView</class> <class>QGBA::PaletteView</class>
<widget class="QWidget" name="PaletteView"> <widget class="QWidget" name="QGBA::PaletteView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>PlacementControl</class> <class>QGBA::PlacementControl</class>
<widget class="QDialog" name="PlacementControl"> <widget class="QDialog" name="QGBA::PlacementControl">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>PrinterView</class> <class>QGBA::PrinterView</class>
<widget class="QWidget" name="PrinterView"> <widget class="QWidget" name="QGBA::PrinterView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -250,7 +250,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>PrinterView</receiver> <receiver>QGBA::PrinterView</receiver>
<slot>close()</slot> <slot>close()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -9,12 +9,6 @@
#include "CoreController.h" #include "CoreController.h"
#include <mgba/core/core.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 #ifdef USE_SQLITE3
#include "feature/sqlite3/no-intro.h" #include "feature/sqlite3/no-intro.h"
#endif #endif
@ -46,25 +40,8 @@ ROMInfo::ROMInfo(std::shared_ptr<CoreController> controller, QWidget* parent)
core->checksum(core, &crc32, mCHECKSUM_CRC32); core->checksum(core, &crc32, mCHECKSUM_CRC32);
switch (controller->thread()->core->platform(controller->thread()->core)) { m_ui.size->setText(QString::number(core->romSize(core)) + tr(" bytes"));
#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;
}
if (crc32) { if (crc32) {
m_ui.crc->setText(QString::number(crc32, 16)); m_ui.crc->setText(QString::number(crc32, 16));
#ifdef USE_SQLITE3 #ifdef USE_SQLITE3

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ROMInfo</class> <class>QGBA::ROMInfo</class>
<widget class="QDialog" name="ROMInfo"> <widget class="QDialog" name="QGBA::ROMInfo">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ReportView</class> <class>QGBA::ReportView</class>
<widget class="QDialog" name="ReportView"> <widget class="QDialog" name="QGBA::ReportView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -163,7 +163,7 @@
<connection> <connection>
<sender>openList</sender> <sender>openList</sender>
<signal>clicked()</signal> <signal>clicked()</signal>
<receiver>ReportView</receiver> <receiver>QGBA::ReportView</receiver>
<slot>openBugReportPage()</slot> <slot>openBugReportPage()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -179,7 +179,7 @@
<connection> <connection>
<sender>generate</sender> <sender>generate</sender>
<signal>clicked()</signal> <signal>clicked()</signal>
<receiver>ReportView</receiver> <receiver>QGBA::ReportView</receiver>
<slot>generateReport()</slot> <slot>generateReport()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -195,7 +195,7 @@
<connection> <connection>
<sender>save</sender> <sender>save</sender>
<signal>clicked()</signal> <signal>clicked()</signal>
<receiver>ReportView</receiver> <receiver>QGBA::ReportView</receiver>
<slot>save()</slot> <slot>save()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -447,14 +447,14 @@ SaveConverter::AnnotatedSave::operator QString() const {
QString typeFormat("%1"); QString typeFormat("%1");
QString endianStr; QString endianStr;
QString saveType; QString saveType;
QString format = QCoreApplication::translate("SaveConverter", "%1 %2 save game"); QString format = QCoreApplication::translate("QGBA::SaveConverter", "%1 %2 save game");
switch (endianness) { switch (endianness) {
case Endian::LITTLE: case Endian::LITTLE:
endianStr = QCoreApplication::translate("SaveConverter", "little endian"); endianStr = QCoreApplication::translate("QGBA::SaveConverter", "little endian");
break; break;
case Endian::BIG: case Endian::BIG:
endianStr = QCoreApplication::translate("SaveConverter", "big endian"); endianStr = QCoreApplication::translate("QGBA::SaveConverter", "big endian");
break; break;
default: default:
break; break;
@ -465,15 +465,15 @@ SaveConverter::AnnotatedSave::operator QString() const {
case mPLATFORM_GBA: case mPLATFORM_GBA:
switch (gba.type) { switch (gba.type) {
case SAVEDATA_SRAM: case SAVEDATA_SRAM:
typeFormat = QCoreApplication::translate("SaveConverter", "SRAM"); typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "SRAM");
break; break;
case SAVEDATA_FLASH512: case SAVEDATA_FLASH512:
case SAVEDATA_FLASH1M: case SAVEDATA_FLASH1M:
typeFormat = QCoreApplication::translate("SaveConverter", "%1 flash"); typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 flash");
break; break;
case SAVEDATA_EEPROM: case SAVEDATA_EEPROM:
case SAVEDATA_EEPROM512: case SAVEDATA_EEPROM512:
typeFormat = QCoreApplication::translate("SaveConverter", "%1 EEPROM"); typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 EEPROM");
break; break;
default: default:
break; break;
@ -485,29 +485,29 @@ SaveConverter::AnnotatedSave::operator QString() const {
switch (gb.type) { switch (gb.type) {
case GB_MBC_AUTODETECT: case GB_MBC_AUTODETECT:
if (size & 0xFF) { if (size & 0xFF) {
typeFormat = QCoreApplication::translate("SaveConverter", "%1 SRAM + RTC"); typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 SRAM + RTC");
} else { } else {
typeFormat = QCoreApplication::translate("SaveConverter", "%1 SRAM"); typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 SRAM");
} }
break; break;
case GB_MBC2: case GB_MBC2:
if (size == 0x100) { if (size == 0x100) {
typeFormat = QCoreApplication::translate("SaveConverter", "packed MBC2"); typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "packed MBC2");
} else { } else {
typeFormat = QCoreApplication::translate("SaveConverter", "unpacked MBC2"); typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "unpacked MBC2");
} }
break; break;
case GB_MBC6: case GB_MBC6:
if (size == GB_SIZE_MBC6_FLASH) { 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) { } 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 { } else {
typeFormat = QCoreApplication::translate("SaveConverter", "MBC6 SRAM"); typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "MBC6 SRAM");
} }
break; break;
case GB_TAMA5: case GB_TAMA5:
typeFormat = QCoreApplication::translate("SaveConverter", "TAMA5"); typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "TAMA5");
break; break;
default: default:
break; break;
@ -519,17 +519,17 @@ SaveConverter::AnnotatedSave::operator QString() const {
} }
saveType = typeFormat.arg(sizeStr); saveType = typeFormat.arg(sizeStr);
if (!endianStr.isEmpty()) { 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) { switch (container) {
case Container::SAVESTATE: 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; break;
case Container::SHARKPORT: case Container::SHARKPORT:
format = QCoreApplication::translate("SaveConverter", "%1 SharkPort %2 save game"); format = QCoreApplication::translate("QGBA::SaveConverter", "%1 SharkPort %2 save game");
break; break;
case Container::GSV: 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; break;
case Container::NONE: case Container::NONE:
break; break;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>SaveConverter</class> <class>QGBA::SaveConverter</class>
<widget class="QDialog" name="SaveConverter"> <widget class="QDialog" name="QGBA::SaveConverter">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -91,7 +91,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>SaveConverter</receiver> <receiver>QGBA::SaveConverter</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -107,7 +107,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>SaveConverter</receiver> <receiver>QGBA::SaveConverter</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>SensorView</class> <class>QGBA::SensorView</class>
<widget class="QWidget" name="SensorView"> <widget class="QWidget" name="QGBA::SensorView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -35,16 +35,17 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
m_ui.setupUi(this); m_ui.setupUi(this);
m_pageIndex[Page::AV] = 0; m_pageIndex[Page::AV] = 0;
m_pageIndex[Page::INTERFACE] = 1; m_pageIndex[Page::GAMEPLAY] = 1;
m_pageIndex[Page::UPDATE] = 2; m_pageIndex[Page::INTERFACE] = 2;
m_pageIndex[Page::EMULATION] = 3; m_pageIndex[Page::UPDATE] = 3;
m_pageIndex[Page::ENHANCEMENTS] = 4; m_pageIndex[Page::EMULATION] = 4;
m_pageIndex[Page::BIOS] = 5; m_pageIndex[Page::ENHANCEMENTS] = 5;
m_pageIndex[Page::PATHS] = 6; m_pageIndex[Page::BIOS] = 6;
m_pageIndex[Page::LOGGING] = 7; m_pageIndex[Page::PATHS] = 7;
m_pageIndex[Page::LOGGING] = 8;
#ifdef M_CORE_GB #ifdef M_CORE_GB
m_pageIndex[Page::GB] = 8; m_pageIndex[Page::GB] = 9;
for (auto model : GameBoy::modelList()) { for (auto model : GameBoy::modelList()) {
m_ui.gbModel->addItem(GameBoy::modelName(model), model); m_ui.gbModel->addItem(GameBoy::modelName(model), model);

View File

@ -35,6 +35,7 @@ public:
enum class Page { enum class Page {
AV, AV,
INTERFACE, INTERFACE,
GAMEPLAY,
UPDATE, UPDATE,
EMULATION, EMULATION,
ENHANCEMENTS, ENHANCEMENTS,

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ShaderSelector</class> <class>QGBA::ShaderSelector</class>
<widget class="QDialog" name="ShaderSelector"> <widget class="QDialog" name="QGBA::ShaderSelector">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ShortcutView</class> <class>QGBA::ShortcutView</class>
<widget class="QWidget" name="ShortcutView"> <widget class="QWidget" name="QGBA::ShortcutView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -51,6 +51,7 @@ TileView::TileView(std::shared_ptr<CoreController> controller, QWidget* parent)
#ifdef M_CORE_GBA #ifdef M_CORE_GBA
case mPLATFORM_GBA: case mPLATFORM_GBA:
m_ui.tile->setBoundary(2048, 0, 2); m_ui.tile->setBoundary(2048, 0, 2);
m_ui.tile->setMaxTile(3096);
break; break;
#endif #endif
#ifdef M_CORE_GB #ifdef M_CORE_GB
@ -60,6 +61,7 @@ TileView::TileView(std::shared_ptr<CoreController> controller, QWidget* parent)
m_ui.tilesBoth->setEnabled(false); m_ui.tilesBoth->setEnabled(false);
m_ui.palette256->setEnabled(false); m_ui.palette256->setEnabled(false);
m_ui.tile->setBoundary(1024, 0, 0); m_ui.tile->setBoundary(1024, 0, 0);
m_ui.tile->setMaxTile(512);
break; break;
#endif #endif
default: default:
@ -74,6 +76,7 @@ TileView::TileView(std::shared_ptr<CoreController> controller, QWidget* parent)
#ifdef M_CORE_GBA #ifdef M_CORE_GBA
case mPLATFORM_GBA: case mPLATFORM_GBA:
m_ui.tile->setBoundary(2048 >> selected, selected, selected + 2); m_ui.tile->setBoundary(2048 >> selected, selected, selected + 2);
m_ui.tile->setMaxTile(3096 >> selected);
break; break;
#endif #endif
#ifdef M_CORE_GB #ifdef M_CORE_GB

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>TileView</class> <class>QGBA::TileView</class>
<widget class="QWidget" name="TileView"> <widget class="QWidget" name="QGBA::TileView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>VideoView</class> <class>QGBA::VideoView</class>
<widget class="QWidget" name="VideoView"> <widget class="QWidget" name="QGBA::VideoView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1382,10 +1382,6 @@ void Window::setupMenu(QMenuBar* menubar) {
#ifdef M_CORE_GBA #ifdef M_CORE_GBA
Action* scanCard = addGameAction(tr("Scan e-Reader dotcodes..."), "scanCard", this, &Window::scanCard, "file"); Action* scanCard = addGameAction(tr("Scan e-Reader dotcodes..."), "scanCard", this, &Window::scanCard, "file");
m_platformActions.insert(mPLATFORM_GBA, scanCard); 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 #endif
addGameAction(tr("ROM &info..."), "romInfo", openControllerTView<ROMInfo>(), "file"); 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"); m_actions.addAction(tr("Game Pak sensors..."), "sensorWindow", openNamedControllerTView<SensorView>(&m_sensorView, &m_inputController), "tools");
addGameAction(tr("&Cheats..."), "cheatsWindow", openControllerTView<CheatsView>(), "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.addSeparator("tools");
m_actions.addAction(tr("Settings..."), "settings", this, &Window::openSettingsWindow, "tools")->setRole(Action::Role::SETTINGS); 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); m_platformActions.insert(mPLATFORM_GBA, gdbWindow);
#endif #endif
#endif #endif
#ifdef ENABLE_SCRIPTING
m_actions.addAction(tr("Scripting..."), "scripting", this, &Window::scriptingOpen, "tools");
#endif
#if defined(USE_DEBUGGERS) || defined(ENABLE_SCRIPTING) #if defined(USE_DEBUGGERS) || defined(ENABLE_SCRIPTING)
m_actions.addSeparator("tools"); m_actions.addSeparator("tools");
#endif #endif
addGameAction(tr("View &palette..."), "paletteWindow", openControllerTView<PaletteView>(), "tools"); m_actions.addMenu(tr("Game state views"), "stateViews", "tools");
addGameAction(tr("View &sprites..."), "spriteWindow", openControllerTView<ObjView>(), "tools"); addGameAction(tr("View &palette..."), "paletteWindow", openControllerTView<PaletteView>(), "stateViews");
addGameAction(tr("View &tiles..."), "tileWindow", openControllerTView<TileView>(), "tools"); addGameAction(tr("View &sprites..."), "spriteWindow", openControllerTView<ObjView>(), "stateViews");
addGameAction(tr("View &map..."), "mapWindow", openControllerTView<MapView>(), "tools"); addGameAction(tr("View &tiles..."), "tileWindow", openControllerTView<TileView>(), "stateViews");
addGameAction(tr("View &map..."), "mapWindow", openControllerTView<MapView>(), "stateViews");
addGameAction(tr("&Frame inspector..."), "frameWindow", [this]() { addGameAction(tr("&Frame inspector..."), "frameWindow", [this]() {
if (!m_frameView) { if (!m_frameView) {
@ -1778,11 +1775,16 @@ void Window::setupMenu(QMenuBar* menubar) {
m_frameView->setAttribute(Qt::WA_DeleteOnClose); m_frameView->setAttribute(Qt::WA_DeleteOnClose);
} }
m_frameView->show(); m_frameView->show();
}, "tools"); }, "stateViews");
addGameAction(tr("View memory..."), "memoryView", openControllerTView<MemoryView>(), "tools"); addGameAction(tr("View memory..."), "memoryView", openControllerTView<MemoryView>(), "stateViews");
addGameAction(tr("Search memory..."), "memorySearch", openControllerTView<MemorySearch>(), "tools"); addGameAction(tr("Search memory..."), "memorySearch", openControllerTView<MemorySearch>(), "stateViews");
addGameAction(tr("View &I/O registers..."), "ioViewer", openControllerTView<IOViewer>(), "tools"); 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"); m_actions.addSeparator("tools");
addGameAction(tr("Record debug video log..."), "recordVL", this, &Window::startVideoLog, "tools"); addGameAction(tr("Record debug video log..."), "recordVL", this, &Window::startVideoLog, "tools");

View File

@ -48,11 +48,11 @@ LibraryTree::LibraryTree(LibraryController* parent)
m_widget->setAlternatingRowColors(true); m_widget->setAlternatingRowColors(true);
QTreeWidgetItem* header = new QTreeWidgetItem({ QTreeWidgetItem* header = new QTreeWidgetItem({
QApplication::translate("LibraryTree", "Name", nullptr), QApplication::translate("QGBA::LibraryTree", "Name", nullptr),
QApplication::translate("LibraryTree", "Location", nullptr), QApplication::translate("QGBA::LibraryTree", "Location", nullptr),
QApplication::translate("LibraryTree", "Platform", nullptr), QApplication::translate("QGBA::LibraryTree", "Platform", nullptr),
QApplication::translate("LibraryTree", "Size", nullptr), QApplication::translate("QGBA::LibraryTree", "Size", nullptr),
QApplication::translate("LibraryTree", "CRC32", nullptr), QApplication::translate("QGBA::LibraryTree", "CRC32", nullptr),
}); });
header->setTextAlignment(3, Qt::AlignTrailing | Qt::AlignVCenter); header->setTextAlignment(3, Qt::AlignTrailing | Qt::AlignVCenter);
m_widget->setHeaderItem(header); m_widget->setHeaderItem(header);

View File

@ -61,6 +61,9 @@ void ScriptingController::setController(std::shared_ptr<CoreController> controll
bool ScriptingController::loadFile(const QString& path) { bool ScriptingController::loadFile(const QString& path) {
VFileDevice vf(path, QIODevice::ReadOnly); VFileDevice vf(path, QIODevice::ReadOnly);
if (!vf.isOpen()) {
return false;
}
return load(vf, path); return load(vf, path);
} }

View File

@ -1,67 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ScriptingView</class> <class>QGBA::ScriptingView</class>
<widget class="QMainWindow" name="ScriptingView"> <widget class="QMainWindow" name="QGBA::ScriptingView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>843</width>
<height>600</height> <height>637</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Scripting</string> <string>Scripting</string>
</property> </property>
<widget class="QWidget" name="centralwidget"> <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"> <item row="0" column="0" rowspan="3">
<widget class="QListView" name="buffers"> <widget class="QSplitter" name="splitter">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding"> <enum>Qt::Horizontal</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>180</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QPlainTextEdit" name="buffer">
<property name="lineWrapMode">
<enum>QPlainTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<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">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</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> </property>
<widget class="QListView" name="buffers">
<property name="minimumSize">
<size>
<width>90</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<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="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>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<widget class="QGBA::LogWidget" name="log">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

@ -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>")

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More