Merge branch 'master' (early part) into medusa
4
CHANGES
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
10
README.md
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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*);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
After Width: | Height: | Size: 443 B |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 676 B |
After Width: | Height: | Size: 509 B |
After Width: | Height: | Size: 782 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 390 B |
After Width: | Height: | Size: 548 B |
After Width: | Height: | Size: 677 B |
|
@ -19,6 +19,9 @@
|
||||||
info->operandFormat |= ARM_OPERAND_SHIFT_REGISTER_3; \
|
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; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
enum class Page {
|
enum class Page {
|
||||||
AV,
|
AV,
|
||||||
INTERFACE,
|
INTERFACE,
|
||||||
|
GAMEPLAY,
|
||||||
UPDATE,
|
UPDATE,
|
||||||
EMULATION,
|
EMULATION,
|
||||||
ENHANCEMENTS,
|
ENHANCEMENTS,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>")
|
|