diff --git a/CHANGES b/CHANGES index f18b6aff9..a5112bc34 100644 --- a/CHANGES +++ b/CHANGES @@ -36,6 +36,7 @@ Misc: 0.9.0: (Future) Features: - e-Reader card scanning + - New tool for converting between different save game formats - WebP and APNG recording - Separate overrides for GBC games that can also run on SGB or regular GB - Game Boy Player features can be enabled by default for all compatible games @@ -84,6 +85,7 @@ Emulation fixes: - GBA SIO: Fix copying Normal mode transfer values - GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800) - GBA SIO: Fix deseralizing SIO registers + - GBA SIO: Fix hanging on starting a second multiplayer window (fixes mgba.io/i/854) - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319) - GBA Video: Fix Hblank timing - GBA Video: Implement green swap (fixes mgba.io/i/1609) @@ -93,6 +95,7 @@ Emulation fixes: Other fixes: - 3DS: Fix thread cleanup - All: Improve export headers (fixes mgba.io/i/1738) + - Cheats: Fix indirect write cheats (fixes mgba.io/i/2026) - CMake: Fix build with downstream minizip that exports incompatible symbols - CMake: Link with correct OpenGL library (fixes mgba.io/i/1872) - Core: Ensure ELF regions can be written before trying @@ -129,8 +132,10 @@ Misc: - Core: Add shutdown callback - Core: Rework thread state synchronization - Core: Improve support for ROM patch cheats, supporting disabling overlapping patches + - Core: Adding to library is now recursive - GB: Allow pausing event loop while CPU is blocked - GB: Add support for sleep and shutdown callbacks + - GB: Redo double speed emulation (closes mgba.io/i/1515) - GB Core: Return the current number of banks for ROM/SRAM, not theoretical max - GB I/O: Implement preliminary support for PCM12/PCM34 (closes mgba.io/i/1468) - GBA: Allow pausing event loop while CPU is blocked @@ -156,6 +161,7 @@ Misc: - Qt: Unify monospace font usage - Qt: Add button to jump to log settings - Qt: Use relative paths in portable mode when applicable (fixes mgba.io/i/838) + - Qt: Better initial shortcut editor column sizes - SDL: Fall back to sw blit if OpenGL init fails - Util: Reset vector size on deinit - VFS: Change semantics of VFile.sync on mapped files (fixes mgba.io/i/1730) diff --git a/README.md b/README.md index 652e21060..fdc6d419c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ medusa is an emulator for running Nintendo DS, Game Boy Advance and Game Boy gam Up-to-date news and downloads can be found at [mgba.io](https://mgba.io/). -[![Build status](https://travis-ci.org/mgba-emu/mgba.svg?branch=medusa)](https://travis-ci.org/mgba-emu/mgba) +[![Build status](https://buildbot.mgba.io/badges/build-win32.svg)](https://buildbot.mgba.io) +[![Translation status](https://hosted.weblate.org/widgets/mgba/-/svg-badge.svg)](https://hosted.weblate.org/engage/mgba) Features -------- @@ -37,6 +38,7 @@ Features - Configurable emulation rewinding. - Support for loading and exporting GameShark and Action Replay snapshots. - Cores available for RetroArch/Libretro and OpenEmu. +- Community-provided translations for several languages via [Weblate](https://hosted.weblate.org/engage/mgba). - Many, many smaller things. #### Game Boy mappers @@ -297,7 +299,7 @@ Missing features on DS are Copyright --------- -medusa is Copyright © 2013 – 2020 Jeffrey Pfau. It is distributed under the [Mozilla Public License version 2.0](https://www.mozilla.org/MPL/2.0/). A copy of the license is available in the distributed LICENSE file. +medusa is Copyright © 2013 – 2021 Jeffrey Pfau. It is distributed under the [Mozilla Public License version 2.0](https://www.mozilla.org/MPL/2.0/). A copy of the license is available in the distributed LICENSE file. medusa contains the following third-party libraries: diff --git a/README_DE.md b/README_DE.md index f69477ebf..310ee7193 100644 --- a/README_DE.md +++ b/README_DE.md @@ -6,6 +6,7 @@ mGBA ist ein Emulator für Game Boy Advance-Spiele. Das Ziel von mGBA ist, schne Aktuelle Neuigkeiten und Downloads findest Du auf [mgba.io](https://mgba.io). [![Build-Status](https://travis-ci.org/mgba-emu/mgba.svg?branch=master)](https://travis-ci.org/mgba-emu/mgba) +[![Status der Übersetzungen](https://hosted.weblate.org/widgets/mgba/-/svg-badge.svg)](https://hosted.weblate.org/engage/mgba) Features -------- @@ -36,6 +37,7 @@ Features - Einstellbare Rücklauf-Funktion. - Unterstützung für das Laden und Exportieren von GameShark- und Action Replay-Abbildern. - Verfügbare Cores für RetroArch/Libretro und OpenEmu. +- Übersetzungen für mehrere Sprachen über [Weblate](https://hosted.weblate.org/engage/mgba). - Viele, viele kleinere Dinge. ### Game Boy-Mapper @@ -240,7 +242,7 @@ Fußnoten Copyright --------- -Copyright für mGBA © 2013 – 2020 Jeffrey Pfau. mGBA wird unter der [Mozilla Public License version 2.0](https://www.mozilla.org/MPL/2.0/) veröffentlicht. Eine Kopie der Lizenz ist in der mitgelieferten Datei LICENSE verfügbar. +Copyright für mGBA © 2013 – 2021 Jeffrey Pfau. mGBA wird unter der [Mozilla Public License version 2.0](https://www.mozilla.org/MPL/2.0/) veröffentlicht. Eine Kopie der Lizenz ist in der mitgelieferten Datei LICENSE verfügbar. mGBA beinhaltet die folgenden Bibliotheken von Drittanbietern: diff --git a/README_ES.md b/README_ES.md index 7003a14aa..681ed5556 100644 --- a/README_ES.md +++ b/README_ES.md @@ -5,7 +5,8 @@ mGBA es un emulador para juegos de Game Boy Advance. Su objetivo es ser más rá Las noticias actualizadas y las descargas se encuentran en [mgba.io](https://mgba.io/). -[![Estado de compilación](https://travis-ci.org/mgba-emu/mgba.svg?branch=master)](https://travis-ci.org/mgba-emu/mgba) +[![Estado de la compilación](https://travis-ci.org/mgba-emu/mgba.svg?branch=master)](https://travis-ci.org/mgba-emu/mgba) +[![Estado de la traducción](https://hosted.weblate.org/widgets/mgba/-/svg-badge.svg)](https://hosted.weblate.org/engage/mgba) Características -------- @@ -36,6 +37,7 @@ Características - Retroceso configurable. - Soporte para cargar y exportar instantáneas de GameShark y Action Replay. - Núcleos disponibles para RetroArch/Libretro y OpenEmu. +- Traducciones de la comunidad a través de [Weblate](https://hosted.weblate.org/engage/mgba). - Otras cosas más pequeñas. #### Mappers (controladores de memoria) soportados @@ -240,7 +242,7 @@ Notas a pie Copyright --------- -mGBA es Copyright © 2013 – 2020 Jeffrey Pfau. Es distribuído bajo la [licencia pública de Mozilla (Mozilla Public License) version 2.0](https://www.mozilla.org/MPL/2.0/). Una copia de la licencia está disponible en el archivo LICENSE. +mGBA es Copyright © 2013 – 2021 Jeffrey Pfau. Es distribuído bajo la [licencia pública de Mozilla (Mozilla Public License) version 2.0](https://www.mozilla.org/MPL/2.0/). Una copia de la licencia está disponible en el archivo LICENSE. mGBA contiene las siguientes bibliotecas de terceros: diff --git a/include/mgba-util/math.h b/include/mgba-util/math.h index 793312c9d..985da7795 100644 --- a/include/mgba-util/math.h +++ b/include/mgba-util/math.h @@ -119,6 +119,33 @@ static inline int reduceFraction(int* num, int* den) { return n; } +#define TYPE_GENERICIZE(MACRO) \ + MACRO(int, Int) \ + MACRO(unsigned, UInt) + +#define LOCK_ASPECT_RATIO(T, t) \ + static inline void lockAspectRatio ## t(T refW, T refH, T* w, T* h) { \ + if (*w * refH > *h * refW) { \ + *w = *h * refW / refH; \ + } else if (*w * refH < *h * refW) { \ + *h = *w * refH / refW; \ + } \ + } + +TYPE_GENERICIZE(LOCK_ASPECT_RATIO) +#undef LOCK_ASPECT_RATIO + +#define LOCK_INTEGER_RATIO(T, t) \ + static inline void lockIntegerRatio ## t(T ref, T* val) { \ + if (*val >= ref) { \ + *val -= *val % ref; \ + } \ + } + +TYPE_GENERICIZE(LOCK_INTEGER_RATIO) +#undef LOCK_INTEGER_RATIO + +#undef TYPE_GENERICIZE CXX_GUARD_END #endif diff --git a/include/mgba-util/vfs.h b/include/mgba-util/vfs.h index 8100541e0..c9faded6e 100644 --- a/include/mgba-util/vfs.h +++ b/include/mgba-util/vfs.h @@ -79,7 +79,7 @@ struct VFile* VFileFIFO(struct CircleBuffer* backing); struct VDir* VDirOpen(const char* path); struct VDir* VDirOpenArchive(const char* path); -#if defined(USE_LIBZIP) || defined(USE_ZLIB) +#if defined(USE_LIBZIP) || defined(USE_MINIZIP) struct VDir* VDirOpenZip(const char* path, int flags); #endif diff --git a/include/mgba/core/core.h b/include/mgba/core/core.h index 96e406918..dcd9bffb1 100644 --- a/include/mgba/core/core.h +++ b/include/mgba/core/core.h @@ -191,6 +191,7 @@ void mCoreTakeScreenshot(struct mCore* core); struct mCore* mCoreFindVF(struct VFile* vf); enum mPlatform mCoreIsCompatible(struct VFile* vf); +struct mCore* mCoreCreate(enum mPlatform); bool mCoreSaveStateNamed(struct mCore* core, struct VFile* vf, int flags); bool mCoreLoadStateNamed(struct mCore* core, struct VFile* vf, int flags); diff --git a/include/mgba/core/library.h b/include/mgba/core/library.h index d55ad4094..d12aa0411 100644 --- a/include/mgba/core/library.h +++ b/include/mgba/core/library.h @@ -35,7 +35,7 @@ void mLibraryDestroy(struct mLibrary*); struct VDir; struct VFile; -void mLibraryLoadDirectory(struct mLibrary* library, const char* base); +void mLibraryLoadDirectory(struct mLibrary* library, const char* base, bool recursive); void mLibraryClear(struct mLibrary* library); size_t mLibraryCount(struct mLibrary* library, const struct mLibraryEntry* constraints); diff --git a/include/mgba/internal/gb/serialize.h b/include/mgba/internal/gb/serialize.h index b3cde1661..18ac83b09 100644 --- a/include/mgba/internal/gb/serialize.h +++ b/include/mgba/internal/gb/serialize.h @@ -13,8 +13,8 @@ CXX_GUARD_START #include #include -extern const uint32_t GB_SAVESTATE_MAGIC; -extern const uint32_t GB_SAVESTATE_VERSION; +extern MGBA_EXPORT const uint32_t GBSavestateMagic; +extern MGBA_EXPORT const uint32_t GBSavestateVersion; mLOG_DECLARE_CATEGORY(GB_STATE); diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index e901329bd..bf6a93774 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -14,8 +14,8 @@ CXX_GUARD_START #include #include -extern const uint32_t GBA_SAVESTATE_MAGIC; -extern const uint32_t GBA_SAVESTATE_VERSION; +extern MGBA_EXPORT const uint32_t GBASavestateMagic; +extern MGBA_EXPORT const uint32_t GBASavestateVersion; mLOG_DECLARE_CATEGORY(GBA_STATE); diff --git a/include/mgba/internal/sm83/sm83.h b/include/mgba/internal/sm83/sm83.h index 10bbf8bc4..86b4d374b 100644 --- a/include/mgba/internal/sm83/sm83.h +++ b/include/mgba/internal/sm83/sm83.h @@ -133,6 +133,7 @@ struct SM83Core { uint16_t index; + int tMultiplier; int32_t cycles; int32_t nextEvent; enum SM83ExecutionState executionState; diff --git a/src/core/cheats.c b/src/core/cheats.c index 8e2e43b05..090883ac2 100644 --- a/src/core/cheats.c +++ b/src/core/cheats.c @@ -666,7 +666,7 @@ void mCheatRefresh(struct mCheatDevice* device, struct mCheatSet* cheats) { break; case CHEAT_ASSIGN_INDIRECT: value = operand; - address = _readMem(device->p, address + cheat->addressOffset, 4); + address = _readMem(device->p, address, 4) + cheat->addressOffset; performAssignment = true; break; case CHEAT_AND: diff --git a/src/core/config.c b/src/core/config.c index b25ba9317..5a9599c4e 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -212,14 +212,20 @@ void mCoreConfigDirectory(char* out, size_t outLength) { } } #ifdef _WIN32 - wchar_t wpath[MAX_PATH]; - wchar_t wprojectName[MAX_PATH]; - wchar_t* home; + WCHAR wpath[MAX_PATH]; + WCHAR wprojectName[MAX_PATH]; + WCHAR* home; MultiByteToWideChar(CP_UTF8, 0, projectName, -1, wprojectName, MAX_PATH); SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &home); StringCchPrintfW(wpath, MAX_PATH, L"%ws\\%ws", home, wprojectName); CoTaskMemFree(home); CreateDirectoryW(wpath, NULL); + if (PATH_SEP[0] != '\\') { + WCHAR* pathSep; + for (pathSep = wpath; pathSep = wcschr(pathSep, L'\\');) { + pathSep[0] = PATH_SEP[0]; + } + } WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, outLength, 0, 0); #elif defined(PSP2) snprintf(out, outLength, "ux0:data/%s", projectName); @@ -256,8 +262,14 @@ void mCoreConfigPortablePath(char* out, size_t outLength) { HMODULE hModule = GetModuleHandleW(NULL); GetModuleFileNameW(hModule, wpath, MAX_PATH); PathRemoveFileSpecW(wpath); + if (PATH_SEP[0] != '\\') { + WCHAR* pathSep; + for (pathSep = wpath; pathSep = wcschr(pathSep, L'\\');) { + pathSep[0] = PATH_SEP[0]; + } + } WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, outLength, 0, 0); - StringCchCatA(out, outLength, "\\portable.ini"); + StringCchCatA(out, outLength, PATH_SEP "portable.ini"); #elif defined(PSP2) || defined(GEKKO) || defined(__SWITCH__) || defined(_3DS) out[0] = '\0'; #else diff --git a/src/core/core.c b/src/core/core.c index 7c4182a5e..74978fe9a 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -80,6 +80,19 @@ enum mPlatform mCoreIsCompatible(struct VFile* vf) { return mPLATFORM_NONE; } +struct mCore* mCoreCreate(enum mPlatform platform) { + const struct mCoreFilter* filter; + for (filter = &_filters[0]; filter->filter; ++filter) { + if (filter->platform == platform) { + break; + } + } + if (filter->open) { + return filter->open(); + } + return NULL; +} + #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 #include diff --git a/src/core/library.c b/src/core/library.c index 530ad6cb9..eeb7794de 100644 --- a/src/core/library.c +++ b/src/core/library.c @@ -42,7 +42,7 @@ struct mLibrary { static void _mLibraryDeleteEntry(struct mLibrary* library, struct mLibraryEntry* entry); static void _mLibraryInsertEntry(struct mLibrary* library, struct mLibraryEntry* entry); -static void _mLibraryAddEntry(struct mLibrary* library, const char* filename, const char* base, struct VFile* vf); +static bool _mLibraryAddEntry(struct mLibrary* library, const char* filename, const char* base, struct VFile* vf); static void _bindConstraints(sqlite3_stmt* statement, const struct mLibraryEntry* constraints) { if (!constraints) { @@ -212,7 +212,7 @@ void mLibraryDestroy(struct mLibrary* library) { free(library); } -void mLibraryLoadDirectory(struct mLibrary* library, const char* base) { +void mLibraryLoadDirectory(struct mLibrary* library, const char* base, bool recursive) { struct VDir* dir = VDirOpenArchive(base); if (!dir) { dir = VDirOpen(base); @@ -248,44 +248,55 @@ void mLibraryLoadDirectory(struct mLibrary* library, const char* base) { dir->rewind(dir); struct VDirEntry* dirent = dir->listNext(dir); while (dirent) { - struct VFile* vf = dir->openFile(dir, dirent->name(dirent), O_RDONLY); - if (!vf) { - dirent = dir->listNext(dir); - continue; + const char* name = dirent->name(dirent); + struct VFile* vf = dir->openFile(dir, name, O_RDONLY); + bool wasAdded = false; + + if (vf) { + wasAdded = _mLibraryAddEntry(library, name, base, vf); + } + if (!wasAdded && name[0] != '.') { + char newBase[PATH_MAX]; + snprintf(newBase, sizeof(newBase), "%s" PATH_SEP "%s", base, name); + + if (recursive) { + mLibraryLoadDirectory(library, newBase, recursive); + } else if (dirent->type(dirent) == VFS_FILE) { + mLibraryLoadDirectory(library, newBase, true); // This will add as an archive + } } - _mLibraryAddEntry(library, dirent->name(dirent), base, vf); dirent = dir->listNext(dir); } dir->close(dir); sqlite3_exec(library->db, "COMMIT;", NULL, NULL, NULL); } -void _mLibraryAddEntry(struct mLibrary* library, const char* filename, const char* base, struct VFile* vf) { - struct mCore* core; +bool _mLibraryAddEntry(struct mLibrary* library, const char* filename, const char* base, struct VFile* vf) { if (!vf) { - return; + return false; } - core = mCoreFindVF(vf); - if (core) { - struct mLibraryEntry entry; - memset(&entry, 0, sizeof(entry)); - core->init(core); - core->loadROM(core, vf); - - core->getGameTitle(core, entry.internalTitle); - core->getGameCode(core, entry.internalCode); - core->checksum(core, &entry.crc32, mCHECKSUM_CRC32); - entry.platform = core->platform(core); - entry.title = NULL; - entry.base = base; - entry.filename = filename; - entry.filesize = vf->size(vf); - _mLibraryInsertEntry(library, &entry); - // Note: this destroys the VFile - core->deinit(core); - } else { + struct mCore* core = mCoreFindVF(vf); + if (!core) { vf->close(vf); + return false; } + struct mLibraryEntry entry; + memset(&entry, 0, sizeof(entry)); + core->init(core); + core->loadROM(core, vf); + + core->getGameTitle(core, entry.internalTitle); + core->getGameCode(core, entry.internalCode); + core->checksum(core, &entry.crc32, mCHECKSUM_CRC32); + entry.platform = core->platform(core); + entry.title = NULL; + entry.base = base; + entry.filename = filename; + entry.filesize = vf->size(vf); + _mLibraryInsertEntry(library, &entry); + // Note: this destroys the VFile + core->deinit(core); + return true; } static void _mLibraryInsertEntry(struct mLibrary* library, struct mLibraryEntry* entry) { diff --git a/src/core/serialize.c b/src/core/serialize.c index d7bd65144..581d83ebe 100644 --- a/src/core/serialize.c +++ b/src/core/serialize.c @@ -282,7 +282,11 @@ static void* _loadPNGState(struct mCore* core, struct VFile* vf, struct mStateEx success = success && PNGReadFooter(png, end); PNGReadClose(png, info, end); - if (success) { + if (!success) { + free(pixels); + mappedMemoryFree(state, stateSize); + return NULL; + } else if (extdata) { struct mStateExtdataItem item = { .size = width * height * 4, .data = pixels, @@ -291,8 +295,6 @@ static void* _loadPNGState(struct mCore* core, struct VFile* vf, struct mStateEx mStateExtdataPut(extdata, EXTDATA_SCREENSHOT, &item); } else { free(pixels); - mappedMemoryFree(state, stateSize); - return 0; } return state; } diff --git a/src/gb/audio.c b/src/gb/audio.c index 126f4bf17..f20fa3fac 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -65,7 +65,7 @@ void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAu if (style == GB_AUDIO_GBA) { audio->timingFactor = 4; } else { - audio->timingFactor = 1; + audio->timingFactor = 2; } audio->frameEvent.context = audio; @@ -339,7 +339,7 @@ void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) { if (audio->playingCh3) { audio->ch3.readable = audio->style != GB_AUDIO_DMG; // TODO: Where does this cycle delay come from? - mTimingSchedule(audio->timing, &audio->ch3Event, audio->timingFactor * 4 + 2 * (2048 - audio->ch3.rate)); + mTimingSchedule(audio->timing, &audio->ch3Event, audio->timingFactor * (4 + 2 * (2048 - audio->ch3.rate))); } *audio->nr52 &= ~0x0004; *audio->nr52 |= audio->playingCh3 << 2; @@ -477,11 +477,8 @@ void GBAudioWriteNR52(struct GBAudio* audio, uint8_t value) { audio->skipFrame = false; audio->frame = 7; - if (audio->p) { - unsigned timingFactor = 0x400 >> !audio->p->doubleSpeed; - if (audio->p->timer.internalDiv & timingFactor) { - audio->skipFrame = true; - } + if (audio->p && audio->p->timer.internalDiv & 0x400) { + audio->skipFrame = true; } } } @@ -914,7 +911,7 @@ static void _updateChannel3(struct mTiming* timing, void* user, uint32_t cyclesL audio->ch3.readable = true; if (audio->style == GB_AUDIO_DMG) { mTimingDeschedule(audio->timing, &audio->ch3Fade); - mTimingSchedule(timing, &audio->ch3Fade, 2 - cyclesLate); + mTimingSchedule(timing, &audio->ch3Fade, 4 - cyclesLate); } int cycles = 2 * (2048 - ch->rate); mTimingSchedule(timing, &audio->ch3Event, audio->timingFactor * cycles - cyclesLate); diff --git a/src/gb/gb.c b/src/gb/gb.c index fdc30724b..00eae92c0 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -742,7 +742,7 @@ void GBSetInterrupts(struct SM83Core* cpu, bool enable) { gb->memory.ime = false; GBUpdateIRQs(gb); } else { - mTimingSchedule(&gb->timing, &gb->eiPending, 4); + mTimingSchedule(&gb->timing, &gb->eiPending, 4 * cpu->tMultiplier); } } @@ -796,7 +796,7 @@ void GBStop(struct SM83Core* cpu) { struct GB* gb = (struct GB*) cpu->master; if (gb->model >= GB_MODEL_CGB && gb->memory.io[GB_REG_KEY1] & 1) { gb->doubleSpeed ^= 1; - gb->audio.timingFactor = gb->doubleSpeed + 1; + gb->cpu->tMultiplier = 2 - gb->doubleSpeed; gb->memory.io[GB_REG_KEY1] = 0; gb->memory.io[GB_REG_KEY1] |= gb->doubleSpeed << 7; } else { diff --git a/src/gb/io.c b/src/gb/io.c index 0e3a70eca..6cf77e4c8 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -417,15 +417,15 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) { } return; case GB_REG_TIMA: - if (value && mTimingUntil(&gb->timing, &gb->timer.irq) > 1) { + if (value && mTimingUntil(&gb->timing, &gb->timer.irq) > 2 - (int) gb->doubleSpeed) { mTimingDeschedule(&gb->timing, &gb->timer.irq); } - if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) { + if (mTimingUntil(&gb->timing, &gb->timer.irq) == (int) gb->doubleSpeed - 2) { return; } break; case GB_REG_TMA: - if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) { + if (mTimingUntil(&gb->timing, &gb->timer.irq) == (int) gb->doubleSpeed - 2) { gb->memory.io[GB_REG_TIMA] = value; } break; diff --git a/src/gb/memory.c b/src/gb/memory.c index b7bd9c9d3..a65ea0e89 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -531,10 +531,7 @@ void GBMemoryDMA(struct GB* gb, uint16_t base) { base &= 0xDFFF; } mTimingDeschedule(&gb->timing, &gb->memory.dmaEvent); - mTimingSchedule(&gb->timing, &gb->memory.dmaEvent, 8); - if (gb->cpu->cycles + 8 < gb->cpu->nextEvent) { - gb->cpu->nextEvent = gb->cpu->cycles + 8; - } + mTimingSchedule(&gb->timing, &gb->memory.dmaEvent, 8 * (2 - gb->doubleSpeed)); gb->memory.dmaSource = base; gb->memory.dmaDest = 0; gb->memory.dmaRemaining = 0xA0; @@ -580,7 +577,7 @@ void _GBMemoryDMAService(struct mTiming* timing, void* context, uint32_t cyclesL ++gb->memory.dmaDest; gb->memory.dmaRemaining = dmaRemaining - 1; if (gb->memory.dmaRemaining) { - mTimingSchedule(timing, &gb->memory.dmaEvent, 4 - cyclesLate); + mTimingSchedule(timing, &gb->memory.dmaEvent, 4 * (2 - gb->doubleSpeed) - cyclesLate); } } @@ -594,7 +591,7 @@ void _GBMemoryHDMAService(struct mTiming* timing, void* context, uint32_t cycles --gb->memory.hdmaRemaining; if (gb->memory.hdmaRemaining) { mTimingDeschedule(timing, &gb->memory.hdmaEvent); - mTimingSchedule(timing, &gb->memory.hdmaEvent, 2 - cyclesLate); + mTimingSchedule(timing, &gb->memory.hdmaEvent, 4 - cyclesLate); } else { gb->cpuBlocked = false; gb->memory.io[GB_REG_HDMA1] = gb->memory.hdmaSource >> 8; diff --git a/src/gb/serialize.c b/src/gb/serialize.c index 056d1fd77..f50d0bb86 100644 --- a/src/gb/serialize.c +++ b/src/gb/serialize.c @@ -13,11 +13,11 @@ mLOG_DEFINE_CATEGORY(GB_STATE, "GB Savestate", "gb.serialize"); -const uint32_t GB_SAVESTATE_MAGIC = 0x00400000; -const uint32_t GB_SAVESTATE_VERSION = 0x00000002; +MGBA_EXPORT const uint32_t GBSavestateMagic = 0x00400000; +MGBA_EXPORT const uint32_t GBSavestateVersion = 0x00000002; void GBSerialize(struct GB* gb, struct GBSerializedState* state) { - STORE_32LE(GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION, 0, &state->versionMagic); + STORE_32LE(GBSavestateMagic + GBSavestateVersion, 0, &state->versionMagic); STORE_32LE(gb->romCrc32, 0, &state->romCrc32); STORE_32LE(gb->timing.masterCycles, 0, &state->masterCycles); STORE_64LE(gb->timing.globalCycles, 0, &state->globalCycles); @@ -76,20 +76,20 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) { int16_t check16; uint16_t ucheck16; LOAD_32LE(ucheck, 0, &state->versionMagic); - if (ucheck > GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION) { - mLOG(GB_STATE, WARN, "Invalid or too new savestate: expected %08X, got %08X", GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION, ucheck); + if (ucheck > GBSavestateMagic + GBSavestateVersion) { + mLOG(GB_STATE, WARN, "Invalid or too new savestate: expected %08X, got %08X", GBSavestateMagic + GBSavestateVersion, ucheck); error = true; - } else if (ucheck < GB_SAVESTATE_MAGIC) { - mLOG(GB_STATE, WARN, "Invalid savestate: expected %08X, got %08X", GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION, ucheck); + } else if (ucheck < GBSavestateMagic) { + mLOG(GB_STATE, WARN, "Invalid savestate: expected %08X, got %08X", GBSavestateMagic + GBSavestateVersion, ucheck); error = true; - } else if (ucheck < GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION) { - mLOG(GB_STATE, WARN, "Old savestate: expected %08X, got %08X, continuing anyway", GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION, ucheck); + } else if (ucheck < GBSavestateMagic + GBSavestateVersion) { + mLOG(GB_STATE, WARN, "Old savestate: expected %08X, got %08X, continuing anyway", GBSavestateMagic + GBSavestateVersion, ucheck); } - bool canSgb = ucheck >= GB_SAVESTATE_MAGIC + 2; + bool canSgb = ucheck >= GBSavestateMagic + 2; if (gb->memory.rom && memcmp(state->title, ((struct GBCartridge*) &gb->memory.rom[0x100])->titleLong, sizeof(state->title))) { LOAD_32LE(ucheck, 0, &state->versionMagic); - if (ucheck > GB_SAVESTATE_MAGIC + 2 || memcmp(state->title, ((struct GBCartridge*) gb->memory.rom)->titleLong, sizeof(state->title))) { + if (ucheck > GBSavestateMagic + 2 || memcmp(state->title, ((struct GBCartridge*) gb->memory.rom)->titleLong, sizeof(state->title))) { // There was a bug in previous versions where the memory address being compared was wrong mLOG(GB_STATE, WARN, "Savestate is for a different game"); error = true; @@ -175,8 +175,6 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) { gb->cpu->halted = GBSerializedCpuFlagsGetHalted(flags); gb->cpuBlocked = GBSerializedCpuFlagsGetBlocked(flags); - gb->audio.timingFactor = gb->doubleSpeed + 1; - LOAD_32LE(gb->cpu->cycles, 0, &state->cpu.cycles); LOAD_32LE(gb->cpu->nextEvent, 0, &state->cpu.nextEvent); gb->timing.root = NULL; diff --git a/src/gb/sio.c b/src/gb/sio.c index 78e3a92e1..d327b606d 100644 --- a/src/gb/sio.c +++ b/src/gb/sio.c @@ -77,7 +77,7 @@ void _GBSIOProcessEvents(struct mTiming* timing, void* context, uint32_t cyclesL sio->pendingSB = 0xFF; } } else { - mTimingSchedule(timing, &sio->event, sio->period); + mTimingSchedule(timing, &sio->event, sio->period * (2 - sio->p->doubleSpeed)); } } @@ -93,7 +93,7 @@ void GBSIOWriteSC(struct GBSIO* sio, uint8_t sc) { if (GBRegisterSCIsEnable(sc)) { mTimingDeschedule(&sio->p->timing, &sio->event); if (GBRegisterSCIsShiftClock(sc)) { - mTimingSchedule(&sio->p->timing, &sio->event, sio->period); + mTimingSchedule(&sio->p->timing, &sio->event, sio->period * (2 - sio->p->doubleSpeed)); sio->remainingBits = 8; } } diff --git a/src/gb/sio/lockstep.c b/src/gb/sio/lockstep.c index a9b3ed8fd..d739140e5 100644 --- a/src/gb/sio/lockstep.c +++ b/src/gb/sio/lockstep.c @@ -128,7 +128,7 @@ static int32_t _masterUpdate(struct GBSIOLockstepNode* node) { case TRANSFER_FINISHING: // Finish the transfer // We need to make sure the other GBs catch up so they don't get behind - node->nextEvent += node->d.p->period - 8; // Split the cycles to avoid waiting too long + node->nextEvent += node->d.p->period * (2 - node->d.p->p->doubleSpeed) - 8; // Split the cycles to avoid waiting too long #ifndef NDEBUG ATOMIC_ADD(node->p->d.transferId, 1); #endif @@ -208,7 +208,7 @@ static void _GBSIOLockstepNodeProcessEvents(struct mTiming* timing, void* user, struct GBSIOLockstepNode* node = user; mLockstepLock(&node->p->d); if (node->p->d.attached < 2) { - mTimingSchedule(timing, &node->event, (GBSIOCyclesPerTransfer[0] >> 1) - cyclesLate); + mTimingSchedule(timing, &node->event, (GBSIOCyclesPerTransfer[0] >> 1) * (2 - node->d.p->p->doubleSpeed) - cyclesLate); mLockstepUnlock(&node->p->d); return; } diff --git a/src/gb/timer.c b/src/gb/timer.c index 1a99a06fd..0be048139 100644 --- a/src/gb/timer.c +++ b/src/gb/timer.c @@ -20,17 +20,18 @@ void _GBTimerIRQ(struct mTiming* timing, void* context, uint32_t cyclesLate) { } static void _GBTimerDivIncrement(struct GBTimer* timer, uint32_t cyclesLate) { - while (timer->nextDiv >= GB_DMG_DIV_PERIOD) { - timer->nextDiv -= GB_DMG_DIV_PERIOD; + int tMultiplier = 2 - timer->p->doubleSpeed; + while (timer->nextDiv >= GB_DMG_DIV_PERIOD * tMultiplier) { + timer->nextDiv -= GB_DMG_DIV_PERIOD * tMultiplier; // Make sure to trigger when the correct bit is a falling edge if (timer->timaPeriod > 0 && (timer->internalDiv & (timer->timaPeriod - 1)) == timer->timaPeriod - 1) { ++timer->p->memory.io[GB_REG_TIMA]; if (!timer->p->memory.io[GB_REG_TIMA]) { - mTimingSchedule(&timer->p->timing, &timer->irq, 7 - ((timer->p->cpu->executionState - cyclesLate) & 3)); + mTimingSchedule(&timer->p->timing, &timer->irq, 7 * tMultiplier - ((timer->p->cpu->executionState * tMultiplier - cyclesLate) & (3 * tMultiplier))); } } - unsigned timingFactor = 0x3FF >> !timer->p->doubleSpeed; + unsigned timingFactor = 0x1FF; if ((timer->internalDiv & timingFactor) == timingFactor) { GBAudioUpdateFrame(&timer->p->audio, &timer->p->timing); } @@ -52,7 +53,7 @@ void _GBTimerUpdate(struct mTiming* timing, void* context, uint32_t cyclesLate) if (timaToGo < divsToGo) { divsToGo = timaToGo; } - timer->nextDiv = GB_DMG_DIV_PERIOD * divsToGo; + timer->nextDiv = GB_DMG_DIV_PERIOD * divsToGo * (2 - timer->p->doubleSpeed); mTimingSchedule(timing, &timer->event, timer->nextDiv - cyclesLate); } @@ -66,7 +67,7 @@ void GBTimerReset(struct GBTimer* timer) { timer->irq.callback = _GBTimerIRQ; timer->event.priority = 0x21; - timer->nextDiv = GB_DMG_DIV_PERIOD; // TODO: GBC differences + timer->nextDiv = GB_DMG_DIV_PERIOD * 2; timer->timaPeriod = 1024 >> 4; } @@ -74,27 +75,27 @@ void GBTimerDivReset(struct GBTimer* timer) { timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event); mTimingDeschedule(&timer->p->timing, &timer->event); _GBTimerDivIncrement(timer, 0); - if (((timer->internalDiv << 1) | ((timer->nextDiv >> 3) & 1)) & timer->timaPeriod) { + int tMultiplier = 2 - timer->p->doubleSpeed; + if (((timer->internalDiv << 1) | ((timer->nextDiv >> (4 - timer->p->doubleSpeed)) & 1)) & timer->timaPeriod) { ++timer->p->memory.io[GB_REG_TIMA]; if (!timer->p->memory.io[GB_REG_TIMA]) { - mTimingSchedule(&timer->p->timing, &timer->irq, 7 - (timer->p->cpu->executionState & 3)); + mTimingSchedule(&timer->p->timing, &timer->irq, (7 - (timer->p->cpu->executionState & 3)) * tMultiplier); } } - unsigned timingFactor = 0x400 >> !timer->p->doubleSpeed; - if (timer->internalDiv & timingFactor) { + if (timer->internalDiv & 0x200) { GBAudioUpdateFrame(&timer->p->audio, &timer->p->timing); } timer->p->memory.io[GB_REG_DIV] = 0; timer->internalDiv = 0; - timer->nextDiv = GB_DMG_DIV_PERIOD; - mTimingSchedule(&timer->p->timing, &timer->event, timer->nextDiv - ((timer->p->cpu->executionState + 1) & 3)); + timer->nextDiv = GB_DMG_DIV_PERIOD * (2 - timer->p->doubleSpeed); + mTimingSchedule(&timer->p->timing, &timer->event, timer->nextDiv - ((timer->p->cpu->executionState + 1) & 3) * tMultiplier); } uint8_t GBTimerUpdateTAC(struct GBTimer* timer, GBRegisterTAC tac) { if (GBRegisterTACIsRun(tac)) { timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event); mTimingDeschedule(&timer->p->timing, &timer->event); - _GBTimerDivIncrement(timer, (timer->p->cpu->executionState + 2) & 3); + _GBTimerDivIncrement(timer, ((timer->p->cpu->executionState + 2) & 3) * (2 - timer->p->doubleSpeed)); switch (GBRegisterTACGetClock(tac)) { case 0: @@ -111,7 +112,7 @@ uint8_t GBTimerUpdateTAC(struct GBTimer* timer, GBRegisterTAC tac) { break; } - timer->nextDiv += GB_DMG_DIV_PERIOD; + timer->nextDiv += GB_DMG_DIV_PERIOD * (2 - timer->p->doubleSpeed); mTimingSchedule(&timer->p->timing, &timer->event, timer->nextDiv); } else { timer->timaPeriod = 0; diff --git a/src/gb/video.c b/src/gb/video.c index 9826b601f..ccaae7717 100644 --- a/src/gb/video.c +++ b/src/gb/video.c @@ -253,7 +253,7 @@ void GBVideoSkipBIOS(struct GBVideo* video) { GBUpdateIRQs(video->p); video->p->memory.io[GB_REG_STAT] = video->stat; mTimingDeschedule(&video->p->timing, &video->modeEvent); - mTimingSchedule(&video->p->timing, &video->modeEvent, next); + mTimingSchedule(&video->p->timing, &video->modeEvent, next << 1); } void _endMode0(struct mTiming* timing, void* context, uint32_t cyclesLate) { @@ -297,7 +297,7 @@ void _endMode0(struct mTiming* timing, void* context, uint32_t cyclesLate) { GBUpdateIRQs(video->p); video->p->memory.io[GB_REG_STAT] = video->stat; - mTimingSchedule(timing, &video->modeEvent, (next << video->p->doubleSpeed) - cyclesLate); + mTimingSchedule(timing, &video->modeEvent, (next << 1) - cyclesLate); } void _endMode1(struct mTiming* timing, void* context, uint32_t cyclesLate) { @@ -334,14 +334,14 @@ void _endMode1(struct mTiming* timing, void* context, uint32_t cyclesLate) { GBUpdateIRQs(video->p); } video->p->memory.io[GB_REG_STAT] = video->stat; - mTimingSchedule(timing, &video->modeEvent, (next << video->p->doubleSpeed) - cyclesLate); + mTimingSchedule(timing, &video->modeEvent, (next << 1) - cyclesLate); } void _endMode2(struct mTiming* timing, void* context, uint32_t cyclesLate) { struct GBVideo* video = context; _cleanOAM(video, video->ly); video->x = -(video->p->memory.io[GB_REG_SCX] & 7); - video->dotClock = mTimingCurrentTime(timing) - cyclesLate + 5 - (video->x << video->p->doubleSpeed); + video->dotClock = mTimingCurrentTime(timing) - cyclesLate + 10 - (video->x << 1); int32_t next = GB_VIDEO_MODE_3_LENGTH_BASE + video->objMax * 6 - video->x; video->mode = 3; video->modeEvent.callback = _endMode3; @@ -352,7 +352,7 @@ void _endMode2(struct mTiming* timing, void* context, uint32_t cyclesLate) { GBUpdateIRQs(video->p); } video->p->memory.io[GB_REG_STAT] = video->stat; - mTimingSchedule(timing, &video->modeEvent, (next << video->p->doubleSpeed) - cyclesLate); + mTimingSchedule(timing, &video->modeEvent, (next << 1) - cyclesLate); } void _endMode3(struct mTiming* timing, void* context, uint32_t cyclesLate) { @@ -375,18 +375,18 @@ void _endMode3(struct mTiming* timing, void* context, uint32_t cyclesLate) { video->p->memory.io[GB_REG_STAT] = video->stat; // TODO: Cache SCX & 7 in case it changes int32_t next = GB_VIDEO_MODE_0_LENGTH_BASE - video->objMax * 6 - (video->p->memory.io[GB_REG_SCX] & 7); - mTimingSchedule(timing, &video->modeEvent, (next << video->p->doubleSpeed) - cyclesLate); + mTimingSchedule(timing, &video->modeEvent, (next << 1) - cyclesLate); } void _updateFrameCount(struct mTiming* timing, void* context, uint32_t cyclesLate) { UNUSED(cyclesLate); struct GBVideo* video = context; if (video->p->cpu->executionState != SM83_CORE_FETCH) { - mTimingSchedule(timing, &video->frameEvent, 4 - ((video->p->cpu->executionState + 1) & 3)); + mTimingSchedule(timing, &video->frameEvent, (4 - ((video->p->cpu->executionState + 1) & 3)) * (2 - video->p->doubleSpeed)); return; } if (!GBRegisterLCDCIsEnable(video->p->memory.io[GB_REG_LCDC])) { - mTimingSchedule(timing, &video->frameEvent, GB_VIDEO_TOTAL_LENGTH); + mTimingSchedule(timing, &video->frameEvent, GB_VIDEO_TOTAL_LENGTH << 1); } --video->frameskipCounter; @@ -424,7 +424,7 @@ void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate) { return; } int oldX = video->x; - video->x = (int32_t) (mTimingCurrentTime(&video->p->timing) - cyclesLate - video->dotClock) >> video->p->doubleSpeed; + video->x = ((int32_t) (mTimingCurrentTime(&video->p->timing) - cyclesLate - video->dotClock)) >> 1; if (video->x > GB_VIDEO_HORIZONTAL_PIXELS) { video->x = GB_VIDEO_HORIZONTAL_PIXELS; } else if (video->x < 0) { @@ -444,7 +444,7 @@ void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) { video->modeEvent.callback = _endMode2; int32_t next = GB_VIDEO_MODE_2_LENGTH - 5; // TODO: Why is this fudge factor needed? Might be related to T-cycles for load/store differing mTimingDeschedule(&video->p->timing, &video->modeEvent); - mTimingSchedule(&video->p->timing, &video->modeEvent, next << video->p->doubleSpeed); + mTimingSchedule(&video->p->timing, &video->modeEvent, next << 1); video->ly = 0; video->p->memory.io[GB_REG_LY] = 0; @@ -471,7 +471,7 @@ void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) { mTimingDeschedule(&video->p->timing, &video->modeEvent); mTimingDeschedule(&video->p->timing, &video->frameEvent); - mTimingSchedule(&video->p->timing, &video->frameEvent, GB_VIDEO_TOTAL_LENGTH); + mTimingSchedule(&video->p->timing, &video->frameEvent, GB_VIDEO_TOTAL_LENGTH << 1); } video->p->memory.io[GB_REG_STAT] = video->stat; } diff --git a/src/gba/matrix.c b/src/gba/matrix.c index c9c12ff9a..fb72e052f 100644 --- a/src/gba/matrix.c +++ b/src/gba/matrix.c @@ -11,6 +11,8 @@ #include #include +#define MAPPING_MASK (GBA_MATRIX_MAPPINGS_MAX - 1) + static void _remapMatrix(struct GBA* gba) { if (gba->memory.matrix.vaddr & 0xFFFFE1FF) { mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping: %08X", gba->memory.matrix.vaddr); @@ -24,11 +26,11 @@ static void _remapMatrix(struct GBA* gba) { mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping end: %08X", gba->memory.matrix.vaddr + gba->memory.matrix.size); return; } - int start = (gba->memory.matrix.vaddr >> 9) & 0x1F; - int size = (gba->memory.matrix.size >> 9) & 0x1F; + int start = gba->memory.matrix.vaddr >> 9; + int size = (gba->memory.matrix.size >> 9) & MAPPING_MASK; int i; for (i = 0; i < size; ++i) { - gba->memory.matrix.mappings[start + i] = gba->memory.matrix.paddr + (i << 9); + gba->memory.matrix.mappings[(start + i) & MAPPING_MASK] = gba->memory.matrix.paddr + (i << 9); } gba->romVf->seek(gba->romVf, gba->memory.matrix.paddr, SEEK_SET); diff --git a/src/gba/serialize.c b/src/gba/serialize.c index fbb7d99d9..f6eafa6a4 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -14,8 +14,8 @@ #include -const uint32_t GBA_SAVESTATE_MAGIC = 0x01000000; -const uint32_t GBA_SAVESTATE_VERSION = 0x00000004; +MGBA_EXPORT const uint32_t GBASavestateMagic = 0x01000000; +MGBA_EXPORT const uint32_t GBASavestateVersion = 0x00000004; mLOG_DEFINE_CATEGORY(GBA_STATE, "GBA Savestate", "gba.serialize"); @@ -25,7 +25,7 @@ struct GBABundledState { }; void GBASerialize(struct GBA* gba, struct GBASerializedState* state) { - STORE_32(GBA_SAVESTATE_MAGIC + GBA_SAVESTATE_VERSION, 0, &state->versionMagic); + STORE_32(GBASavestateMagic + GBASavestateVersion, 0, &state->versionMagic); STORE_32(gba->biosChecksum, 0, &state->biosChecksum); STORE_32(gba->romCrc32, 0, &state->romCrc32); STORE_32(gba->timing.masterCycles, 0, &state->masterCycles); @@ -87,14 +87,14 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) { int32_t check; uint32_t ucheck; LOAD_32(ucheck, 0, &state->versionMagic); - if (ucheck > GBA_SAVESTATE_MAGIC + GBA_SAVESTATE_VERSION) { - mLOG(GBA_STATE, WARN, "Invalid or too new savestate: expected %08X, got %08X", GBA_SAVESTATE_MAGIC + GBA_SAVESTATE_VERSION, ucheck); + if (ucheck > GBASavestateMagic + GBASavestateVersion) { + mLOG(GBA_STATE, WARN, "Invalid or too new savestate: expected %08X, got %08X", GBASavestateMagic + GBASavestateVersion, ucheck); error = true; - } else if (ucheck < GBA_SAVESTATE_MAGIC) { - mLOG(GBA_STATE, WARN, "Invalid savestate: expected %08X, got %08X", GBA_SAVESTATE_MAGIC + GBA_SAVESTATE_VERSION, ucheck); + } else if (ucheck < GBASavestateMagic) { + mLOG(GBA_STATE, WARN, "Invalid savestate: expected %08X, got %08X", GBASavestateMagic + GBASavestateVersion, ucheck); error = true; - } else if (ucheck < GBA_SAVESTATE_MAGIC + GBA_SAVESTATE_VERSION) { - mLOG(GBA_STATE, WARN, "Old savestate: expected %08X, got %08X, continuing anyway", GBA_SAVESTATE_MAGIC + GBA_SAVESTATE_VERSION, ucheck); + } else if (ucheck < GBASavestateMagic + GBASavestateVersion) { + mLOG(GBA_STATE, WARN, "Old savestate: expected %08X, got %08X, continuing anyway", GBASavestateMagic + GBASavestateVersion, ucheck); } LOAD_32(ucheck, 0, &state->biosChecksum); if (ucheck != gba->biosChecksum) { diff --git a/src/gba/sio/lockstep.c b/src/gba/sio/lockstep.c index a2ecfc5b5..6e4f1f31d 100644 --- a/src/gba/sio/lockstep.c +++ b/src/gba/sio/lockstep.c @@ -149,11 +149,7 @@ bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver) { // Flush ongoing transfer if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { - int oldWhen = node->event.when; - - mTimingDeschedule(&driver->p->p->timing, &node->event); - mTimingSchedule(&driver->p->p->timing, &node->event, 0); - node->eventDiff -= oldWhen - node->event.when; + node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); mTimingDeschedule(&driver->p->p->timing, &node->event); } @@ -190,15 +186,11 @@ static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); ATOMIC_STORE(node->p->d.transferCycles, GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][node->p->d.attached - 1]); - bool scheduled = mTimingIsScheduled(&driver->p->p->timing, &node->event); - int oldWhen = node->event.when; - - mTimingDeschedule(&driver->p->p->timing, &node->event); - mTimingSchedule(&driver->p->p->timing, &node->event, 0); - - if (scheduled) { - node->eventDiff -= oldWhen - node->event.when; + if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { + node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); + mTimingDeschedule(&driver->p->p->timing, &node->event); } + mTimingSchedule(&driver->p->p->timing, &node->event, 0); } else { value &= ~0x0080; } @@ -443,14 +435,13 @@ static uint32_t _slaveUpdate(struct GBASIOLockstepNode* node) { static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) { struct GBASIOLockstepNode* node = user; mLockstepLock(&node->p->d); - if (node->p->d.attached < 2) { - mLockstepUnlock(&node->p->d); - return; - } + int32_t cycles = 0; node->nextEvent -= cyclesLate; node->eventDiff += cyclesLate; - if (node->nextEvent <= 0) { + if (node->p->d.attached < 2) { + cycles = GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][0]; + } else if (node->nextEvent <= 0) { if (!node->id) { cycles = _masterUpdate(node); } else { diff --git a/src/platform/opengl/gl.c b/src/platform/opengl/gl.c index d270f22b0..2e2e580c7 100644 --- a/src/platform/opengl/gl.c +++ b/src/platform/opengl/gl.c @@ -88,19 +88,11 @@ static void mGLContextResized(struct VideoBackend* v, unsigned w, unsigned h) { unsigned drawW = w; unsigned drawH = h; if (v->lockAspectRatio) { - if (w * v->height > h * v->width) { - drawW = h * v->width / v->height; - } else if (w * v->height < h * v->width) { - drawH = w * v->height / v->width; - } + lockAspectRatioUInt(v->width, v->height, &drawW, &drawH); } if (v->lockIntegerScaling) { - if (drawW >= v->width) { - drawW -= drawW % v->width; - } - if (drawH >= v->height) { - drawH -= drawH % v->height; - } + lockIntegerRatioUInt(v->width, &drawW); + lockIntegerRatioUInt(v->height, &drawH); } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index a8052cab1..d9f6705e5 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -221,19 +221,11 @@ static void mGLES2ContextResized(struct VideoBackend* v, unsigned w, unsigned h) unsigned drawW = w; unsigned drawH = h; if (v->lockAspectRatio) { - if (w * v->height > h * v->width) { - drawW = h * v->width / v->height; - } else if (w * v->height < h * v->width) { - drawH = w * v->height / v->width; - } + lockAspectRatioUInt(v->width, v->height, &drawW, &drawH); } if (v->lockIntegerScaling) { - if (drawW >= v->width) { - drawW -= drawW % v->width; - } - if (drawH >= v->height) { - drawH -= drawH % v->height; - } + lockIntegerRatioUInt(v->width, &drawW); + lockIntegerRatioUInt(v->height, &drawH); } size_t n; for (n = 0; n < context->nShaders; ++n) { diff --git a/src/platform/qt/AboutScreen.cpp b/src/platform/qt/AboutScreen.cpp index 7c3ecd1ef..b1c1716ce 100644 --- a/src/platform/qt/AboutScreen.cpp +++ b/src/platform/qt/AboutScreen.cpp @@ -71,4 +71,10 @@ AboutScreen::AboutScreen(QWidget* parent) patrons.replace("{patrons}", patronList.join(" • ")); m_ui.patrons->setText(patrons); } + + { + QString copyright = m_ui.copyright->text(); + copyright.replace("{year}", tr("2021")); + m_ui.copyright->setText(copyright); + } } diff --git a/src/platform/qt/AboutScreen.ui b/src/platform/qt/AboutScreen.ui index 4a500912c..c49e77b36 100644 --- a/src/platform/qt/AboutScreen.ui +++ b/src/platform/qt/AboutScreen.ui @@ -83,7 +83,7 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. diff --git a/src/platform/qt/AssetInfo.cpp b/src/platform/qt/AssetInfo.cpp index aaab59a42..22f1a464e 100644 --- a/src/platform/qt/AssetInfo.cpp +++ b/src/platform/qt/AssetInfo.cpp @@ -20,7 +20,7 @@ void AssetInfo::addCustomProperty(const QString& id, const QString& visibleName) QHBoxLayout* newLayout = new QHBoxLayout; newLayout->addWidget(new QLabel(visibleName)); QLabel* value = new QLabel; - value->setFont(GBAApp::monospaceFont()); + value->setFont(GBAApp::app()->monospaceFont()); value->setAlignment(Qt::AlignRight); newLayout->addWidget(value); m_customProperties[id] = value; diff --git a/src/platform/qt/AssetTile.cpp b/src/platform/qt/AssetTile.cpp index cfc9ea56f..d7bc30c14 100644 --- a/src/platform/qt/AssetTile.cpp +++ b/src/platform/qt/AssetTile.cpp @@ -31,7 +31,7 @@ AssetTile::AssetTile(QWidget* parent) connect(m_ui.preview, &Swatch::indexPressed, this, &AssetTile::selectColor); - const QFont font = GBAApp::monospaceFont(); + const QFont font = GBAApp::app()->monospaceFont(); m_ui.tileId->setFont(font); m_ui.paletteId->setFont(font); diff --git a/src/platform/qt/AudioDevice.cpp b/src/platform/qt/AudioDevice.cpp index af6bc6e01..9baf12712 100644 --- a/src/platform/qt/AudioDevice.cpp +++ b/src/platform/qt/AudioDevice.cpp @@ -40,20 +40,18 @@ void AudioDevice::setInput(mCoreThread* input) { } qint64 AudioDevice::readData(char* data, qint64 maxSize) { - if (maxSize > 0xFFFFFFFFLL) { - maxSize = 0xFFFFFFFFLL; - } - if (!m_context->core) { LOG(QT, WARN) << tr("Audio device is missing its core"); return 0; } + maxSize /= sizeof(GBAStereoSample); mCoreSyncLockAudio(&m_context->impl->sync); - int available = blip_samples_avail(m_context->core->getAudioChannel(m_context->core, 0)); - if (available > maxSize / sizeof(GBAStereoSample)) { - available = maxSize / sizeof(GBAStereoSample); - } + int available = std::min({ + blip_samples_avail(m_context->core->getAudioChannel(m_context->core, 0)), + maxSize, + std::numeric_limits::max() + }); blip_read_samples(m_context->core->getAudioChannel(m_context->core, 0), &reinterpret_cast(data)->left, available, true); blip_read_samples(m_context->core->getAudioChannel(m_context->core, 1), &reinterpret_cast(data)->right, available, true); mCoreSyncConsumeAudio(&m_context->impl->sync); diff --git a/src/platform/qt/AudioProcessorSDL.cpp b/src/platform/qt/AudioProcessorSDL.cpp index 8682ded58..bf0a5dbdd 100644 --- a/src/platform/qt/AudioProcessorSDL.cpp +++ b/src/platform/qt/AudioProcessorSDL.cpp @@ -52,7 +52,7 @@ void AudioProcessorSDL::pause() { void AudioProcessorSDL::setBufferSamples(int samples) { AudioProcessor::setBufferSamples(samples); - if (m_audio.samples != samples) { + if (m_audio.samples != static_cast(samples)) { m_audio.samples = samples; if (m_audio.core) { mSDLDeinitAudio(&m_audio); diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 6fb3f7fda..8641ed557 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -101,6 +101,7 @@ set(SOURCE_FILES ReportView.cpp ROMInfo.cpp RotatedHeaderView.cpp + SaveConverter.cpp SavestateButton.cpp SensorView.cpp SettingsView.cpp @@ -145,6 +146,7 @@ set(UI_FILES PrinterView.ui ReportView.ui ROMInfo.ui + SaveConverter.ui SensorView.ui SettingsView.ui ShaderSelector.ui diff --git a/src/platform/qt/CheatsModel.cpp b/src/platform/qt/CheatsModel.cpp index 419e3cc26..3694424d8 100644 --- a/src/platform/qt/CheatsModel.cpp +++ b/src/platform/qt/CheatsModel.cpp @@ -20,7 +20,7 @@ CheatsModel::CheatsModel(mCheatDevice* device, QObject* parent) : QAbstractItemModel(parent) , m_device(device) { - m_font = GBAApp::monospaceFont(); + m_font = GBAApp::app()->monospaceFont(); } QVariant CheatsModel::data(const QModelIndex& index, int role) const { diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp index dd2464e4b..74861027d 100644 --- a/src/platform/qt/ConfigController.cpp +++ b/src/platform/qt/ConfigController.cpp @@ -23,7 +23,7 @@ ConfigOption::ConfigOption(const QString& name, QObject* parent) void ConfigOption::connect(std::function slot, QObject* parent) { m_slots[parent] = slot; - QObject::connect(parent, &QObject::destroyed, [this, slot, parent]() { + QObject::connect(parent, &QObject::destroyed, this, [this, parent]() { m_slots.remove(parent); }); } @@ -37,10 +37,10 @@ Action* ConfigOption::addValue(const QString& text, const QVariant& value, Actio if (actions) { action = actions->addAction(text, name, function, menu); } else { - action = new Action(function, name, text); + action = new Action(function, name, text, this); } action->setExclusive(); - QObject::connect(action, &QObject::destroyed, [this, action, value]() { + QObject::connect(action, &QObject::destroyed, this, [this, action, value]() { m_actions.removeAll(std::make_pair(action, value)); }); m_actions.append(std::make_pair(action, value)); @@ -59,10 +59,10 @@ Action* ConfigOption::addBoolean(const QString& text, ActionMapper* actions, con if (actions) { action = actions->addBooleanAction(text, m_name, function, menu); } else { - action = new Action(function, m_name, text); + action = new Action(function, m_name, text, this); } - QObject::connect(action, &QObject::destroyed, [this, action]() { + QObject::connect(action, &QObject::destroyed, this, [this, action]() { m_actions.removeAll(std::make_pair(action, 1)); }); m_actions.append(std::make_pair(action, 1)); @@ -103,7 +103,7 @@ ConfigController::ConfigController(QObject* parent) QString fileName = configDir(); fileName.append(QDir::separator()); fileName.append("qt.ini"); - m_settings = new QSettings(fileName, QSettings::IniFormat, this); + m_settings = std::make_unique(fileName, QSettings::IniFormat); mCoreConfigInit(&m_config, PORT); @@ -150,7 +150,7 @@ ConfigOption* ConfigController::addOption(const char* key) { } ConfigOption* newOption = new ConfigOption(optionName, this); m_optionSet[optionName] = newOption; - connect(newOption, &ConfigOption::valueChanged, [this, key](const QVariant& value) { + connect(newOption, &ConfigOption::valueChanged, this, [this, key](const QVariant& value) { setOption(key, value); }); return newOption; @@ -272,6 +272,9 @@ void ConfigController::setMRU(const QList& mru) { break; } } + for (; i < MRU_LIST_SIZE; ++i) { + m_settings->remove(QString::number(i)); + } m_settings->endGroup(); } @@ -289,12 +292,11 @@ void ConfigController::makePortable() { QString fileName(configDir()); fileName.append(QDir::separator()); fileName.append("qt.ini"); - QSettings* settings2 = new QSettings(fileName, QSettings::IniFormat, this); + auto settings2 = std::make_unique(fileName, QSettings::IniFormat); for (const auto& key : m_settings->allKeys()) { settings2->setValue(key, m_settings->value(key)); } - delete m_settings; - m_settings = settings2; + m_settings = std::move(settings2); } bool ConfigController::isPortable() { diff --git a/src/platform/qt/ConfigController.h b/src/platform/qt/ConfigController.h index 7f2943fad..df7cb816d 100644 --- a/src/platform/qt/ConfigController.h +++ b/src/platform/qt/ConfigController.h @@ -7,12 +7,13 @@ #include "Override.h" -#include +#include #include #include #include #include +#include #include #include @@ -53,7 +54,7 @@ signals: void valueChanged(const QVariant& value); private: - QMap> m_slots; + QHash> m_slots; QList> m_actions; QString m_name; }; @@ -110,8 +111,8 @@ private: mCoreConfig m_config; mCoreOptions m_opts{}; - QMap m_optionSet; - QSettings* m_settings; + QHash m_optionSet; + std::unique_ptr m_settings; static QString s_configDir; }; diff --git a/src/platform/qt/CoreManager.cpp b/src/platform/qt/CoreManager.cpp index 758eaaca1..98403216a 100644 --- a/src/platform/qt/CoreManager.cpp +++ b/src/platform/qt/CoreManager.cpp @@ -14,9 +14,6 @@ #ifdef M_CORE_GBA #include #endif -#ifdef M_CORE_GB -#include -#endif #include #include @@ -31,57 +28,6 @@ void CoreManager::setMultiplayerController(MultiplayerController* multiplayer) { m_multiplayer = multiplayer; } -QByteArray CoreManager::getExtdata(const QString& filename, mStateExtdataTag extdataType) { - VFileDevice vf(filename, QIODevice::ReadOnly); - - if (!vf.isOpen()) { - return {}; - } - - mStateExtdata extdata; - mStateExtdataInit(&extdata); - - QByteArray bytes; - auto extract = [&bytes, &extdata, &vf, extdataType](mCore* core) -> bool { - if (mCoreExtractExtdata(core, vf, &extdata)) { - mStateExtdataItem extitem; - if (!mStateExtdataGet(&extdata, extdataType, &extitem)) { - return false; - } - if (extitem.size) { - bytes = QByteArray::fromRawData(static_cast(extitem.data), extitem.size); - } - return true; - } - return false; - }; - - bool done = false; - struct mCore* core = nullptr; -#ifdef USE_PNG - done = extract(nullptr); -#endif -#ifdef M_CORE_GBA - if (!done) { - core = GBACoreCreate(); - core->init(core); - done = extract(core); - core->deinit(core); - } -#endif -#ifdef M_CORE_GB - if (!done) { - core = GBCoreCreate(); - core->init(core); - done = extract(core); - core->deinit(core); - } -#endif - - mStateExtdataDeinit(&extdata); - return bytes; -} - CoreController* CoreManager::loadGame(const QString& path) { QFileInfo info(path); if (!info.isReadable()) { diff --git a/src/platform/qt/CoreManager.h b/src/platform/qt/CoreManager.h index 3a31288b9..da7460f22 100644 --- a/src/platform/qt/CoreManager.h +++ b/src/platform/qt/CoreManager.h @@ -9,8 +9,6 @@ #include #include -#include - struct mCoreConfig; struct VFile; @@ -27,8 +25,6 @@ public: void setMultiplayerController(MultiplayerController*); void setPreload(bool preload) { m_preload = preload; } - static QByteArray getExtdata(const QString& filename, mStateExtdataTag extdataType); - public slots: CoreController* loadGame(const QString& path); CoreController* loadGame(VFile* vf, const QString& path, const QString& base); diff --git a/src/platform/qt/DisplayQt.cpp b/src/platform/qt/DisplayQt.cpp index 9be1a3674..42175fb2a 100644 --- a/src/platform/qt/DisplayQt.cpp +++ b/src/platform/qt/DisplayQt.cpp @@ -6,6 +6,7 @@ #include "DisplayQt.h" #include "CoreController.h" +#include "utils.h" #include @@ -98,26 +99,7 @@ void DisplayQt::paintEvent(QPaintEvent*) { if (isFiltered()) { painter.setRenderHint(QPainter::SmoothPixmapTransform); } - // TODO: Refactor this code out (since it's copied in like 3 places) - QSize s = size(); - QSize ds = viewportSize(); - if (isAspectRatioLocked()) { - if (s.width() * m_height > s.height() * m_width) { - ds.setWidth(s.height() * m_width / m_height); - } else if (s.width() * m_height < s.height() * m_width) { - ds.setHeight(s.width() * m_height / m_width); - } - } - if (isIntegerScalingLocked()) { - if (ds.width() >= m_width) { - ds.setWidth(ds.width() - ds.width() % m_width); - } - if (ds.height() >= m_height) { - ds.setHeight(ds.height() - ds.height() % m_height); - } - } - QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2); - QRect full(origin, ds); + QRect full(clampSize(QSize(m_width, m_height), size(), isAspectRatioLocked(), isIntegerScalingLocked())); if (hasInterframeBlending()) { painter.drawImage(full, m_oldBacking, QRect(0, 0, m_width, m_height)); diff --git a/src/platform/qt/FrameView.cpp b/src/platform/qt/FrameView.cpp index 6635dabfe..530e8a2e5 100644 --- a/src/platform/qt/FrameView.cpp +++ b/src/platform/qt/FrameView.cpp @@ -83,7 +83,12 @@ FrameView::FrameView(std::shared_ptr controller, QWidget* parent FrameView::~FrameView() { QMutexLocker locker(&m_mutex); *m_callbackLocker = false; + + if (m_nextFrame) { + m_controller->endVideoLog(true); + } if (m_vl) { + mCoreConfigDeinit(&m_vl->config); m_vl->deinit(m_vl); } } @@ -517,6 +522,9 @@ bool FrameView::eventFilter(QObject*, QEvent* event) { void FrameView::refreshVl() { QMutexLocker locker(&m_mutex); + if (m_currentFrame) { + m_currentFrame->close(m_currentFrame); + } m_currentFrame = m_nextFrame; m_nextFrame = VFileDevice::openMemory(); if (m_currentFrame) { @@ -536,6 +544,7 @@ void FrameView::newVl() { return; } if (m_vl) { + mCoreConfigDeinit(&m_vl->config); m_vl->deinit(m_vl); } m_vl = mCoreFindVF(m_currentFrame); diff --git a/src/platform/qt/GBAApp.cpp b/src/platform/qt/GBAApp.cpp index f6a0f96e8..19b6010fd 100644 --- a/src/platform/qt/GBAApp.cpp +++ b/src/platform/qt/GBAApp.cpp @@ -36,14 +36,12 @@ static GBAApp* g_app = nullptr; mLOG_DEFINE_CATEGORY(QT, "Qt", "platform.qt"); -QFont GBAApp::s_monospace; - GBAApp::GBAApp(int& argc, char* argv[], ConfigController* config) : QApplication(argc, argv) , m_configController(config) + , m_monospace(QFontDatabase::systemFont(QFontDatabase::FixedFont)) { g_app = this; - s_monospace = QFontDatabase::systemFont(QFontDatabase::FixedFont); #ifdef BUILD_SDL SDL_Init(SDL_INIT_NOPARACHUTE); diff --git a/src/platform/qt/GBAApp.h b/src/platform/qt/GBAApp.h index 8f2f1dd6f..84779fca0 100644 --- a/src/platform/qt/GBAApp.h +++ b/src/platform/qt/GBAApp.h @@ -57,7 +57,7 @@ public: static QString dataDir(); - static QFont monospaceFont() { return s_monospace; } + QFont monospaceFont() { return m_monospace; } QList windows() { return m_windows; } Window* newWindow(); @@ -114,7 +114,7 @@ private: QThreadPool m_workerThreads; qint64 m_nextJob = 1; - static QFont s_monospace; + QFont m_monospace; NoIntroDB* m_db = nullptr; }; diff --git a/src/platform/qt/IOViewer.cpp b/src/platform/qt/IOViewer.cpp index 3729df2f2..07f5438fb 100644 --- a/src/platform/qt/IOViewer.cpp +++ b/src/platform/qt/IOViewer.cpp @@ -1594,7 +1594,7 @@ IOViewer::IOViewer(std::shared_ptr controller, QWidget* parent) m_ui.regSelect->addItem("0x" + QString("%1: %2").arg((i << m_width) + m_base, 4, 16, QChar('0')).toUpper().arg(reg), i << m_width); } - const QFont font = GBAApp::monospaceFont(); + const QFont font = GBAApp::app()->monospaceFont(); m_ui.regValue->setFont(font); connect(m_ui.buttonBox, &QDialogButtonBox::clicked, this, &IOViewer::buttonPressed); diff --git a/src/platform/qt/LoadSaveState.cpp b/src/platform/qt/LoadSaveState.cpp index 78c58c2d4..4bcae6175 100644 --- a/src/platform/qt/LoadSaveState.cpp +++ b/src/platform/qt/LoadSaveState.cpp @@ -200,7 +200,7 @@ void LoadSaveState::loadState(int slot) { unsigned width, height; thread->core->desiredVideoDimensions(thread->core, &width, &height); mStateExtdataItem item; - if (mStateExtdataGet(&extdata, EXTDATA_SCREENSHOT, &item) && item.size >= width * height * 4) { + if (mStateExtdataGet(&extdata, EXTDATA_SCREENSHOT, &item) && item.size >= static_cast(width * height * 4)) { stateImage = QImage((uchar*) item.data, width, height, QImage::Format_ARGB32).rgbSwapped(); } diff --git a/src/platform/qt/MapView.cpp b/src/platform/qt/MapView.cpp index ec89a2dfc..be709a8f9 100644 --- a/src/platform/qt/MapView.cpp +++ b/src/platform/qt/MapView.cpp @@ -109,10 +109,10 @@ MapView::MapView(std::shared_ptr controller, QWidget* parent) } void MapView::selectMap(int map) { - if (map >= mMapCacheSetSize(&m_cacheSet->maps)) { + if (map == m_map || map < 0) { return; } - if (map == m_map) { + if (static_cast(map) >= mMapCacheSetSize(&m_cacheSet->maps)) { return; } m_map = map; diff --git a/src/platform/qt/MemoryModel.cpp b/src/platform/qt/MemoryModel.cpp index ab21408d0..d0f3df1f6 100644 --- a/src/platform/qt/MemoryModel.cpp +++ b/src/platform/qt/MemoryModel.cpp @@ -9,6 +9,7 @@ #include "CoreController.h" #include "LogController.h" #include "VFileDevice.h" +#include "utils.h" #include #include @@ -27,7 +28,7 @@ using namespace QGBA; MemoryModel::MemoryModel(QWidget* parent) : QAbstractScrollArea(parent) { - m_font = GBAApp::monospaceFont(); + m_font = GBAApp::app()->monospaceFont(); #ifdef Q_OS_MAC m_font.setPointSize(12); #else @@ -346,7 +347,7 @@ void MemoryModel::paintEvent(QPaintEvent*) { int height = (viewport()->size().height() - m_cellHeight) / m_cellHeight; for (int y = 0; y < height; ++y) { int yp = m_cellHeight * y + m_margins.top(); - if ((y + m_top) * 16 >= m_size) { + if ((y + m_top) * 16U >= m_size) { break; } QString data; @@ -628,11 +629,7 @@ void MemoryModel::keyPressEvent(QKeyEvent* event) { } void MemoryModel::boundsCheck() { - if (m_top < 0) { - m_top = 0; - } else if (m_top > (m_size >> 4) + 1 - viewport()->size().height() / m_cellHeight) { - m_top = (m_size >> 4) + 1 - viewport()->size().height() / m_cellHeight; - } + m_top = clamp(m_top, 0, static_cast(m_size >> 4) + 1 - viewport()->size().height() / m_cellHeight); } bool MemoryModel::isInSelection(uint32_t address) { @@ -676,34 +673,35 @@ void MemoryModel::adjustCursor(int adjust, bool shift) { } int cursorPosition = m_top; if (shift) { + uint32_t absolute; if (m_selectionAnchor == m_selection.first) { if (adjust < 0 && m_base - adjust > m_selection.second) { - adjust = m_base - m_selection.second + m_align; + absolute = m_base - m_selection.second + m_align; } else if (adjust > 0 && m_selection.second + adjust >= m_base + m_size) { - adjust = m_base + m_size - m_selection.second; + absolute = m_base + m_size - m_selection.second; } - adjust += m_selection.second; - if (adjust <= m_selection.first) { + absolute += m_selection.second; + if (absolute <= m_selection.first) { m_selection.second = m_selection.first + m_align; - m_selection.first = adjust - m_align; + m_selection.first = absolute - m_align; cursorPosition = m_selection.first; } else { - m_selection.second = adjust; + m_selection.second = absolute; cursorPosition = m_selection.second - m_align; } } else { if (adjust < 0 && m_base - adjust > m_selection.first) { - adjust = m_base - m_selection.first; + absolute = m_base - m_selection.first; } else if (adjust > 0 && m_selection.first + adjust >= m_base + m_size) { - adjust = m_base + m_size - m_selection.first - m_align; + absolute = m_base + m_size - m_selection.first - m_align; } - adjust += m_selection.first; - if (adjust >= m_selection.second) { + absolute += m_selection.first; + if (absolute >= m_selection.second) { m_selection.first = m_selection.second - m_align; - m_selection.second = adjust + m_align; - cursorPosition = adjust; + m_selection.second = absolute + m_align; + cursorPosition = absolute; } else { - m_selection.first = adjust; + m_selection.first = absolute; cursorPosition = m_selection.first; } } diff --git a/src/platform/qt/MemoryView.cpp b/src/platform/qt/MemoryView.cpp index cf111c9c3..c740b4dca 100644 --- a/src/platform/qt/MemoryView.cpp +++ b/src/platform/qt/MemoryView.cpp @@ -256,7 +256,7 @@ void MemoryView::updateSelection(uint32_t start, uint32_t end) { } void MemoryView::updateStatus() { - int align = m_ui.hexfield->alignment(); + unsigned align = m_ui.hexfield->alignment(); mCore* core = m_controller->thread()->core; QByteArray selection(m_ui.hexfield->serialize()); QString text(m_ui.hexfield->decodeText(selection)); diff --git a/src/platform/qt/MessagePainter.cpp b/src/platform/qt/MessagePainter.cpp index fecff4917..15ab748aa 100644 --- a/src/platform/qt/MessagePainter.cpp +++ b/src/platform/qt/MessagePainter.cpp @@ -16,7 +16,7 @@ using namespace QGBA; MessagePainter::MessagePainter(QObject* parent) : QObject(parent) { - m_messageFont = GBAApp::monospaceFont(); + m_messageFont = GBAApp::app()->monospaceFont(); m_messageFont.setPixelSize(13); connect(&m_messageTimer, &QTimer::timeout, this, &MessagePainter::clearMessage); m_messageTimer.setSingleShot(true); diff --git a/src/platform/qt/ObjView.cpp b/src/platform/qt/ObjView.cpp index 1dfc70935..39e38892a 100644 --- a/src/platform/qt/ObjView.cpp +++ b/src/platform/qt/ObjView.cpp @@ -33,7 +33,7 @@ ObjView::ObjView(std::shared_ptr controller, QWidget* parent) m_ui.setupUi(this); m_ui.tile->setController(controller); - const QFont font = GBAApp::monospaceFont(); + const QFont font = GBAApp::app()->monospaceFont(); m_ui.x->setFont(font); m_ui.y->setFont(font); @@ -133,8 +133,8 @@ void ObjView::updateTilesGBA(bool force) { mTileCache* tileCache = mTileCacheSetGetPointer(&m_cacheSet->tiles, newInfo.paletteSet); int i = 0; - for (int y = 0; y < newInfo.height; ++y) { - for (int x = 0; x < newInfo.width; ++x, ++i, ++tile, ++tileBase) { + for (unsigned y = 0; y < newInfo.height; ++y) { + for (unsigned x = 0; x < newInfo.width; ++x, ++i, ++tile, ++tileBase) { const color_t* data = mTileCacheGetTileIfDirty(tileCache, &m_tileStatus[16 * tileBase], tile, newInfo.paletteId); if (data) { m_ui.tiles->setTile(i, data); @@ -224,7 +224,7 @@ void ObjView::updateTilesGB(bool force) { int i = 0; m_ui.tile->setPalette(newInfo.paletteId); - for (int y = 0; y < newInfo.height; ++y, ++i) { + for (unsigned y = 0; y < newInfo.height; ++y, ++i) { unsigned t = tile + i; const color_t* data = mTileCacheGetTileIfDirty(tileCache, &m_tileStatus[8 * t], t, newInfo.paletteId); if (data) { diff --git a/src/platform/qt/PaletteView.cpp b/src/platform/qt/PaletteView.cpp index f72507ea6..60b67a90a 100644 --- a/src/platform/qt/PaletteView.cpp +++ b/src/platform/qt/PaletteView.cpp @@ -47,7 +47,7 @@ PaletteView::PaletteView(std::shared_ptr controller, QWidget* pa m_ui.selected->setDimensions(QSize(1, 1)); updatePalette(); - const QFont font = GBAApp::monospaceFont(); + const QFont font = GBAApp::app()->monospaceFont(); m_ui.hexcode->setFont(font); m_ui.value->setFont(font); @@ -69,7 +69,7 @@ void PaletteView::updatePalette() { return; } const uint16_t* palette; - size_t count; + int count; switch (m_controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: diff --git a/src/platform/qt/RegisterView.cpp b/src/platform/qt/RegisterView.cpp index e712bf95a..49b44870b 100644 --- a/src/platform/qt/RegisterView.cpp +++ b/src/platform/qt/RegisterView.cpp @@ -74,7 +74,7 @@ RegisterView::RegisterView(std::shared_ptr controller, QWidget* void RegisterView::addRegisters(const QStringList& names) { QFormLayout* form = static_cast(layout()); - const QFont font = GBAApp::monospaceFont(); + const QFont font = GBAApp::app()->monospaceFont(); for (const auto& reg : names) { QLabel* value = new QLabel; value->setTextInteractionFlags(Qt::TextSelectableByMouse); diff --git a/src/platform/qt/ReportView.cpp b/src/platform/qt/ReportView.cpp index accc5d9e6..b33fd2ea6 100644 --- a/src/platform/qt/ReportView.cpp +++ b/src/platform/qt/ReportView.cpp @@ -12,7 +12,9 @@ #include #include +#include #include +#include #include #include "CoreController.h" @@ -37,8 +39,43 @@ #include #endif +#ifdef USE_EDITLINE +#include +#endif + +#ifdef USE_FFMPEG +#include +#include +#include +#include +#include +#ifdef USE_LIBAVRESAMPLE +#include +#endif +#ifdef USE_LIBSWRESAMPLE +#include +#endif +#endif + +#ifdef USE_LIBZIP +#include +#endif + +#ifdef USE_LZMA +#include <7zVersion.h> +#endif + +#ifdef BUILD_SDL +#include +#endif + #ifdef USE_SQLITE3 #include "feature/sqlite3/no-intro.h" +#include +#endif + +#ifdef USE_ZLIB +#include #endif using namespace QGBA; @@ -84,6 +121,72 @@ void ReportView::generateReport() { swReport << QString("Build architecture: %1").arg(QSysInfo::buildCpuArchitecture()); swReport << QString("Run architecture: %1").arg(QSysInfo::currentCpuArchitecture()); swReport << QString("Qt version: %1").arg(QLatin1String(qVersion())); +#ifdef USE_FFMPEG + QStringList libavVers; + libavVers << QLatin1String(LIBAVCODEC_IDENT); + libavVers << QLatin1String(LIBAVFILTER_IDENT); + libavVers << QLatin1String(LIBAVFORMAT_IDENT); +#ifdef USE_LIBAVRESAMPLE + libavVers << QLatin1String(LIBAVRESAMPLE_IDENT); +#endif + libavVers << QLatin1String(LIBAVUTIL_IDENT); +#ifdef USE_LIBSWRESAMPLE + libavVers << QLatin1String(LIBSWRESAMPLE_IDENT); +#endif + libavVers << QLatin1String(LIBSWSCALE_IDENT); +#ifdef USE_LIBAV + swReport << QString("Libav versions: %1.%2").arg(libavVers.join(", ")); +#else + swReport << QString("FFmpeg versions: %1.%2").arg(libavVers.join(", ")); +#endif +#else + swReport << QString("FFmpeg not linked"); +#endif +#ifdef USE_EDITLINE + swReport << QString("libedit version: %1.%2").arg(LIBEDIT_MAJOR).arg(LIBEDIT_MINOR); +#else + swReport << QString("libedit not linked"); +#endif +#ifdef USE_ELF + swReport << QString("libelf linked"); +#else + swReport << QString("libelf not linked"); +#endif +#ifdef USE_PNG + swReport << QString("libpng version: %1").arg(QLatin1String(PNG_LIBPNG_VER_STRING)); +#else + swReport << QString("libpng not linked"); +#endif +#ifdef USE_LIBZIP + swReport << QString("libzip version: %1").arg(QLatin1String(LIBZIP_VERSION)); +#else + swReport << QString("libzip not linked"); +#endif +#ifdef USE_LZMA + swReport << QString("libLZMA version: %1").arg(QLatin1String(MY_VERSION_NUMBERS)); +#else + swReport << QString("libLZMA not linked"); +#endif +#ifdef USE_MINIZIP + swReport << QString("minizip linked"); +#else + swReport << QString("minizip not linked"); +#endif +#ifdef BUILD_SDL + swReport << QString("SDL version: %1.%2.%3").arg(SDL_MAJOR_VERSION).arg(SDL_MINOR_VERSION).arg(SDL_PATCHLEVEL); +#else + swReport << QString("SDL not linked"); +#endif +#ifdef USE_SQLITE3 + swReport << QString("SQLite3 version: %1").arg(QLatin1String(SQLITE_VERSION)); +#else + swReport << QString("SQLite3 not linked"); +#endif +#ifdef USE_ZLIB + swReport << QString("zlib version: %1").arg(QLatin1String(ZLIB_VERSION)); +#else + swReport << QString("zlib not linked"); +#endif addReport(QString("System info"), swReport.join('\n')); QStringList hwReport; @@ -209,6 +312,7 @@ void ReportView::generateReport() { } void ReportView::save() { +#if defined(USE_LIBZIP) || defined(USE_MINIZIP) QString filename = GBAApp::app()->getSaveFileName(this, tr("Bug report archive"), tr("ZIP archive (*.zip)")); if (filename.isNull()) { return; @@ -228,6 +332,7 @@ void ReportView::save() { vf.close(); } zip->close(zip); +#endif } void ReportView::setShownReport(const QString& filename) { @@ -243,7 +348,9 @@ void ReportView::rebuildModel() { } m_ui.fileList->addItem(item); } +#if defined(USE_LIBZIP) || defined(USE_MINIZIP) m_ui.save->setEnabled(true); +#endif m_ui.fileList->setEnabled(true); m_ui.fileView->setEnabled(true); m_ui.openList->setEnabled(true); diff --git a/src/platform/qt/SaveConverter.cpp b/src/platform/qt/SaveConverter.cpp new file mode 100644 index 000000000..3ccc952d6 --- /dev/null +++ b/src/platform/qt/SaveConverter.cpp @@ -0,0 +1,658 @@ +/* Copyright (c) 2013-2021 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "SaveConverter.h" + +#include + +#include "GBAApp.h" +#include "LogController.h" +#include "VFileDevice.h" +#include "utils.h" + +#ifdef M_CORE_GBA +#include +#include +#endif +#ifdef M_CORE_GB +#include +#include +#endif + +#include +#include + +using namespace QGBA; + +SaveConverter::SaveConverter(std::shared_ptr controller, QWidget* parent) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) + , m_controller(controller) +{ + m_ui.setupUi(this); + + connect(m_ui.inputFile, &QLineEdit::textEdited, this, &SaveConverter::refreshInputTypes); + connect(m_ui.inputBrowse, &QAbstractButton::clicked, this, [this]() { + // TODO: Add gameshark saves here too + QStringList formats{"*.sav", "*.sgm", "*.ss0", "*.ss1", "*.ss2", "*.ss3", "*.ss4", "*.ss5", "*.ss6", "*.ss7", "*.ss8", "*.ss9"}; + QString filter = tr("Save games and save states (%1)").arg(formats.join(QChar(' '))); + QString filename = GBAApp::app()->getOpenFileName(this, tr("Select save game or save state"), filter); + if (!filename.isEmpty()) { + m_ui.inputFile->setText(filename); + refreshInputTypes(); + } + }); + connect(m_ui.inputType, static_cast(&QComboBox::currentIndexChanged), this, &SaveConverter::refreshOutputTypes); + + connect(m_ui.outputFile, &QLineEdit::textEdited, this, &SaveConverter::checkCanConvert); + connect(m_ui.outputBrowse, &QAbstractButton::clicked, this, [this]() { + // TODO: Add gameshark saves here too + QStringList formats{"*.sav", "*.sgm"}; + QString filter = tr("Save games (%1)").arg(formats.join(QChar(' '))); + QString filename = GBAApp::app()->getSaveFileName(this, tr("Select save game"), filter); + if (!filename.isEmpty()) { + m_ui.outputFile->setText(filename); + checkCanConvert(); + } + }); + connect(m_ui.outputType, static_cast(&QComboBox::currentIndexChanged), this, &SaveConverter::checkCanConvert); + connect(this, &QDialog::accepted, this, &SaveConverter::convert); + + refreshInputTypes(); + m_ui.buttonBox->button(QDialogButtonBox::Save)->setDisabled(true); +} + +void SaveConverter::convert() { + if (m_validSaves.isEmpty() || m_validOutputs.isEmpty()) { + return; + } + const AnnotatedSave& input = m_validSaves[m_ui.inputType->currentIndex()]; + const AnnotatedSave& output = m_validOutputs[m_ui.outputType->currentIndex()]; + QByteArray converted = input.convertTo(output); + if (converted.isEmpty()) { + QMessageBox* failure = new QMessageBox(QMessageBox::Warning, tr("Conversion failed"), tr("Failed to convert the save game. This is probably a bug."), + QMessageBox::Ok, this, Qt::Sheet); + failure->setAttribute(Qt::WA_DeleteOnClose); + failure->show(); + return; + } + QFile out(m_ui.outputFile->text()); + out.open(QIODevice::WriteOnly | QIODevice::Truncate); + out.write(converted); + out.close(); +} + +void SaveConverter::refreshInputTypes() { + m_validSaves.clear(); + m_ui.inputType->clear(); + if (m_ui.inputFile->text().isEmpty()) { + m_ui.inputType->addItem(tr("No file selected")); + m_ui.inputType->setEnabled(false); + return; + } + + std::shared_ptr vf = std::make_shared(m_ui.inputFile->text(), QIODevice::ReadOnly); + if (!vf->isOpen()) { + m_ui.inputType->addItem(tr("Could not open file")); + m_ui.inputType->setEnabled(false); + return; + } + + detectFromSavestate(*vf); + detectFromSize(vf); + + for (const auto& save : m_validSaves) { + m_ui.inputType->addItem(save); + } + if (m_validSaves.count()) { + m_ui.inputType->setEnabled(true); + } else { + m_ui.inputType->addItem(tr("No valid formats found")); + m_ui.inputType->setEnabled(false); + } +} + +void SaveConverter::refreshOutputTypes() { + m_ui.outputType->clear(); + if (m_validSaves.isEmpty()) { + m_ui.outputType->addItem(tr("Please select a valid input file")); + m_ui.outputType->setEnabled(false); + return; + } + m_validOutputs = m_validSaves[m_ui.inputType->currentIndex()].possibleConversions(); + for (const auto& save : m_validOutputs) { + m_ui.outputType->addItem(save); + } + if (m_validOutputs.count()) { + m_ui.outputType->setEnabled(true); + } else { + m_ui.outputType->addItem(tr("No valid conversions found")); + m_ui.outputType->setEnabled(false); + } + checkCanConvert(); +} + +void SaveConverter::checkCanConvert() { + QAbstractButton* button = m_ui.buttonBox->button(QDialogButtonBox::Save); + if (m_ui.inputFile->text().isEmpty()) { + button->setEnabled(false); + return; + } + if (m_ui.outputFile->text().isEmpty()) { + button->setEnabled(false); + return; + } + if (!m_ui.inputType->isEnabled()) { + button->setEnabled(false); + return; + } + if (!m_ui.outputType->isEnabled()) { + button->setEnabled(false); + return; + } + button->setEnabled(true); +} + +void SaveConverter::detectFromSavestate(VFile* vf) { + mPlatform platform = getStatePlatform(vf); + if (platform == mPLATFORM_NONE) { + return; + } + + QByteArray extSavedata = getExtdata(vf, platform, EXTDATA_SAVEDATA); + if (!extSavedata.size()) { + return; + } + + QByteArray state = getState(vf, platform); + AnnotatedSave save{platform, std::make_shared(extSavedata)}; + switch (platform) { +#ifdef M_CORE_GBA + case mPLATFORM_GBA: + save.gba.type = static_cast(state.at(offsetof(GBASerializedState, savedata.type))); + if (save.gba.type == SAVEDATA_EEPROM || save.gba.type == SAVEDATA_EEPROM512) { + save.endianness = Endian::LITTLE; + } + break; +#endif +#ifdef M_CORE_GB + case mPLATFORM_GB: + // GB savestates don't store the MBC type...should probably fix that + save.gb.type = GB_MBC_AUTODETECT; + if (state.size() == 0x100) { + // MBC2 packed save + save.endianness = Endian::LITTLE; + save.gb.type = GB_MBC2; + } + break; +#endif + default: + break; + } + m_validSaves.append(save); +} + +void SaveConverter::detectFromSize(std::shared_ptr vf) { +#ifdef M_CORE_GBA + switch (vf->size()) { + case SIZE_CART_SRAM: + m_validSaves.append(AnnotatedSave{SAVEDATA_SRAM, vf}); + break; + case SIZE_CART_FLASH512: + m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH512, vf}); + break; + case SIZE_CART_FLASH1M: + m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH1M, vf}); + break; + case SIZE_CART_EEPROM: + m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, vf, Endian::LITTLE}); + m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, vf, Endian::BIG}); + break; + case SIZE_CART_EEPROM512: + m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, vf, Endian::LITTLE}); + m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, vf, Endian::BIG}); + break; + } +#endif + +#ifdef M_CORE_GB + switch (vf->size()) { + case 0x800: + case 0x82C: + case 0x830: + case 0x2000: + case 0x202C: + case 0x2030: + case 0x8000: + case 0x802C: + case 0x8030: + case 0x10000: + case 0x1002C: + case 0x10030: + case 0x20000: + case 0x2002C: + case 0x20030: + m_validSaves.append(AnnotatedSave{GB_MBC_AUTODETECT, vf}); + break; + case 0x100: + m_validSaves.append(AnnotatedSave{GB_MBC2, vf, Endian::LITTLE}); + m_validSaves.append(AnnotatedSave{GB_MBC2, vf, Endian::BIG}); + break; + case 0x200: + m_validSaves.append(AnnotatedSave{GB_MBC2, vf}); + break; + case GB_SIZE_MBC6_FLASH: // Flash only + case GB_SIZE_MBC6_FLASH + 0x8000: // Concatenated SRAM and flash + m_validSaves.append(AnnotatedSave{GB_MBC6, vf}); + break; + case 0x20: + m_validSaves.append(AnnotatedSave{GB_TAMA5, vf}); + break; + } +#endif +} + +mPlatform SaveConverter::getStatePlatform(VFile* vf) { + uint32_t magic; + void* state = nullptr; + struct mCore* core = nullptr; + mPlatform platform = mPLATFORM_NONE; +#ifdef M_CORE_GBA + if (platform == mPLATFORM_NONE) { + core = GBACoreCreate(); + core->init(core); + state = mCoreExtractState(core, vf, nullptr); + core->deinit(core); + if (state) { + LOAD_32LE(magic, 0, state); + if (magic - GBASavestateMagic <= GBASavestateVersion) { + platform = mPLATFORM_GBA; + } + mappedMemoryFree(state, core->stateSize(core)); + } + } +#endif +#ifdef M_CORE_GB + if (platform == mPLATFORM_NONE) { + core = GBCoreCreate(); + core->init(core); + state = mCoreExtractState(core, vf, nullptr); + core->deinit(core); + if (state) { + LOAD_32LE(magic, 0, state); + if (magic - GBSavestateMagic <= GBSavestateVersion) { + platform = mPLATFORM_GB; + } + mappedMemoryFree(state, core->stateSize(core)); + } + } +#endif + + return platform; +} + +QByteArray SaveConverter::getState(VFile* vf, mPlatform platform) { + QByteArray bytes; + struct mCore* core = mCoreCreate(platform); + core->init(core); + void* state = mCoreExtractState(core, vf, nullptr); + if (state) { + size_t size = core->stateSize(core); + bytes = QByteArray::fromRawData(static_cast(state), size); + bytes.data(); // Trigger a deep copy before we delete the backing + mappedMemoryFree(state, size); + } + core->deinit(core); + return bytes; +} + +QByteArray SaveConverter::getExtdata(VFile* vf, mPlatform platform, mStateExtdataTag extdataType) { + mStateExtdata extdata; + mStateExtdataInit(&extdata); + QByteArray bytes; + struct mCore* core = mCoreCreate(platform); + core->init(core); + if (mCoreExtractExtdata(core, vf, &extdata)) { + mStateExtdataItem extitem; + if (mStateExtdataGet(&extdata, extdataType, &extitem) && extitem.size) { + bytes = QByteArray::fromRawData(static_cast(extitem.data), extitem.size); + bytes.data(); // Trigger a deep copy before we delete the backing + } + } + core->deinit(core); + mStateExtdataDeinit(&extdata); + return bytes; +} + +SaveConverter::AnnotatedSave::AnnotatedSave() + : savestate(false) + , platform(mPLATFORM_NONE) + , size(0) + , backing() + , endianness(Endian::NONE) +{ +} + +SaveConverter::AnnotatedSave::AnnotatedSave(mPlatform platform, std::shared_ptr vf, Endian endianness) + : savestate(true) + , platform(platform) + , size(vf->size()) + , backing(vf) + , endianness(endianness) +{ +} + +#ifdef M_CORE_GBA +SaveConverter::AnnotatedSave::AnnotatedSave(SavedataType type, std::shared_ptr vf, Endian endianness) + : savestate(false) + , platform(mPLATFORM_GBA) + , size(vf->size()) + , backing(vf) + , endianness(endianness) + , gba({type}) +{ +} +#endif + +#ifdef M_CORE_GB +SaveConverter::AnnotatedSave::AnnotatedSave(GBMemoryBankControllerType type, std::shared_ptr vf, Endian endianness) + : savestate(false) + , platform(mPLATFORM_GB) + , size(vf->size()) + , backing(vf) + , endianness(endianness) + , gb({type}) +{ +} +#endif + +SaveConverter::AnnotatedSave SaveConverter::AnnotatedSave::asRaw() const { + AnnotatedSave raw; + raw.platform = platform; + raw.size = size; + raw.endianness = endianness; + switch (platform) { +#ifdef M_CORE_GBA + case mPLATFORM_GBA: + raw.gba = gba; + break; +#endif +#ifdef M_CORE_GB + case mPLATFORM_GB: + raw.gb = gb; + break; +#endif + default: + break; + } + return raw; +} + +SaveConverter::AnnotatedSave::operator QString() const { + QString sizeStr(niceSizeFormat(size)); + QString typeFormat("%1"); + QString endianStr; + QString saveType; + QString format = QCoreApplication::translate("SaveConverter", "%1 %2 save game"); + + switch (endianness) { + case Endian::LITTLE: + endianStr = QCoreApplication::translate("SaveConverter", "little endian"); + break; + case Endian::BIG: + endianStr = QCoreApplication::translate("SaveConverter", "big endian"); + break; + default: + break; + } + + switch (platform) { +#ifdef M_CORE_GBA + case mPLATFORM_GBA: + switch (gba.type) { + case SAVEDATA_SRAM: + typeFormat = QCoreApplication::translate("SaveConverter", "SRAM"); + break; + case SAVEDATA_FLASH512: + case SAVEDATA_FLASH1M: + typeFormat = QCoreApplication::translate("SaveConverter", "%1 flash"); + break; + case SAVEDATA_EEPROM: + case SAVEDATA_EEPROM512: + typeFormat = QCoreApplication::translate("SaveConverter", "%1 EEPROM"); + break; + default: + break; + } + break; +#endif +#ifdef M_CORE_GB + case mPLATFORM_GB: + switch (gb.type) { + case GB_MBC_AUTODETECT: + if (size & 0xFF) { + typeFormat = QCoreApplication::translate("SaveConverter", "%1 SRAM + RTC"); + } else { + typeFormat = QCoreApplication::translate("SaveConverter", "%1 SRAM"); + } + break; + case GB_MBC2: + if (size == 0x100) { + typeFormat = QCoreApplication::translate("SaveConverter", "packed MBC2"); + } else { + typeFormat = QCoreApplication::translate("SaveConverter", "unpacked MBC2"); + } + break; + case GB_MBC6: + if (size == GB_SIZE_MBC6_FLASH) { + typeFormat = QCoreApplication::translate("SaveConverter", "MBC6 flash"); + } else if (size > GB_SIZE_MBC6_FLASH) { + typeFormat = QCoreApplication::translate("SaveConverter", "MBC6 combined SRAM + flash"); + } else { + typeFormat = QCoreApplication::translate("SaveConverter", "MBC6 SRAM"); + } + break; + case GB_TAMA5: + typeFormat = QCoreApplication::translate("SaveConverter", "TAMA5"); + break; + default: + break; + } + break; +#endif + default: + break; + } + saveType = typeFormat.arg(sizeStr); + if (!endianStr.isEmpty()) { + saveType = QCoreApplication::translate("SaveConverter", "%1 (%2)").arg(saveType).arg(endianStr); + } + if (savestate) { + format = QCoreApplication::translate("SaveConverter", "%1 save state with embedded %2 save game"); + } + return format.arg(nicePlatformFormat(platform)).arg(saveType); +} + +bool SaveConverter::AnnotatedSave::operator==(const AnnotatedSave& other) const { + if (other.savestate != savestate || other.platform != platform || other.size != size || other.endianness != endianness) { + return false; + } + switch (platform) { +#ifdef M_CORE_GBA + case mPLATFORM_GBA: + if (other.gba.type != gba.type) { + return false; + } + break; +#endif +#ifdef M_CORE_GB + case mPLATFORM_GB: + if (other.gb.type != gb.type) { + return false; + } + break; +#endif + default: + break; + } + return true; +} + +QList SaveConverter::AnnotatedSave::possibleConversions() const { + QList possible; + AnnotatedSave same = asRaw(); + same.backing.reset(); + same.savestate = false; + + if (savestate) { + possible.append(same); + } + + + AnnotatedSave endianSwapped = same; + switch (endianness) { + case Endian::LITTLE: + endianSwapped.endianness = Endian::BIG; + possible.append(endianSwapped); + break; + case Endian::BIG: + endianSwapped.endianness = Endian::LITTLE; + possible.append(endianSwapped); + break; + default: + break; + } + + switch (platform) { +#ifdef M_CORE_GB + case mPLATFORM_GB: + switch (gb.type) { + case GB_MBC2: + if (size == 0x100) { + AnnotatedSave unpacked = same; + unpacked.size = 0x200; + unpacked.endianness = Endian::NONE; + possible.append(unpacked); + } else { + AnnotatedSave packed = same; + packed.size = 0x100; + packed.endianness = Endian::LITTLE; + possible.append(packed); + packed.endianness = Endian::BIG; + possible.append(packed); + } + break; + case GB_MBC6: + if (size > GB_SIZE_MBC6_FLASH) { + AnnotatedSave separated = same; + separated.size = size - GB_SIZE_MBC6_FLASH; + possible.append(separated); + separated.size = GB_SIZE_MBC6_FLASH; + possible.append(separated); + } + break; + default: + break; + } + break; +#endif + default: + break; + } + + return possible; +} + +QByteArray SaveConverter::AnnotatedSave::convertTo(const SaveConverter::AnnotatedSave& target) const { + QByteArray converted; + QByteArray buffer; + backing->seek(0); + if (target == asRaw()) { + return backing->readAll(); + } + + if (platform != target.platform) { + LOG(QT, ERROR) << tr("Cannot convert save games between platforms"); + return {}; + } + + switch (platform) { +#ifdef M_CORE_GBA + case mPLATFORM_GBA: + switch (gba.type) { + case SAVEDATA_EEPROM: + case SAVEDATA_EEPROM512: + converted.resize(target.size); + buffer = backing->readAll(); + for (int i = 0; i < size; i += 8) { + uint64_t word; + const uint64_t* in = reinterpret_cast(buffer.constData()); + uint64_t* out = reinterpret_cast(converted.data()); + LOAD_64LE(word, i, in); + STORE_64BE(word, i, out); + } + break; + default: + break; + } + break; +#endif +#ifdef M_CORE_GB + case mPLATFORM_GB: + switch (gb.type) { + case GB_MBC2: + converted.reserve(target.size); + buffer = backing->readAll(); + if (size == 0x100 && target.size == 0x200) { + if (endianness == Endian::LITTLE) { + for (uint8_t byte : buffer) { + converted.append(0xF0 | (byte & 0xF)); + converted.append(0xF0 | (byte >> 4)); + } + } else if (endianness == Endian::BIG) { + for (uint8_t byte : buffer) { + converted.append(0xF0 | (byte >> 4)); + converted.append(0xF0 | (byte & 0xF)); + } + } + } else if (size == 0x200 && target.size == 0x100) { + uint8_t byte; + if (target.endianness == Endian::LITTLE) { + for (int i = 0; i < target.size; ++i) { + byte = buffer[i * 2] & 0xF; + byte |= (buffer[i * 2 + 1] & 0xF) << 4; + converted.append(byte); + } + } else if (target.endianness == Endian::BIG) { + for (int i = 0; i < target.size; ++i) { + byte = (buffer[i * 2] & 0xF) << 4; + byte |= buffer[i * 2 + 1] & 0xF; + converted.append(byte); + } + } + } else if (size == 0x100 && target.size == 0x100) { + for (uint8_t byte : buffer) { + converted.append((byte >> 4) | (byte << 4)); + } + } + break; + case GB_MBC6: + if (size == target.size + GB_SIZE_MBC6_FLASH) { + converted = backing->read(target.size); + } else if (target.size == GB_SIZE_MBC6_FLASH) { + backing->seek(size - GB_SIZE_MBC6_FLASH); + converted = backing->read(GB_SIZE_MBC6_FLASH); + } + break; + default: + break; + } + break; +#endif + default: + break; + } + + return converted; +} diff --git a/src/platform/qt/SaveConverter.h b/src/platform/qt/SaveConverter.h new file mode 100644 index 000000000..a9da27952 --- /dev/null +++ b/src/platform/qt/SaveConverter.h @@ -0,0 +1,102 @@ +/* Copyright (c) 2013-2021 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#pragma once + +#include + +#include "CoreController.h" +#include "utils.h" + +#ifdef M_CORE_GBA +#include +#include +#endif +#ifdef M_CORE_GB +#include +#include +#endif + +#include + +#include "ui_SaveConverter.h" + +struct VFile; + +namespace QGBA { + +class SaveConverter : public QDialog { +Q_OBJECT + +public: + SaveConverter(std::shared_ptr controller, QWidget* parent = nullptr); + + static mPlatform getStatePlatform(VFile*); + static QByteArray getState(VFile*, mPlatform); + static QByteArray getExtdata(VFile*, mPlatform, mStateExtdataTag); + +public slots: + void convert(); + +private slots: + void refreshInputTypes(); + void refreshOutputTypes(); + void checkCanConvert(); + +private: +#ifdef M_CORE_GBA + struct GBASave { + SavedataType type; + }; +#endif +#ifdef M_CORE_GB + struct GBSave { + GBMemoryBankControllerType type; + }; +#endif + struct AnnotatedSave { + AnnotatedSave(); + AnnotatedSave(mPlatform, std::shared_ptr, Endian = Endian::NONE); +#ifdef M_CORE_GBA + AnnotatedSave(SavedataType, std::shared_ptr, Endian = Endian::NONE); +#endif +#ifdef M_CORE_GB + AnnotatedSave(GBMemoryBankControllerType, std::shared_ptr, Endian = Endian::NONE); +#endif + + AnnotatedSave asRaw() const; + operator QString() const; + bool operator==(const AnnotatedSave&) const; + + QList possibleConversions() const; + QByteArray convertTo(const AnnotatedSave&) const; + + bool savestate; + mPlatform platform; + ssize_t size; + std::shared_ptr backing; + Endian endianness; + union { +#ifdef M_CORE_GBA + GBASave gba; +#endif +#ifdef M_CORE_GB + GBSave gb; +#endif + }; + }; + + void detectFromSavestate(VFile*); + void detectFromSize(std::shared_ptr); + void detectFromHeaders(std::shared_ptr); + + Ui::SaveConverter m_ui; + + std::shared_ptr m_controller; + QList m_validSaves; + QList m_validOutputs; +}; + +} diff --git a/src/platform/qt/SaveConverter.ui b/src/platform/qt/SaveConverter.ui new file mode 100644 index 000000000..758400e25 --- /dev/null +++ b/src/platform/qt/SaveConverter.ui @@ -0,0 +1,124 @@ + + + SaveConverter + + + + 0 + 0 + 546 + 300 + + + + Convert/Extract Save Game + + + + + + Input file + + + + + + + + + Browse + + + + + + + false + + + + + + + + + + Output file + + + + + + + + + Browse + + + + + + + false + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Save + + + + + + + inputFile + inputBrowse + inputType + outputFile + outputBrowse + outputType + + + + + buttonBox + accepted() + SaveConverter + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SaveConverter + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/platform/qt/SensorView.cpp b/src/platform/qt/SensorView.cpp index 54c49cc2c..ba8f87da2 100644 --- a/src/platform/qt/SensorView.cpp +++ b/src/platform/qt/SensorView.cpp @@ -8,6 +8,7 @@ #include "CoreController.h" #include "GamepadAxisEvent.h" #include "InputController.h" +#include "utils.h" #include #include @@ -129,7 +130,7 @@ void SensorView::updateSensors() { } void SensorView::setLuminanceValue(int value) { - value = std::max(0, std::min(value, 255)); + value = clamp(value, 0, 255); if (m_input) { m_input->setLuminanceValue(value); } diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index ec12cea38..58a8f1fc5 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -883,7 +883,7 @@ - Savestate extra data: + Save state extra data: @@ -900,7 +900,7 @@ - Save data + Save game true @@ -927,7 +927,7 @@ - Load extra data: + Load state extra data: @@ -944,7 +944,7 @@ - Save data + Save game diff --git a/src/platform/qt/ShortcutView.cpp b/src/platform/qt/ShortcutView.cpp index cf0826006..badd7d5af 100644 --- a/src/platform/qt/ShortcutView.cpp +++ b/src/platform/qt/ShortcutView.cpp @@ -10,6 +10,7 @@ #include "ShortcutController.h" #include "ShortcutModel.h" +#include #include using namespace QGBA; @@ -134,6 +135,15 @@ void ShortcutView::closeEvent(QCloseEvent*) { } } +void ShortcutView::showEvent(QShowEvent*) { + QString longString("Ctrl+Alt+Shift+Tab"); + int width = QFontMetrics(QFont()).width(longString); + QHeaderView* header = m_ui.shortcutTable->header(); + header->resizeSection(0, header->length() - width * 2); + header->resizeSection(1, width); + header->resizeSection(2, width); +} + bool ShortcutView::event(QEvent* event) { if (m_input) { QEvent::Type type = event->type(); diff --git a/src/platform/qt/ShortcutView.h b/src/platform/qt/ShortcutView.h index 02a7ab1e6..4e370c126 100644 --- a/src/platform/qt/ShortcutView.h +++ b/src/platform/qt/ShortcutView.h @@ -32,6 +32,7 @@ public: protected: virtual bool event(QEvent*) override; virtual void closeEvent(QCloseEvent*) override; + virtual void showEvent(QShowEvent*) override; private slots: void load(const QModelIndex&); diff --git a/src/platform/qt/ShortcutView.ui b/src/platform/qt/ShortcutView.ui index b77d46e98..1ac97169e 100644 --- a/src/platform/qt/ShortcutView.ui +++ b/src/platform/qt/ShortcutView.ui @@ -16,6 +16,9 @@ + + Qt::ScrollBarAlwaysOn + 120 diff --git a/src/platform/qt/VFileDevice.cpp b/src/platform/qt/VFileDevice.cpp index 331720fa8..bce0ed830 100644 --- a/src/platform/qt/VFileDevice.cpp +++ b/src/platform/qt/VFileDevice.cpp @@ -91,6 +91,17 @@ VFileDevice::VFileDevice(const QString& filename, QIODevice::OpenMode mode, QObj } } +VFileDevice::VFileDevice(const QByteArray& mem, QObject* parent) + : QIODevice(parent) + , m_vf(VFileMemChunk(mem.constData(), mem.size())) +{ + setOpenMode(QIODevice::ReadWrite); +} + +VFileDevice::~VFileDevice() { + close(); +} + void VFileDevice::close() { if (!m_vf) { return; @@ -117,6 +128,13 @@ VFileDevice& VFileDevice::operator=(VFile* vf) { return *this; } +VFile* VFileDevice::take() { + VFile* vf = m_vf; + m_vf = nullptr; + QIODevice::close(); + return vf; +} + qint64 VFileDevice::readData(char* data, qint64 maxSize) { return m_vf->read(m_vf, data, maxSize); } diff --git a/src/platform/qt/VFileDevice.h b/src/platform/qt/VFileDevice.h index 72f3f1379..9df1aff93 100644 --- a/src/platform/qt/VFileDevice.h +++ b/src/platform/qt/VFileDevice.h @@ -19,7 +19,9 @@ Q_OBJECT public: VFileDevice(VFile* vf = nullptr, QObject* parent = nullptr); + VFileDevice(const QByteArray& mem, QObject* parent = nullptr); VFileDevice(const QString&, QIODevice::OpenMode, QObject* parent = nullptr); + virtual ~VFileDevice(); virtual void close() override; virtual bool seek(qint64 pos) override; @@ -29,6 +31,7 @@ public: VFileDevice& operator=(VFile*); operator VFile*() { return m_vf; } + VFile* take(); static VFile* wrap(QIODevice*, QIODevice::OpenMode); static VFile* wrap(QFileDevice*, QIODevice::OpenMode); diff --git a/src/platform/qt/VideoView.cpp b/src/platform/qt/VideoView.cpp index 5a5b6a605..5ef6d9141 100644 --- a/src/platform/qt/VideoView.cpp +++ b/src/platform/qt/VideoView.cpp @@ -9,6 +9,7 @@ #include "GBAApp.h" #include "LogController.h" +#include "utils.h" #include @@ -522,11 +523,7 @@ void VideoView::setPreset(const Preset& preset) { QSize VideoView::maintainAspect(const QSize& size) { QSize ds = size; - if (ds.width() * m_nativeHeight > ds.height() * m_nativeWidth) { - ds.setWidth(ds.height() * m_nativeWidth / m_nativeHeight); - } else if (ds.width() * m_nativeHeight < ds.height() * m_nativeWidth) { - ds.setHeight(ds.width() * m_nativeHeight / m_nativeWidth); - } + lockAspectRatio(QSize(m_nativeWidth, m_nativeHeight), ds); return ds; } diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 77b0dbabe..f628a66ed 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -49,12 +49,14 @@ #include "PrinterView.h" #include "ReportView.h" #include "ROMInfo.h" +#include "SaveConverter.h" #include "SensorView.h" #include "ShaderSelector.h" #include "ShortcutController.h" #include "TileView.h" #include "VideoProxy.h" #include "VideoView.h" +#include "utils.h" #ifdef USE_DISCORD_RPC #include "DiscordCoordinator.h" @@ -417,8 +419,8 @@ void Window::replaceROM() { void Window::selectSave(bool temporary) { QStringList formats{"*.sav"}; - QString filter = tr("Game Boy Advance save files (%1)").arg(formats.join(QChar(' '))); - QString filename = GBAApp::app()->getOpenFileName(this, tr("Select save"), filter); + QString filter = tr("Save games (%1)").arg(formats.join(QChar(' '))); + QString filename = GBAApp::app()->getOpenFileName(this, tr("Select save game"), filter); if (!filename.isEmpty()) { m_controller->loadSave(filename, temporary); } @@ -426,14 +428,14 @@ void Window::selectSave(bool temporary) { void Window::selectState(bool load) { QStringList formats{"*.ss0", "*.ss1", "*.ss2", "*.ss3", "*.ss4", "*.ss5", "*.ss6", "*.ss7", "*.ss8", "*.ss9"}; - QString filter = tr("mGBA savestate files (%1)").arg(formats.join(QChar(' '))); + QString filter = tr("mGBA save state files (%1)").arg(formats.join(QChar(' '))); if (load) { - QString filename = GBAApp::app()->getOpenFileName(this, tr("Select savestate"), filter); + QString filename = GBAApp::app()->getOpenFileName(this, tr("Select save state"), filter); if (!filename.isEmpty()) { m_controller->loadState(filename); } } else { - QString filename = GBAApp::app()->getSaveFileName(this, tr("Select savestate"), filter); + QString filename = GBAApp::app()->getSaveFileName(this, tr("Select save state"), filter); if (!filename.isEmpty()) { m_controller->saveState(filename); } @@ -1183,10 +1185,10 @@ void Window::setupMenu(QMenuBar* menubar) { m_actions.addAction(tr("Add folder to library..."), "addDirToLibrary", this, &Window::addDirToLibrary, "file"); #endif - addGameAction(tr("Load alternate save..."), "loadAlternateSave", [this]() { + addGameAction(tr("Load alternate save game..."), "loadAlternateSave", [this]() { this->selectSave(false); }, "file"); - addGameAction(tr("Load temporary save..."), "loadTemporarySave", [this]() { + addGameAction(tr("Load temporary save game..."), "loadTemporarySave", [this]() { this->selectSave(true); }, "file"); @@ -1294,6 +1296,8 @@ void Window::setupMenu(QMenuBar* menubar) { #ifdef M_CORE_GBA m_actions.addSeparator("file"); + m_actions.addAction(tr("Convert save game..."), "convertSave", openControllerTView(), "file"); + Action* importShark = addGameAction(tr("Import GameShark Save..."), "importShark", this, &Window::importSharkport, "file"); m_platformActions.insert(mPLATFORM_GBA, importShark); @@ -1980,9 +1984,7 @@ void Window::attachDisplay() { void Window::setLogo() { m_screenWidget->setPixmap(m_logo); m_screenWidget->setCenteredAspectRatio(m_logo.width(), m_logo.height()); - m_screenWidget->setDimensions(m_logo.width(), m_logo.height()); m_screenWidget->setLockIntegerScaling(false); - m_screenWidget->setLockAspectRatio(true); m_screenWidget->filter(true); m_screenWidget->unsetCursor(); } @@ -2037,30 +2039,6 @@ void WindowBackground::paintEvent(QPaintEvent* event) { QPainter painter(this); painter.setRenderHint(QPainter::SmoothPixmapTransform, m_filter); painter.fillRect(QRect(QPoint(), size()), Qt::black); - QSize s = size(); - QSize ds = s; - if (m_centered) { - if (ds.width() * m_aspectHeight < ds.height() * m_aspectWidth) { - ds.setWidth(ds.height() * m_aspectWidth / m_aspectHeight); - } else if (ds.width() * m_aspectHeight > ds.height() * m_aspectWidth) { - ds.setHeight(ds.width() * m_aspectHeight / m_aspectWidth); - } - } else if (m_lockAspectRatio) { - if (ds.width() * m_aspectHeight > ds.height() * m_aspectWidth) { - ds.setWidth(ds.height() * m_aspectWidth / m_aspectHeight); - } else if (ds.width() * m_aspectHeight < ds.height() * m_aspectWidth) { - ds.setHeight(ds.width() * m_aspectHeight / m_aspectWidth); - } - } - if (m_lockIntegerScaling) { - if (ds.width() >= m_aspectWidth) { - ds.setWidth(ds.width() - ds.width() % m_aspectWidth); - } - if (ds.height() >= m_aspectHeight) { - ds.setHeight(ds.height() - ds.height() % m_aspectHeight); - } - } - QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2); - QRect full(origin, ds); + QRect full(clampSize(QSize(m_aspectWidth, m_aspectHeight), size(), m_lockAspectRatio, m_lockIntegerScaling, m_centered)); painter.drawPixmap(full, logo); } diff --git a/src/platform/qt/input/InputController.cpp b/src/platform/qt/input/InputController.cpp index e1c1a8407..43b55f525 100644 --- a/src/platform/qt/input/InputController.cpp +++ b/src/platform/qt/input/InputController.cpp @@ -13,6 +13,7 @@ #include "InputModel.h" #include "InputProfile.h" #include "LogController.h" +#include "utils.h" #include #include @@ -1002,7 +1003,7 @@ void InputController::decreaseLuminanceLevel() { void InputController::setLuminanceLevel(int level) { int value = 0x16; - level = std::max(0, std::min(10, level)); + level = clamp(level, 0, 10); if (level > 0) { value += GBA_LUX_LEVELS[level - 1]; } diff --git a/src/platform/qt/library/LibraryController.cpp b/src/platform/qt/library/LibraryController.cpp index 51fa6d619..2c8c37741 100644 --- a/src/platform/qt/library/LibraryController.cpp +++ b/src/platform/qt/library/LibraryController.cpp @@ -108,10 +108,10 @@ QPair LibraryController::selectedPath() { return e ? qMakePair(e->base(), e->filename()) : qMakePair("", ""); } -void LibraryController::addDirectory(const QString& dir) { +void LibraryController::addDirectory(const QString& dir, bool recursive) { // The worker thread temporarily owns the library std::shared_ptr library = m_library; - m_libraryJob = GBAApp::app()->submitWorkerJob(std::bind(&LibraryController::loadDirectory, this, dir), this, [this, library]() { + m_libraryJob = GBAApp::app()->submitWorkerJob(std::bind(&LibraryController::loadDirectory, this, dir, recursive), this, [this, library]() { m_libraryJob = -1; refresh(); }); @@ -181,10 +181,10 @@ void LibraryController::selectLastBootedGame() { } } -void LibraryController::loadDirectory(const QString& dir) { - // This class can get delted during this function (sigh) so we need to hold onto this +void LibraryController::loadDirectory(const QString& dir, bool recursive) { + // This class can get deleted during this function (sigh) so we need to hold onto this std::shared_ptr library = m_library; - mLibraryLoadDirectory(library.get(), dir.toUtf8().constData()); + mLibraryLoadDirectory(library.get(), dir.toUtf8().constData(), recursive); } void LibraryController::freeLibrary() { @@ -192,4 +192,4 @@ void LibraryController::freeLibrary() { mLibraryEntryFree(mLibraryListingGetPointer(&m_listing, i)); } mLibraryListingClear(&m_listing); -} \ No newline at end of file +} diff --git a/src/platform/qt/library/LibraryController.h b/src/platform/qt/library/LibraryController.h index 9f88cdff5..2b5a595ee 100644 --- a/src/platform/qt/library/LibraryController.h +++ b/src/platform/qt/library/LibraryController.h @@ -84,7 +84,7 @@ public: void selectLastBootedGame(); - void addDirectory(const QString& dir); + void addDirectory(const QString& dir, bool recursive = true); public slots: void clear(); @@ -97,7 +97,7 @@ private slots: void refresh(); private: - void loadDirectory(const QString&); // Called on separate thread + void loadDirectory(const QString&, bool recursive = true); // Called on separate thread void freeLibrary(); ConfigController* m_config = nullptr; diff --git a/src/platform/qt/ts/medusa-emu-de.ts b/src/platform/qt/ts/medusa-emu-de.ts index 75e4412ed..e809b69dc 100644 --- a/src/platform/qt/ts/medusa-emu-de.ts +++ b/src/platform/qt/ts/medusa-emu-de.ts @@ -35,10 +35,10 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 – 2020 Jeffrey Pfau, lizenziert unter der Mozilla Public License, Version 2.0 -Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. + © 2013 – {year} Jeffrey Pfau, lizenziert unter der Mozilla Public License, Version 2.0 +Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd. @@ -1150,6 +1150,14 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.Kopieren + + QGBA::AboutScreen + + + 2021 + 2021 + + QGBA::AssetTile @@ -1239,17 +1247,17 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::CoreManager - + Failed to open game file: %1 Fehler beim Öffnen der Spieldatei: %1 - + Could not load game. Are you sure it's in the correct format? Konnte das Spiel nicht laden. Bist Du sicher, dass es im korrekten Format vorliegt? - + Failed to open save file. Is the save directory writable? Fehler beim Öffnen der Speicherdatei. Ist das Zielverzeichnis beschreibbar? @@ -1257,52 +1265,52 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::FrameView - + Export frame Bild exportieren - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Keine - + Background Hintergrund - + Window Fenster - + Objwin Objwin - + Sprite Sprite - + Backdrop Hintergrund - + Frame Frame - + %1 %2 %1 %2 @@ -1310,7 +1318,7 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::GBAApp - + Enable Discord Rich Presence Discord-Integration aktivieren @@ -3532,62 +3540,62 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::MemoryModel - + Copy selection Auswahl kopieren - + Save selection Auswahl speichern - + Paste Einfügen - + Load Laden - + All Alle - + Load TBL TBL laden - + Save selected memory Ausgewählten Speicher abspeichern - + Failed to open output file: %1 Fehler beim Öffnen der Ausgabedatei: %1 - + Load memory Lade Speicher - + Failed to open input file: %1 Fehler beim Laden der Eingabedatei: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3757,16 +3765,79 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::ReportView - + Bug report archive Fehlerbericht speichern - + ZIP archive (*.zip) ZIP-Archiv (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + Spielstände (%1) + + + + Select save game + Spielstand auswählen + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3829,7 +3900,7 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. Select directory - + Verzeichnis auswählen @@ -3910,17 +3981,17 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 Fehler beim Öffnen der Ausgabe-Videodatei: %1 - + Native (%0x%1) Nativ (%0x%1) - + Select output file Ausgabedatei auswählen @@ -3928,7 +3999,7 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance-ROMs (%1) @@ -3938,78 +4009,61 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.DS-ROMs (%1) - + Game Boy ROMs (%1) Game Boy-ROMs (%1) - + All ROMs (%1) Alle ROMs (%1) - + %1 Video Logs (*.mvl) %1 Video-Logs (*.mvl) - + Archives (%1) Archive (%1) - - - + + + Select ROM ROM auswählen - - Game Boy Advance save files (%1) - Game Boy Advance-Speicherdateien (%1) - - - - - + + Select save Speicherdatei wählen - - mGBA savestate files (%1) - mGBA Savestate-Dateien (%1) - - - - - Select savestate - Savestate auswählen - - - + Select patch Patch wählen - + Patches (*.ips *.ups *.bps) Patches (*.ips *.ups *.bps) - + Select image Bild auswählen - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Bild-Datei (*.png *.gif *.jpg *.jpeg);;Alle Dateien (*) - - + + GameShark saves (*.sps *.xps) GameShark-Speicherdaten (*.sps *.xps) @@ -4024,22 +4078,22 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.DS-Unterstützung erfordert ein Abbild des BIOS und der Firmware. - + Select video log Video-Log auswählen - + Video logs (*.mvl) Video-Logs (*.mvl) - + Crash Absturz - + The game has crashed with the following error: %1 @@ -4048,418 +4102,413 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. - + Unimplemented BIOS call Nicht implementierter BIOS-Aufruf - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Dieses Spiel verwendet einen BIOS-Aufruf, der nicht implementiert ist. Bitte verwenden Sie für die beste Spielerfahrung das offizielle BIOS. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Es konnte kein geeignetes Ausgabegerät erstellt werden, stattdessen wird Software-Rendering als Rückfalloption genutzt. Spiele laufen möglicherweise langsamer, besonders innerhalb großer Fenster. - + Really make portable? Portablen Modus wirklich aktivieren? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Diese Einstellung wird den Emulator so konfigurieren, dass er seine Konfiguration aus dem gleichen Verzeichnis wie die Programmdatei lädt. Möchten Sie fortfahren? - + Restart needed Neustart benötigt - + Some changes will not take effect until the emulator is restarted. Einige Änderungen werden erst übernommen, wenn der Emulator neu gestartet wurde. - + - Player %1 of %2 - Spieler %1 von %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 Bilder/Sekunde) - %4 - + &File &Datei - + Load &ROM... &ROM laden... - + Load ROM in archive... ROM aus Archiv laden... - - Load alternate save... - Alternative Speicherdatei laden... - - - - Load temporary save... - Temporäre Speicherdatei laden... - - - + Load &patch... &Patch laden... - + Boot BIOS BIOS booten - + Replace ROM... ROM ersetzen... - + ROM &info... ROM-&Informationen... - + Recent Zuletzt verwendet - + Make portable Portablen Modus aktivieren - + &Load state Savestate (aktueller Zustand) &laden - + Load state file... Savestate-Datei laden... - + &Save state Savestate (aktueller Zustand) &speichern - + Save state file... Savestate-Datei speichern... - + Quick load Schnell laden - + Quick save Schnell speichern - + Load recent Lade zuletzt gespeicherten Savestate - + Save recent Speichere aktuellen Zustand - + Undo load state Laden des Savestate rückgängig machen - + Undo save state Speichern des Savestate rückgängig machen - - + + State &%1 Savestate &%1 - + Load camera image... Lade Kamerabild... - + + Convert save game... + + + + New multiplayer window Neues Multiplayer-Fenster - + Report bug... Fehler melden... - + E&xit &Beenden - + &Emulation &Emulation - + &Reset Zu&rücksetzen - + Sh&utdown Schli&eßen - + Yank game pak Spielmodul herausziehen - + &Pause &Pause - + &Next frame &Nächstes Bild - + Fast forward (held) Schneller Vorlauf (gehalten) - + &Fast forward Schneller &Vorlauf - + Fast forward speed Vorlauf-Geschwindigkeit - + Unbounded Unbegrenzt - + %0x %0x - + Rewind (held) Zurückspulen (gehalten) - + Re&wind Zur&ückspulen - + Step backwards Schrittweiser Rücklauf - + Sync to &video Mit &Video synchronisieren - + Sync to &audio Mit &Audio synchronisieren - + Solar sensor Sonnen-Sensor - + Increase solar level Sonnen-Level erhöhen - + Decrease solar level Sonnen-Level verringern - + Brightest solar level Hellster Sonnen-Level - + Darkest solar level Dunkelster Sonnen-Level - + Brightness %1 Helligkeit %1 - + BattleChip Gate... BattleChip Gate... - + Audio/&Video Audio/&Video - + Frame size Bildgröße - + Toggle fullscreen Vollbildmodus umschalten - + Lock aspect ratio Seitenverhältnis korrigieren - + Force integer scaling Pixelgenaue Skalierung (Integer scaling) - + Interframe blending Interframe-Überblendung - + Frame&skip Frame&skip - + Mute Stummschalten - + FPS target Bildwiederholrate - + Take &screenshot &Screenshot erstellen - + F12 F12 - + Clear Leeren - + Game Boy Printer... Game Boy Printer... - + Video layers Video-Ebenen - + Audio channels Audio-Kanäle - + Adjust layer placement... Lage der Bildebenen anpassen... - + &Tools &Werkzeuge - + View &logs... &Logs ansehen... - + Game &overrides... Spiel-&Überschreibungen... - + &Cheats... &Cheats... - + Open debugger console... Debugger-Konsole öffnen... - + Start &GDB server... &GDB-Server starten... - + Settings... Einstellungen... @@ -4479,208 +4528,249 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.DS - + Select folder Ordner auswählen - + + Save games (%1) + Spielstände (%1) + + + + Select save game + Spielstand auswählen + + + + mGBA save state files (%1) + mGBA-Savestates (%1) + + + + + Select save state + Savestate auswählen + + + Select e-Reader dotcode e-Reader-Code auswählen - + e-Reader card (*.raw *.bin *.bmp) e-Reader-Karte (*.raw *.bin *.bmp) - + Couldn't Start Konnte nicht gestartet werden - + Could not start game. Spiel konnte nicht gestartet werden. - + Add folder to library... Ordner zur Bibliothek hinzufügen... - + + Load alternate save game... + Alternativen Spielstand laden... + + + + Load temporary save game... + Temporären Spielstand laden... + + + Scan e-Reader dotcodes... e-Reader-Code einlesen... - + Import GameShark Save... GameShare-Speicherstand importieren... - + Export GameShark Save... GameShark-Speicherstand exportieren... - + About... Über... - + %1× %1x - + Bilinear filtering Bilineare Filterung - + Native (59.7275) Nativ (59.7275) - + Record A/V... Audio/Video aufzeichnen... - + Record GIF/WebP/APNG... GIF/WebP/APNG aufzeichnen... - + Game Pak sensors... Spielmodul-Sensoren... - + View &palette... &Palette betrachten... - + View &sprites... &Sprites betrachten... - + View &tiles... &Tiles betrachten... - + View &map... &Map betrachten... - + &Frame inspector... &Bildbetrachter... - + View memory... Speicher betrachten... - - - - View &I/O registers... - &I/O-Register betrachten... - + Search memory... Speicher durchsuchen... - + View &I/O registers... &I/O-Register betrachten... - + Record debug video log... Video-Protokoll aufzeichnen... - + Stop debug video log Aufzeichnen des Video-Protokolls beenden - + Exit fullscreen Vollbildmodus beenden - + GameShark Button (held) GameShark-Taste (gehalten) - + Autofire Autofeuer - + Autofire A Autofeuer A - + Autofire B Autofeuer B - + Autofire L Autofeuer L - + Autofire R Autofeuer R - + Autofire Start Autofeuer Start - + Autofire Select Autofeuer Select - + Autofire Up Autofeuer nach oben - + Autofire Right Autofeuer rechts - + Autofire Down Autofeuer nach unten - + Autofire Left Autofeuer links QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4816,6 +4906,110 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.Savestate erzeugen und anhängen + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + Durchsuchen + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + SRAM + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5128,6 +5322,22 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.Show FPS in title bar Bildwiederholrate in der Titelleiste anzeigen + + + Save state extra data: + Zusätzliche Savestate-Daten: + + + + + Save game + Spielstand + + + + Load state extra data: + Zusätzliche Savestate-Daten laden: + Enable Game Boy Player features by default @@ -5397,12 +5607,6 @@ wenn vorhanden Screenshot Screenshot - - - - Save data - Speicherdaten - @@ -5429,16 +5633,6 @@ wenn vorhanden Idle loops: Leerlaufprozesse: - - - Savestate extra data: - Zusätzliche Savestate-Daten: - - - - Load extra data: - Lade zusätzliche Daten: - Autofire interval: @@ -5550,17 +5744,17 @@ wenn vorhanden Tastenkürzel bearbeiten - + Keyboard Tastatur - + Gamepad Gamepad - + Clear Löschen diff --git a/src/platform/qt/ts/medusa-emu-es.ts b/src/platform/qt/ts/medusa-emu-es.ts index f28e12c20..911a6b110 100644 --- a/src/platform/qt/ts/medusa-emu-es.ts +++ b/src/platform/qt/ts/medusa-emu-es.ts @@ -25,9 +25,9 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 – 2020 Jeffrey Pfau, licenciado bajo la Mozilla Public License, versión 2.0 + © 2013 – {year} Jeffrey Pfau, licenciado bajo la Mozilla Public License, versión 2.0 Game Boy Advance es una marca registrada de Nintendo Co., Ltd. @@ -1135,6 +1135,14 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. Ampliación + + QGBA::AboutScreen + + + 2021 + 2021 + + QGBA::AssetTile @@ -1224,17 +1232,17 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::CoreManager - + Failed to open game file: %1 Error al abrir el archivo del juego: %1 - + Could not load game. Are you sure it's in the correct format? No se pudo cargar el juego. ¿Estás seguro de que está en el formato correcto? - + Failed to open save file. Is the save directory writable? Error al abrir el archivo de guardado: ¿El directorio tiene permisos de escritura? @@ -1242,52 +1250,52 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::FrameView - + Export frame Exportar cuadro - + Portable Network Graphics (*.png) Gráficos de red portátiles (*.png) - + None Ninguno - + Background Fondo (BG) - + Window Ventana (WIN) - + Objwin Objwin - + Sprite Sprite - + Backdrop Telón de fondo (backdrop) - + Frame Cuadro - + %1 %2 %1× {1 %2?} @@ -1295,7 +1303,7 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::GBAApp - + Enable Discord Rich Presence Habilitar Rich Presence en Discord @@ -3486,62 +3494,62 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::MemoryModel - + Copy selection Copiar selección - + Save selection Guardar selección - + Paste Pegar - + Load Cargar - + All Todo - + Load TBL Cargar TBL - + Save selected memory Guardar memoria seleccionada - + Failed to open output file: %1 Error al abrir el archivo de salida: %1 - + Load memory Cargar memoria - + Failed to open input file: %1 Error al abrir el archivo de entrada: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3711,16 +3719,79 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::ReportView - + Bug report archive Archivo del reporte de bugs - + ZIP archive (*.zip) Archivo ZIP (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3864,17 +3935,17 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 Error al abrir el archivo de video de salida: %1 - + Native (%0x%1) Native (%0x%1) - + Select output file Seleccionar archivo de salida @@ -3882,118 +3953,101 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::Window - + Game Boy Advance ROMs (%1) ROMs de Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs de Game Boy (%1) - + All ROMs (%1) Todas las ROMs (%1) - + %1 Video Logs (*.mvl) Video-registros de %1 (*.mvl) - + Archives (%1) Contenedores (%1) - - - + + + Select ROM Seleccionar ROM - + Select folder Seleccionar carpeta - - Game Boy Advance save files (%1) - Archivos de guardado de Game Boy Advance (%1) - - - - - + + Select save Seleccionar guardado - - mGBA savestate files (%1) - Archivos de estado de guardado de mGBA (%1) - - - - - Select savestate - Elegir estado de guardado - - - + Select patch Seleccionar parche - + Patches (*.ips *.ups *.bps) Parches (*.ips *.ups *.bps) - + Select e-Reader dotcode Seleccionar dotcode del e-Reader - + e-Reader card (*.raw *.bin *.bmp) Tarjeta e-Reader (*.raw *.bin *.bmp) - + Select image Seleccionar imagen - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Archivo de imagen (*.png *.gif *.jpg *.jpeg);;Todos los archivos (*) - - + + GameShark saves (*.sps *.xps) Guardados de GameShark (*.sps *.xps) - + Select video log Seleccionar video-registro - + Video logs (*.mvl) Video-registros (*.mvl) - + Crash Error fatal - + The game has crashed with the following error: %1 @@ -4002,604 +4056,645 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. %1 - + Unimplemented BIOS call Llamada a BIOS no implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este juego utiliza una llamada al BIOS que no se ha implementado. Utiliza el BIOS oficial para obtener la mejor experiencia. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. No se pudo crear un dispositivo de pantalla apropiado, recurriendo a software. Los juegos pueden funcionar lentamente, especialmente con ventanas grandes. - + Really make portable? ¿Hacer "portable"? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Esto hará que el emulador cargue su configuración desde el mismo directorio que el ejecutable. ¿Quieres continuar? - + Restart needed Reinicio necesario - + Some changes will not take effect until the emulator is restarted. Algunos cambios no surtirán efecto hasta que se reinicie el emulador. - + - Player %1 of %2 - Jugador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Archivo - + Load &ROM... Cargar &ROM... - + Load ROM in archive... Cargar ROM desde contenedor... - + Add folder to library... Agregar carpeta a la biblioteca... - - Load alternate save... - Cargar guardado alternativo... - - - - Load temporary save... - Cargar guardado temporal... - - - + Load &patch... Cargar &parche... - + Boot BIOS Arrancar BIOS - + Replace ROM... Reemplazar ROM... - + ROM &info... &Información de la ROM... - + Recent Recientes - + Make portable Hacer "portable" - + &Load state Ca&rgar estado - + Report bug... Reportar bug... - + About... Acerca de... - + Game Pak sensors... Sensores del cartucho... - + Clear Limpiar - + Load state file... Cargar archivo de estado... - + + Save games (%1) + + + + + Select save game + + + + + mGBA save state files (%1) + + + + + + Select save state + + + + + Load alternate save game... + + + + + Load temporary save game... + + + + &Save state Guardar e&stado - + Save state file... Guardar archivo de estado... - + Quick load Cargado rápido - + Quick save Guardado rápido - + Load recent Cargar reciente - + Save recent Guardar reciente - + Undo load state Deshacer cargar estado - + Undo save state Deshacer guardar estado - - + + State &%1 Estado &%1 - + Load camera image... Cargar imagen para la cámara... - + + Convert save game... + + + + New multiplayer window Nueva ventana multijugador - + E&xit Salir (&X) - + &Emulation &Emulación - + &Reset &Reinicializar - + Sh&utdown Apagar (&U) - + Yank game pak Tirar del cartucho - + &Pause &Pausar - + &Next frame Cuadro siguie&nte - + Fast forward (held) Avance rápido (mantener) - + &Fast forward &Avance rápido - + Fast forward speed Velocidad de avance rápido - + Unbounded Sin límite - + %0x %0x - + Rewind (held) Rebobinar (mantener) - + Re&wind Re&bobinar - + Step backwards Paso hacia atrás - + Sync to &video Sincronizar a &video - + Sync to &audio Sincronizar a au&dio - + Solar sensor Sensor solar - + Increase solar level Subir nivel - + Decrease solar level Bajar nivel - + Brightest solar level Más claro - + Darkest solar level Más oscuro - + Brightness %1 Brillo %1 - + Audio/&Video Audio/&video - + Frame size Tamaño del cuadro - + Toggle fullscreen Pantalla completa - + Lock aspect ratio Bloquear proporción de aspecto - + Force integer scaling Forzar escala a enteros - + Bilinear filtering Filtro bilineal - + Frame&skip &Salto de cuadros - + Mute Silenciar - + FPS target Objetivo de FPS - + Native (59.7275) Nativo (59,7275) - + Take &screenshot Tomar pan&tallazo - + F12 F12 - + Game Boy Printer... Game Boy Printer... - + BattleChip Gate... BattleChip Gate... - + %1× %1× - + Interframe blending Mezcla entre cuadros - + Record A/V... Grabar A/V... - + Video layers Capas de video - + Audio channels Canales de audio - + Adjust layer placement... Ajustar ubicación de capas... - + &Tools Herramien&tas - + View &logs... Ver re&gistros... - + Game &overrides... Ajustes específic&os por juego... - + Couldn't Start No se pudo iniciar - + Could not start game. No se pudo iniciar el juego. - + Scan e-Reader dotcodes... Escanear dotcodes del e-Reader... - + Import GameShark Save... Importar desde GameShark... - + Export GameShark Save... Exportar a GameShark... - + Record GIF/WebP/APNG... Grabar GIF/WebP/APNG... - + &Cheats... Tru&cos... - + Settings... Ajustes... - + Open debugger console... Abrir consola de depuración... - + Start &GDB server... Iniciar servidor &GDB... - + View &palette... Ver &paleta... - + View &sprites... Ver &sprites... - + View &tiles... Ver &tiles... - + View &map... Ver &mapa... - + &Frame inspector... Inspec&tor de cuadros... - + View memory... Ver memoria... - + Search memory... Buscar memoria... - + View &I/O registers... Ver registros &I/O... - + Record debug video log... Grabar registro de depuración de video... - + Stop debug video log Detener registro de depuración de video - + Exit fullscreen Salir de pantalla completa - + GameShark Button (held) Botón GameShark (mantener) - + Autofire Disparo automático - + Autofire A Disparo automático A - + Autofire B Disparo automático B - + Autofire L Disparo automático L - + Autofire R Disparo automático R - + Autofire Start Disparo automático Start - + Autofire Select Disparo automático Select - + Autofire Up Disparo automático Arriba - + Autofire Right Disparo automático Derecha - + Autofire Down Disparo automático Abajo - + Autofire Left Disparo automático Izquierda QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4735,6 +4830,110 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + Examinar + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + SRAM + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5036,6 +5235,22 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. Show OSD messages Mostrar mensajes en el OSD + + + Save state extra data: + + + + + + Save game + + + + + Load state extra data: + + Super Game Boy/Game Boy Color model: @@ -5212,34 +5427,18 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. Detect and remove Detectar y eliminar - - - Savestate extra data: - Guardar datos extra: - Screenshot Pantallazo - - - - Save data - Datos de guardado - Cheat codes Trucos - - - Load extra data: - Cargar datos extra: - Preload entire ROM into memory @@ -5449,17 +5648,17 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. Editar atajos de teclado - + Keyboard Teclado - + Gamepad Mando - + Clear Limpiar diff --git a/src/platform/qt/ts/medusa-emu-it.ts b/src/platform/qt/ts/medusa-emu-it.ts index 8284cb409..073fef9df 100644 --- a/src/platform/qt/ts/medusa-emu-it.ts +++ b/src/platform/qt/ts/medusa-emu-it.ts @@ -20,9 +20,9 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 - 2020 Jeffrey Pfau, sotto licenza Mozilla Public License, versione 2.0 + © 2013 - {year} Jeffrey Pfau, sotto licenza Mozilla Public License, versione 2.0 Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. @@ -269,7 +269,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Record GIF/WebP/APNG - + Registra GIF/WebP/APNG @@ -284,7 +284,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. WebP - + WebP @@ -330,12 +330,12 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Location - + Posizione Platform - + Piattaforma @@ -345,7 +345,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. CRC32 - CRC32: {32?} + CRC32 @@ -983,7 +983,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. VBA bug compatibility mode - + Modalità compatibilità bug VBA @@ -1135,6 +1135,14 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Ingrandimento + + QGBA::AboutScreen + + + 2021 + 2021 + + QGBA::AssetTile @@ -1208,7 +1216,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Can't yank pack in unexpected platform! - + Non riesco a strappare il pacchetto in una piattaforma inaspettata! @@ -1224,70 +1232,70 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. QGBA::CoreManager - + Failed to open game file: %1 Impossibile aprire il file di gioco: %1 - + Could not load game. Are you sure it's in the correct format? Impossibile caricare il gioco. Sei sicuro che sia nel formato corretto? - + Failed to open save file. Is the save directory writable? - + Impossibile aprire il file di salvataggio. La directory di salvataggio è scrivibile? QGBA::FrameView - + Export frame Esporta Frame - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Nessuno - + Background Sfondo - + Window Finestra - + Objwin - + Objwin - + Sprite Sprite - + Backdrop Sfondo - + Frame - + Inquadratura - + %1 %2 %1x {1 %2?} @@ -1295,7 +1303,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. QGBA::GBAApp - + Enable Discord Rich Presence Abilita Discord Rich Presence @@ -1381,7 +1389,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Graphics Interchange Format (*.gif);;WebP ( *.webp);;Animated Portable Network Graphics (*.png *.apng) - + Formato di intercambio delle grafiche (*.gif);; WebP ( *.webp);; Grafica di rete portatile animata (*.png *.apng) @@ -3486,62 +3494,62 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. QGBA::MemoryModel - + Copy selection Copia selezione - + Save selection Salva selezione - + Paste Incolla - + Load Carica - + All Tutto - + Load TBL Carica TBL - + Save selected memory Salva la memoria selezionata - + Failed to open output file: %1 Impossibile aprire il file di output: %1 - + Load memory Carica memoria - + Failed to open input file: %1 Impossibile aprire il file di input: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3636,17 +3644,17 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Official MBCs - + MBC ufficiali Licensed MBCs - + MBC con licenza Unlicensed MBCs - + MBC senza licenza @@ -3711,13 +3719,76 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. QGBA::ReportView - + Bug report archive + Archivio delle segnalazioni di bug + + + + ZIP archive (*.zip) + Archivio ZIP (*.zip) + + + + QGBA::SaveConverter + + + Save games and save states (%1) - - ZIP archive (*.zip) + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms @@ -3864,17 +3935,17 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 Errore durante l'archiviazione del video: %1 - + Native (%0x%1) Nativo (%0x%1) - + Select output file Seleziona file di uscita @@ -3882,113 +3953,96 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. QGBA::Window - + Game Boy Advance ROMs (%1) ROM per Game Boy Advance (%1) - + Game Boy ROMs (%1) ROM per Game Boy (%1) - + All ROMs (%1) Tutte le ROM (%1) - + %1 Video Logs (*.mvl) %1 log Video (*.mvl) - + Archives (%1) Archivi (%1) - - - + + + Select ROM Seleziona ROM - - Game Boy Advance save files (%1) - Game Boy Advance file di salvataggio (%1) - - - - - + + Select save Seleziona salvataggio - - mGBA savestate files (%1) - mGBA file stato (%1) - - - - - Select savestate - Seleziona stato di salvataggio - - - + Select patch Seleziona patch - + Patches (*.ips *.ups *.bps) Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode Selezione e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) e-Reader card (*.raw *.bin *.bmp) - + Select image Seleziona immagine - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) File immagine (*.png *.gif *.jpg *.jpeg);;Tutti i file (*) - - + + GameShark saves (*.sps *.xps) Salvataggi GameShark (*.sps *.xps) - + Select video log Seleziona log video - + Video logs (*.mvl) Log video (*.mvl) - + Crash Errore fatale - + The game has crashed with the following error: %1 @@ -3997,609 +4051,650 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. %1 - + Unimplemented BIOS call BIOS non implementato - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - Questo gioco utilizza una chiamata BIOS non implementata. Utilizza il BIOS ufficiale per una migliore esperienza + Questo gioco utilizza una chiamata BIOS non implementata. Utilizza il BIOS ufficiale per una migliore esperienza. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Impossibile creare un dispositivo di visualizzazione appropriato, tornando alla visualizzazione software. I giochi possono funzionare lentamente, specialmente con finestre più grandi. - + Really make portable? Vuoi davvero rendere portatile l'applicazione? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? In questo modo l'emulatore carica la propria configurazione dalla stessa cartella dell'eseguibile. Vuoi continuare? - + Restart needed È necessario riavviare - + Some changes will not take effect until the emulator is restarted. Alcune modifiche non avranno effetto finché l'emulatore non verrà riavviato. - + - Player %1 of %2 - Giocatore %1 di %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File File - + Load &ROM... Carica ROM... - + Load ROM in archive... Carica la ROM in archivio... - - Load alternate save... - Carica il salvataggio alternativo... - - - - Load temporary save... - Carica il salvataggio temporaneo.. - - - + Load &patch... Carica patch... - + Boot BIOS Avvia BIOS - + Replace ROM... Sostituisci la ROM... - + Scan e-Reader dotcodes... Scansiona e-Reader dotcode... - + ROM &info... Informazioni ROM... - + Recent Recente - + Make portable Rendi portatile - + &Load state Carica stato - + &Save state Salva stato - + Quick load Caricamento rapido - + Quick save Salvataggio rapido - + Load recent Carica recente - + Save recent Salva recente - + Undo load state Annulla il caricamento dello stato - + Undo save state Annulla salvataggio stato - - + + State &%1 Stato %1 - + Load camera image... Carica immagine camera... - + + Convert save game... + + + + New multiplayer window Nuova finestra multigiocatore - + Report bug... - + Segnala bug... - + E&xit Esci (&X) - + &Emulation Emulazione - + &Reset Reset - + Sh&utdown Spegni (&U) - + Yank game pak Yank game pak - + &Pause Pausa - + &Next frame Salta il prossimo frame (&N) - + Fast forward (held) Avanzamento rapido (tieni premuto) - + &Fast forward Avanzamento rapido (&F) - + Fast forward speed Velocità di avanzamento rapido - + Unbounded Illimitata - + %0x %0x - + Rewind (held) Riavvolgimento (tieni premuto) - + Re&wind Riavvolgimento (&W) - + Step backwards Torna indietro - + Sync to &video Sincronizza con il video - + Sync to &audio Sincronizza con l'audio - + Solar sensor Sensore solare - + Increase solar level Aumenta il livello solare - + Decrease solar level Riduce il livello solare - + Brightest solar level Livello solare brillante - + Darkest solar level Livello solare più scuro - + Brightness %1 Luminosità %1 - + Audio/&Video Audio/Video - + Frame size Dimensioni Frame - + Toggle fullscreen Abilita Schermo Intero - + Lock aspect ratio Blocca rapporti aspetto - + Frame&skip Salto frame - + Mute Muto - + FPS target FPS finali - + Take &screenshot Acquisisci screenshot - + F12 F12 - + Record GIF/WebP/APNG... - + Registra GIF / WebP / APNG ... - + Video layers Layers video - + Audio channels Canali audio - + &Tools Strumenti - + View &logs... - Visualizza registri... (&L) + Visualizza (&Logs) &registri... - + Game &overrides... Valore specifico per il gioco... - + &Cheats... Trucchi... - + Open debugger console... Apri debugger console... - + Start &GDB server... Avvia server GDB... - + Settings... Impostazioni... - + Select folder Seleziona cartella - + Couldn't Start Non è stato possibile avviare - + Could not start game. - NOn è stato possibile avviare il gioco + Non è stato possibile avviare il gioco. - + Add folder to library... Aggiungi cartella alla libreria... - + Load state file... Carica stato di salvataggio... - + Save state file... Salva stato di salvataggio... - + Import GameShark Save... Importa Salvataggio GameShark... - + Export GameShark Save... Esporta Salvataggio GameShark... - + About... Informazioni… - + Force integer scaling Forza l'integer scaling - + Bilinear filtering Filtro bilineare - + Game Boy Printer... Stampante Game Boy... - + + Save games (%1) + + + + + Select save game + + + + + mGBA save state files (%1) + + + + + + Select save state + + + + + Load alternate save game... + + + + + Load temporary save game... + + + + BattleChip Gate... BattleChip Gate... - + %1× %1x - + Interframe blending Interframe blending - + Native (59.7275) Nativo (59.7) - + Record A/V... - Registra A/V + Registra A/V... - + Adjust layer placement... Regola posizionamento layer... - + Game Pak sensors... Sensori Game Pak... - + View &palette... Mostra palette... - + View &sprites... Mostra sprites... - + View &tiles... Mostra tiles... - + View &map... Mostra mappa... - + &Frame inspector... &Frame inspector... - + View memory... Mostra memoria... - + Search memory... Ricerca memoria... - + View &I/O registers... Mostra registri I/O... - + Record debug video log... Registra debug video log... - + Stop debug video log - Ferma debug video log... + Ferma debug video log - + Exit fullscreen Esci da Schermo Intero - + GameShark Button (held) Pulsante GameShark (tieni premuto) - + Autofire Pulsanti Autofire - + Autofire A Autofire A - + Autofire B Autofire B - + Autofire L Autofire L - + Autofire R Autofire R - + Autofire Start Autofire Start - + Autofire Select Autofire Select - + Autofire Up Autofire Su - + Autofire Right AAutofire Destra - + Autofire Down Autofire Giù - + Autofire Left Autofire Sinistra - + Clear Pulisci QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4702,17 +4797,17 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Generate Bug Report - + Genera segnalazione bug <html><head/><body><p>To file a bug report, please first generate a report file to attach to the bug report you're about to file. It is recommended that you include the save files, as these often help with debugging issues. This will collect some information about the version of {projectName} you're running, your configuration, your computer, and the game you currently have open (if any). Once this collection is completed you can review all of the information gathered below and save it to a zip file. The collection will automatically attempt to redact any personal information, such as your username if it's in any of the paths gathered, but just in case you can edit it afterwards. After you have generated and saved it, please click the button below or go to <a href="https://mgba.io/i/"><span style=" text-decoration: underline; color:#2980b9;">mgba.io/i</span></a> to file the bug report on GitHub. Make sure to attach the report you generated!</p></body></html> - + <html> <head/> <body> <p> Per presentare una segnalazione di bug, generare innanzitutto un file di report da allegare alla segnalazione di bug che si sta per presentare. Si consiglia di includere i file di salvataggio, poiché spesso aiutano con i problemi di debug. Verranno raccolte alcune informazioni sulla versione di {projectName} in esecuzione, sulla configurazione, sul computer e sul gioco attualmente aperto (se presente). Una volta completata questa raccolta è possibile esaminare tutte le informazioni raccolte di seguito e salvarle in un file zip. La raccolta tenterà automaticamente di redigere qualsiasi informazione personale, ad esempio il tuo nome utente se si trova in uno dei percorsi raccolti, ma nel caso in cui tu possa modificarla in seguito. Dopo averlo generato e salvato, fare clic sul pulsante sottostante o passare a <a href="https://mgba.io/i/"><span style=" text-decoration: underline; color:#2980b9;">mgba.io/i</span></a> per presentare la segnalazione di bug su GitHub. Assicurarsi di allegare il report generato! </p> </body> </html> Generate report - + Genera rapporto @@ -4722,16 +4817,120 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Open issue list in browser - + Apri l'elenco dei problemi nel browser Include save file - + Includi file di salvataggio Create and include savestate + Creare e includere lo stato di salvataggio + + + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + Sfoglia + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + SRAM + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game @@ -4948,7 +5147,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Fast forward volume: - Volume modalità accelerata + Volume modalità accelerata: @@ -5019,17 +5218,33 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Dynamically update window title - + Aggiorna dinamicamente il titolo della finestra Enable Discord Rich Presence Abilita Discord Rich Presence + + + Save state extra data: + + + + + + Save game + + + + + Load state extra data: + + Super Game Boy/Game Boy Color model: - + Modello Super Game Boy / Game Boy Color: @@ -5039,7 +5254,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Show filename instead of ROM name in title bar - + Mostra nome file anziché nome ROM nella barra del titolo @@ -5049,7 +5264,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Enable Game Boy Player features by default - + Abilitare le funzionalità di Game Boy Player per impostazione predefinita @@ -5109,7 +5324,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Super Game Boy model: - Modello Super GameBoy + Modello Super GameBoy: @@ -5144,17 +5359,17 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Game Boy-only model: - + Modello solo per Game Boy: Game Boy Color-only model: - + Modello solo per Game Boy Color: Game Boy/Game Boy Color model: - + Modello Game Boy / Game Boy Color: @@ -5251,12 +5466,6 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Screenshot Screenshot - - - - Save data - Salva dati - @@ -5333,16 +5542,6 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Idle loops: Idle loops: - - - Savestate extra data: - Dati extra salvataggio stato: - - - - Load extra data: - Carica dati extra: - Preload entire ROM into memory @@ -5449,17 +5648,17 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. Modifica le Scorciatoie - + Keyboard Tastiera - + Gamepad Gamepad - + Clear Svuota diff --git a/src/platform/qt/ts/mgba-en.ts b/src/platform/qt/ts/mgba-en.ts index dc53acb0a..ebc481dfd 100644 --- a/src/platform/qt/ts/mgba-en.ts +++ b/src/platform/qt/ts/mgba-en.ts @@ -25,7 +25,7 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. @@ -1134,6 +1134,14 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + + QGBA::AboutScreen + + + 2021 + + + QGBA::AssetTile @@ -1223,17 +1231,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::CoreManager - + Failed to open game file: %1 - + Could not load game. Are you sure it's in the correct format? - + Failed to open save file. Is the save directory writable? @@ -1241,52 +1249,52 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::FrameView - + Export frame - + Portable Network Graphics (*.png) - + None - + Background - + Window - + Objwin - + Sprite - + Backdrop - + Frame - + %1 %2 @@ -1294,7 +1302,7 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::GBAApp - + Enable Discord Rich Presence @@ -3485,62 +3493,62 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::MemoryModel - + Copy selection - + Save selection - + Paste - + Load - + All - + Load TBL - + Save selected memory - + Failed to open output file: %1 - + Load memory - + Failed to open input file: %1 - + TBL - + ISO-8859-1 @@ -3710,16 +3718,79 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3863,17 +3934,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 - + Native (%0x%1) - + Select output file @@ -3881,722 +3952,746 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - - + + + Select ROM - + Select folder - - Game Boy Advance save files (%1) - - - - - - + + Select save - - mGBA savestate files (%1) - - - - - - Select savestate - - - - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - - + + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - - Load alternate save... + + Save games (%1) - - Load temporary save... + + Select save game - + + mGBA save state files (%1) + + + + + + Select save state + + + + + Load alternate save game... + + + + + Load temporary save game... + + + + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + + Convert save game... + + + + Import GameShark Save... - + Export GameShark Save... - + New multiplayer window - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Sync to &video - + Sync to &audio - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4732,6 +4827,110 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5181,7 +5380,18 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - Savestate extra data: + Save state extra data: + + + + + + Save game + + + + + Load state extra data: @@ -5190,23 +5400,12 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. Screenshot - - - - Save data - - Cheat codes - - - Load extra data: - - Enable Game Boy Player features by default @@ -5446,17 +5645,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - + Keyboard - + Gamepad - + Clear diff --git a/src/platform/qt/ts/mgba-fr.ts b/src/platform/qt/ts/mgba-fr.ts index bf6821b58..e1f79b724 100644 --- a/src/platform/qt/ts/mgba-fr.ts +++ b/src/platform/qt/ts/mgba-fr.ts @@ -25,9 +25,9 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 – 2020 Jeffrey Pfau, sous la licence publique de Mozilla, version 2.0 + © 2013 – {year} Jeffrey Pfau, sous la licence publique de Mozilla, version 2.0 Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. @@ -1136,6 +1136,14 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.Agrandissement + + QGBA::AboutScreen + + + 2021 + 2021 + + QGBA::AssetTile @@ -1225,17 +1233,17 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. QGBA::CoreManager - + Failed to open game file: %1 Échec de l'ouverture du fichier de jeu : %1 - + Could not load game. Are you sure it's in the correct format? Impossible de charger le jeu. Êtes-vous sûr qu'il est dans le bon format ? - + Failed to open save file. Is the save directory writable? Impossible d'ouvrir le fichier de sauvegarde. Le répertoire de sauvegarde est-il accessible en écriture ? @@ -1243,52 +1251,52 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. QGBA::FrameView - + Export frame Exporter l'image - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Aucun - + Background Arrière plan - + Window Fenêtre - + Objwin - + Sprite Sprite - + Backdrop Toile de fond - + Frame - + %1 %2 %1 %2 @@ -1296,7 +1304,7 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. QGBA::GBAApp - + Enable Discord Rich Presence Activer intégration avec Discord @@ -3505,62 +3513,62 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. QGBA::MemoryModel - + Copy selection Copier la sélection - + Save selection Sauvegarder la sélection - + Paste Coller - + Load Charger - + All Tout - + Load TBL Charger le TBL - + Save selected memory Sauvegarder la mémoire sélectionné - + Failed to open output file: %1 Impossible d'ouvrir le fichier de sortie : %1 - + Load memory Charger la mémoire - + Failed to open input file: %1 Impossible d'ouvrir le fichier d'entrée : %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3730,16 +3738,79 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. QGBA::ReportView - + Bug report archive Archive de signalement d'erreur - + ZIP archive (*.zip) Archive ZIP (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3883,17 +3954,17 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 Impossible d'ouvrir le fichier vidéo de sortie : %1 - + Native (%0x%1) Natif (%0x%1) - + Select output file Choisir le fichier de sortie @@ -3901,118 +3972,101 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. QGBA::Window - + Game Boy Advance ROMs (%1) ROMs de Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs de Game Boy (%1) - + All ROMs (%1) Toutes les ROM (%1) - + %1 Video Logs (*.mvl) %1 Journaux vidéo (*.mvl) - + Archives (%1) Archives (%1) - - - + + + Select ROM Choisir une ROM - + Select folder Choisir un dossier - - Game Boy Advance save files (%1) - Fichiers de sauvegarde Game Boy Advance (%1) - - - - - + + Select save Choisir une sauvegarde - - mGBA savestate files (%1) - mGBA fichiers d'état (%1) - - - - - Select savestate - Sélectionner un fichier d'état - - - + Select patch Sélectionner un correctif - + Patches (*.ips *.ups *.bps) Correctifs/Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode Sélectionnez le numéro de point du e-Reader - + e-Reader card (*.raw *.bin *.bmp) e-Reader carte (*.raw *.bin *.bmp) - + Select image Choisir une image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Image (*.png *.gif *.jpg *.jpeg);;Tous les fichiers (*) - - + + GameShark saves (*.sps *.xps) Sauvegardes GameShark (*.sps *.xps) - + Select video log Sélectionner un journal vidéo - + Video logs (*.mvl) Journaux vidéo (*.mvl) - + Crash Plantage - + The game has crashed with the following error: %1 @@ -4021,604 +4075,645 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. - + Unimplemented BIOS call Requête au BIOS non supporté - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Ce jeu utilise un appel BIOS qui n'est pas implémenté. Veuillez utiliser le BIOS officiel pour une meilleure expérience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Échec de la création d'un périphérique d'affichage approprié, retour à l'affichage du logiciel. Les jeux peuvent fonctionner lentement, en particulier avec des fenêtres plus grandes. - + Really make portable? Vraiment rendre portable ? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Cela amènera l'émulateur à charger sa configuration depuis le même répertoire que l'exécutable. Souhaitez vous continuer ? - + Restart needed Un redémarrage est nécessaire - + Some changes will not take effect until the emulator is restarted. Certains changements ne prendront effet qu'après le redémarrage de l'émulateur. - + - Player %1 of %2 - Joueur %1 of %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Fichier - + Load &ROM... Charger une &ROM… - + Load ROM in archive... Charger la ROM d'une archive… - + Add folder to library... Ajouter un dossier à la bibliothèque… - - Load alternate save... - Charger une sauvegarde alternative… - - - - Load temporary save... - Charger une sauvegarde temporaire… - - - + Load &patch... Charger un c&orrectif… - + Boot BIOS Démarrer le BIOS - + Replace ROM... Remplacer la ROM… - + ROM &info... &Infos sur la ROM… - + Recent Récent - + Make portable Rendre portable - + &Load state &Charger un état - + &Save state &Sauvegarder un état - + Quick load Chargement rapide - + Quick save Sauvegarde rapide - + Load recent Charger un fichier récent - + Save recent Sauvegarder un fichier récent - + Undo load state Annuler le chargement de l'état - + Undo save state Annuler la sauvegarde de l'état - - + + State &%1 État &%1 - + Load camera image... Charger une image de la caméra… - + + Convert save game... + + + + New multiplayer window Nouvelle fenêtre multijoueur - + Report bug... Signalement de l'erreur… - + E&xit &Quitter - + &Emulation &Émulation - + &Reset &Réinitialiser - + Sh&utdown Extin&ction - + Yank game pak Yank game pak - + &Pause &Pause - + &Next frame &Image suivante - + Fast forward (held) Avance rapide (maintenir) - + &Fast forward A&vance rapide - + Fast forward speed Vitesse de l'avance rapide - + Unbounded Sans limites - + %0x %0x - + Rewind (held) Rembobiner (maintenir) - + Re&wind Rem&bobiner - + Step backwards Retour en arrière - + Sync to &video Synchro &vidéo - + Sync to &audio Synchro &audio - + Solar sensor Capteur solaire - + Increase solar level Augmenter le niveau solaire - + Decrease solar level Diminuer le niveau solaire - + Brightest solar level Tester le niveau solaire - + Darkest solar level Assombrir le niveau solaire - + Brightness %1 Luminosité %1 - + Audio/&Video Audio/&Vidéo - + Frame size Taille de l'image - + Toggle fullscreen Basculer en plein écran - + Lock aspect ratio Bloquer les proportions - + Force integer scaling Forcer la mise à l'échelle par des nombres entiers - + Bilinear filtering Filtrage bilinèaire - + Frame&skip &Saut d'image - + Mute Muet - + FPS target FPS ciblé - + Take &screenshot Prendre une ca&pture d'écran - + F12 F12 - + Game Boy Printer... Imprimante GameBoy… - + Video layers Couches vidéo - + Audio channels Canaux audio - + Adjust layer placement... Ajuster la disposition… - + &Tools Ou&tils - + View &logs... Voir les &journaux… - + Game &overrides... - + Couldn't Start N'a pas pu démarrer - + + Save games (%1) + + + + + Select save game + + + + + mGBA save state files (%1) + + + + + + Select save state + + + + Could not start game. Impossible de démarrer le jeu. - + + Load alternate save game... + + + + + Load temporary save game... + + + + Scan e-Reader dotcodes... Scanner les dotcodes e-Reader... - + Load state file... Charger le fichier d'état... - + Save state file... Enregistrer le fichier d'état... - + Import GameShark Save... Importer la sauvegarde de GameShark... - + Export GameShark Save... Exporter la sauvegarde de GameShark... - + About... À propos de… - + BattleChip Gate... - + %1× %1× - + Interframe blending Mélange d'images - + Native (59.7275) Natif (59.7275) - + Record A/V... Enregistrer A/V... - + Record GIF/WebP/APNG... Enregistrer GIF/WebP/APNG... - + Game Pak sensors... Capteurs de la Game Pak... - + &Cheats... &Cheats… - + Settings... Paramètres… - + Open debugger console... Ouvrir la console de débug… - + Start &GDB server... Démarrer le serveur &GDB… - + View &palette... Voir la &palette… - + View &sprites... Voir les &sprites… - + View &tiles... Voir les &tiles… - + View &map... Voir la &map… - + &Frame inspector... Inspecteur de &frame... - + View memory... Voir la mémoire… - + Search memory... Recherche dans la mémoire… - + View &I/O registers... Voir les registres d'&E/S... - + Record debug video log... Enregistrer le journal vidéo de débogage... - + Stop debug video log Arrêter le journal vidéo de débogage - + Exit fullscreen Quitter le plein écran - + GameShark Button (held) Bouton GameShark (maintenir) - + Autofire Tir automatique - + Autofire A Tir automatique A - + Autofire B Tir automatique B - + Autofire L Tir automatique L - + Autofire R Tir automatique R - + Autofire Start Tir automatique Start - + Autofire Select Tir automatique Select - + Autofire Up Tir automatique Up - + Autofire Right Tir automatique Right - + Autofire Down Tir automatique Down - + Autofire Left Tir automatique Gauche - + Clear Vider QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4754,6 +4849,110 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.Créer et inclure l'état de sauvegarde + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + Parcourir + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + SRAM + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5036,6 +5235,22 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.Dynamically update window title + + + Save state extra data: + + + + + + Save game + + + + + Load state extra data: + + Enable Game Boy Player features by default @@ -5232,34 +5447,18 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.Detect and remove Détecter et supprimer - - - Savestate extra data: - Enregistrer des données supplémentaires : - Screenshot Capture d'écran - - - - Save data - Sauvegarder les données - Cheat codes Codes de triches - - - Load extra data: - Chargez des données supplémentaires : - Preload entire ROM into memory @@ -5469,17 +5668,17 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.Modifier les raccourcis - + Keyboard Clavier - + Gamepad Manette de jeu - + Clear Vider diff --git a/src/platform/qt/ts/mgba-ja.ts b/src/platform/qt/ts/mgba-ja.ts index 897936a18..a32606ec1 100644 --- a/src/platform/qt/ts/mgba-ja.ts +++ b/src/platform/qt/ts/mgba-ja.ts @@ -25,9 +25,9 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 – 2020 Jeffrey Pfau。Mozilla Public License(バージョン2.0)の下でライセンスされています。 + © 2013 – {year} Jeffrey Pfau。Mozilla Public License(バージョン2.0)の下でライセンスされています。 「ゲームボーイアドバンス」、GAME BOY ADVANCEは任天堂株式会社の登録商標です。 @@ -1135,6 +1135,14 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. 倍率 + + QGBA::AboutScreen + + + 2021 + 2021 + + QGBA::AssetTile @@ -1224,17 +1232,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::CoreManager - + Failed to open game file: %1 ゲームファイルを開けませんでした: %1 - + Could not load game. Are you sure it's in the correct format? ゲームをロードできませんでした。ゲームのフォーマットが正しいことを確認してください。 - + Failed to open save file. Is the save directory writable? セーブファイルを開けませんでした。セーブディレクトリが書き込み可能であることを確認してください。 @@ -1242,52 +1250,52 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::FrameView - + Export frame フレームを書き出す - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None なし - + Background バックグラウンド - + Window ウインドウ - + Objwin Objwin - + Sprite スプライト - + Backdrop 背景 - + Frame フレーム - + %1 %2 %1 %2 @@ -1295,7 +1303,7 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::GBAApp - + Enable Discord Rich Presence DiscordのRich Presence有効 @@ -3486,62 +3494,62 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::MemoryModel - + Copy selection 選択値をコピー - + Save selection 選択値を保存 - + Paste 貼り付け - + Load ロード - + All All - + Load TBL TBLをロード - + Save selected memory 選択したメモリを保存 - + Failed to open output file: %1 出力ファイルを開けませんでした: %1 - + Load memory メモリをロード - + Failed to open input file: %1 入力ファイルを開けませんでした: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3711,16 +3719,79 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::ReportView - + Bug report archive バグレポートアーカイブ - + ZIP archive (*.zip) ZIPアーカイブ (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3864,17 +3935,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 出力ビデオファイルを開けませんでした: %1 - + Native (%0x%1) ネイティブ(%0x%1) - + Select output file 出力ファイルを選択 @@ -3882,118 +3953,101 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::Window - + Game Boy Advance ROMs (%1) ゲームボーイアドバンスファイル (%1) - + Game Boy ROMs (%1) ゲームボーイファイル (%1) - + All ROMs (%1) すべてのファイル (%1) - + %1 Video Logs (*.mvl) %1ビデオログ (*.mvl) - + Archives (%1) アーカイブファイル (%1) - - - + + + Select ROM ROMを開く - + Select folder フォルダを開く - - Game Boy Advance save files (%1) - ゲームボーイアドバンスセーブファイル (%1) - - - - - + + Select save セーブを開く - - mGBA savestate files (%1) - mGBAセーブステートファイル (%1) - - - - - Select savestate - セーブステートを開く - - - + Select patch パッチを開く - + Patches (*.ips *.ups *.bps) パッチファイル (*.ips *.ups *.bps) - + Select e-Reader dotcode カードeを開く - + e-Reader card (*.raw *.bin *.bmp) カードe (*.raw *.bin *.bmp) - + Select image 画像を開く - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 画像ファイル (*.png *.gif *.jpg *.jpeg);;すべてのファイル (*) - - + + GameShark saves (*.sps *.xps) GameSharkセーブファイル (*.sps *.xps) - + Select video log ビデオログを開く - + Video logs (*.mvl) ビデオログ (*.mvl) - + Crash クラッシュ - + The game has crashed with the following error: %1 @@ -4002,604 +4056,645 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. %1 - + Couldn't Start 起動失敗 - + Could not start game. ゲームを起動できませんでした。 - + Unimplemented BIOS call 未実装のBIOS呼び出し - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. このゲームは実装されていないBIOS呼び出しを使用します。最高のエクスペリエンスを得るには公式のBIOSを使用してください。 - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. 適切なディスプレイデバイスの作成に失敗し、ソフトディスプレイにフォールバックしました。特に大きなウィンドウでは、ゲームの実行が遅い場合があります。 - + Really make portable? 本当にポータブルにしますか? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? これによりエミュレータは実行ファイルと同じディレクトリにある設定ファイルをロードします。続けますか? - + Restart needed 再起動が必要 - + Some changes will not take effect until the emulator is restarted. 一部の変更は、エミュレータを再起動するまで有効になりません。 - + - Player %1 of %2 - プレーヤー %1 of %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &ファイル (&F) - + Load &ROM... ROMをロード... - + Load ROM in archive... アーカイブにROMをロード... - + Add folder to library... ライブリーにフォルダを追加... - - Load alternate save... - 別のセーブをロード... - - - - Load temporary save... - 一時セーブをロード... - - - + Load &patch... パッチをロード... (&P) - + Boot BIOS BIOSを起動 - + Replace ROM... ROMを交換... - + Scan e-Reader dotcodes... カードeをスキャン... - + ROM &info... ROM情報... (&I) - + Recent 最近開いたROM - + Make portable ポータブル化 - + &Load state ステートをロード (&L) - + Report bug... バグ報告 - + About... バージョン情報... - + Record GIF/WebP/APNG... GIF/WebP/APNGを記録 - + Game Pak sensors... カートリッジセンサー... - + Clear 消去 - + Load state file... ステートファイルをロード... - + + Save games (%1) + + + + + Select save game + + + + + mGBA save state files (%1) + + + + + + Select save state + + + + + Load alternate save game... + + + + + Load temporary save game... + + + + &Save state ステートをセーブ (&S) - + Save state file... ステートファイルをセーブ... - + Quick load クイックロード - + Quick save クイックセーブ - + Load recent 最近使ったクイックロットからロード - + Save recent 最近使ったクイックロットにセーブ - + Undo load state クイックロードを元に戻す - + Undo save state クイックセーブを元に戻す - - + + State &%1 クイックスロット &%1 - + Load camera image... カメラ画像をロード... - + + Convert save game... + + + + Import GameShark Save... GameSharkスナップショットを読み込む - + Export GameShark Save... GameSharkスナップショットを書き出す - + New multiplayer window 新しいウィンドウ(マルチプレイ) - + E&xit 終了 (&X) - + &Emulation エミュレーション (&E) - + &Reset リセット (&R) - + Sh&utdown 閉じる (&U) - + Yank game pak ゲームパックをヤンク - + &Pause 一時停止 (&P) - + &Next frame 次のフレーム (&N) - + Fast forward (held) 早送り(押し) - + &Fast forward 早送り (&F) - + Fast forward speed 早送り速度 - + Unbounded 制限なし - + %0x %0x - + Rewind (held) 巻戻し(押し) - + Re&wind 巻戻し (&R) - + Step backwards 後退 - + Sync to &video ビデオ同期 (&V) - + Sync to &audio オーディオ同期 (&A) - + Solar sensor 太陽センサー - + Increase solar level 明るさを上げる - + Decrease solar level 明るさを下げる - + Brightest solar level 明るさ最高 - + Darkest solar level 明るさ最低 - + Brightness %1 明るさ %1 - + Audio/&Video オーディオ/ビデオ (&V) - + Frame size 画面サイズ - + Toggle fullscreen 全画面表示 - + Lock aspect ratio 縦横比を固定 - + Force integer scaling 整数スケーリングを強制 - + Bilinear filtering バイリニアフィルタリング - + Frame&skip フレームスキップ (&S) - + Mute ミュート - + FPS target FPS - + Native (59.7275) ネイティブ(59.7275) - + Take &screenshot スクリーンショット (&S) - + F12 F12 - + Game Boy Printer... ポケットプリンタ... - + BattleChip Gate... チップゲート... - + %1× %1× - + Interframe blending フレーム間混合 - + Record A/V... ビデオ録画... - + Video layers ビデオレイヤー - + Audio channels オーディオチャンネル - + Adjust layer placement... レイヤーの配置を調整... - + &Tools ツール (&T) - + View &logs... ログビューアー... (&L) - + Game &overrides... ゲーム別設定... (&O) - + &Cheats... チート... (&C) - + Settings... 設定... - + Open debugger console... デバッガコンソールを開く... - + Start &GDB server... GDBサーバを起動... (&G) - + View &palette... パレットビューアー... (&P) - + View &sprites... スプライトビューアー... (&S) - + View &tiles... タイルビューアー... (&T) - + View &map... マップビューアー... (&M) - + &Frame inspector... フレームインスペクタ... (&F) - + View memory... メモリビューアー... - + Search memory... メモリ検索... - + View &I/O registers... IOビューアー... (&I) - + Record debug video log... デバッグビデオログ... - + Stop debug video log デバッグビデオログを停止 - + Exit fullscreen 全画面表示を終了 - + GameShark Button (held) GameSharkボタン(押し) - + Autofire 連打 - + Autofire A 連打 A - + Autofire B 連打 B - + Autofire L 連打 L - + Autofire R 連打 R - + Autofire Start 連打 Start - + Autofire Select 連打 Select - + Autofire Up 連打 上 - + Autofire Right 連打 右 - + Autofire Down 連打 下 - + Autofire Left 連打 左 QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4735,6 +4830,110 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. セーブステートファイルを作成して含める + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + 参照 + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + SRAM + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5041,6 +5240,22 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. Fast forward (held) speed: 早送り(押し)速度: + + + Save state extra data: + + + + + + Save game + + + + + Load state extra data: + + Enable Game Boy Player features by default @@ -5217,34 +5432,18 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. Detect and remove 検出して削除 - - - Savestate extra data: - セーブステートの追加データ: - Screenshot スクリーンショット - - - - Save data - セーブデータ - Cheat codes チートコード - - - Load extra data: - 追加データをロード: - Preload entire ROM into memory @@ -5449,17 +5648,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. ショートカットキーを編集 - + Keyboard キーボード - + Gamepad ゲームパッド - + Clear 削除 diff --git a/src/platform/qt/ts/mgba-ko.ts b/src/platform/qt/ts/mgba-ko.ts index 684d9a4db..269009b14 100644 --- a/src/platform/qt/ts/mgba-ko.ts +++ b/src/platform/qt/ts/mgba-ko.ts @@ -20,9 +20,9 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 - 2020 Jeffrey Pfau, 모질라 공식 라이센스 버전 2.0에 따라 사용 허가되었습니다. + © 2013 - {year} Jeffrey Pfau, 모질라 공식 라이센스 버전 2.0에 따라 사용 허가되었습니다. Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. @@ -1135,6 +1135,14 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. + + QGBA::AboutScreen + + + 2021 + 2021 + + QGBA::AssetTile @@ -1224,17 +1232,17 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. QGBA::CoreManager - + Failed to open game file: %1 게임 파일을 열지 못했습니다: %1 - + Could not load game. Are you sure it's in the correct format? 게임을 로드할 수 없습니다. 올바른 형식인지 확인하십시오. - + Failed to open save file. Is the save directory writable? @@ -1242,52 +1250,52 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. QGBA::FrameView - + Export frame - + Portable Network Graphics (*.png) 휴대용 네트워크 그래픽 (*.png) - + None 없음 - + Background 배경 - + Window - + Objwin - + Sprite - + Backdrop - + Frame - + %1 %2 %1x {1 %2?} @@ -1295,7 +1303,7 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. QGBA::GBAApp - + Enable Discord Rich Presence @@ -3486,62 +3494,62 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. QGBA::MemoryModel - + Copy selection 선택 항목 복사 - + Save selection 선택 항목 저장 - + Paste 붙여넣기 - + Load 로드 - + All 모두 - + Load TBL 테이블 로드 - + Save selected memory 선택한 메모리 저장 - + Failed to open output file: %1 출력 파일을 열지 못했습니다: %1 - + Load memory 메모리 로드 - + Failed to open input file: %1 입력 파일을 열지 못했습니다: %1 - + TBL 테이블 - + ISO-8859-1 ISO-8859-1 @@ -3711,16 +3719,79 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3864,17 +3935,17 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. QGBA::VideoView - + Failed to open output video file: %1 출력 비디오 파일을 열지 못했습니다: %1 - + Native (%0x%1) 기본 (%0x%1) - + Select output file 출력 파일 선택 @@ -3882,113 +3953,96 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. QGBA::Window - + Game Boy Advance ROMs (%1) 게임 보이 어드밴스 롬 (%1) - + Game Boy ROMs (%1) 게임 보이 (%1) - + All ROMs (%1) 모든 롬 (%1) - + %1 Video Logs (*.mvl) %1 비디오 로그 (*.mvl) - + Archives (%1) 아카이브 (%1) - - - + + + Select ROM 롬 선택 - - Game Boy Advance save files (%1) - 게임 보이 어드밴스 저장 파일 (%1) - - - - - + + Select save 저장 파일 선택 - - mGBA savestate files (%1) - - - - - - Select savestate - - - - + Select patch 패치 선택 - + Patches (*.ips *.ups *.bps) 패치 (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image 이미지 선택 - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 이미지 파일 (*.png *.gif *.jpg *.jpeg);;모든 파일 (*) - - + + GameShark saves (*.sps *.xps) 게임샤크 저장 파일 (*.sps *.xps) - + Select video log 비디오 로그 선택 - + Video logs (*.mvl) 비디오 로그 (*.mvl) - + Crash 치명적인 오류 - + The game has crashed with the following error: %1 @@ -3997,609 +4051,650 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. %1 - + Unimplemented BIOS call 구현되지 않은 바이오스 호출 - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. 이 게임은 구현되지 않은 바이오스 호출을 사용합니다. 최상의 성능을 얻으려면 공식 바이오스를 사용하십시오. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? 정말로 휴대용을 만듭니까? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? 이렇게하면 에뮬레이터가 실행 파일과 동일한 디렉토리에서 구성을 로드하게됩니다. 계속 하시겠습니까? - + Restart needed 재시작 필요 - + Some changes will not take effect until the emulator is restarted. 일부 변경 사항은 에뮬레이터가 다시 시작될 때까지 적용되지 않습니다. - + - Player %1 of %2 - 플레이어 %1 의 %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &파일 - + Load &ROM... 로드 &롬... - + Load ROM in archive... 롬을 아카이브에 로드... - - Load alternate save... - 대체 저장 로드... - - - - Load temporary save... - 임시 저장 로드... - - - + Load &patch... 로드 &패치... - + Boot BIOS BIOS 부팅 - + Replace ROM... 롬 교체... - + Scan e-Reader dotcodes... - + ROM &info... 롬 &정보... - + Recent 최근 실행 - + Make portable 휴대용 만들기 - + &Load state &로드 파일 상태 - + &Save state &저장 파일 상태 - + Quick load 빠른 로드 - + Quick save 빠른 저장 - + Load recent 최근 실행 로드 - + Save recent 최근 실행 저장 - + Undo load state 로드 파일 상태 복원 - + Undo save state 저장 파일 상태 복원 - - + + State &%1 상태 &%1 - + Load camera image... 카메라 이미지 로드... - + + Convert save game... + + + + New multiplayer window 새로운 멀티 플레이어 창 - + E&xit 종&료 - + &Emulation &에뮬레이션 - + &Reset &재설정 - + Sh&utdown 종&료 - + Yank game pak 양키 게임 팩 - + &Pause &정지 - + &Next frame &다음 프레임 - + Fast forward (held) 빨리 감기 (누름) - + &Fast forward &빨리 감기 - + Fast forward speed 빨리 감기 속도 - + Unbounded 무제한 - + %0x %0x - + Rewind (held) 되김기 (누름) - + Re&wind 리&와인드 - + Step backwards 돌아가기 - + Sync to &video 비디오 &동기화 - + Sync to &audio 오디오 &동기화 - + Brightest solar level 가장 밝은 태양 수준 - + Darkest solar level 가장 어두운 태양 수준 - + Brightness %1 밝기 %1 - + Audio/&Video 오디오/&비디오 - + Frame size 프레임 크기 - + Toggle fullscreen 전체화면 전환 - + Lock aspect ratio 화면비 잠금 - + Frame&skip 프레임&건너뛰기 - + Mute 무음 - + FPS target FPS 대상 - + Take &screenshot 스크린샷 &찍기 - + F12 F12 - + Video layers 비디오 레이어 - + Audio channels 오디오 채널 - + &Tools &도구 - + View &logs... 로그 &보기... - + Game &overrides... 게임 &오버라이드... - + &Cheats... &치트.. - + Open debugger console... 디버거 콘솔 열기... - + Start &GDB server... GDB 서버 &시작... - + Settings... 설정... - + Select folder 폴더 선택 - + Couldn't Start - + Could not start game. - + Add folder to library... 라이브러리에 폴더 추가... - + Load state file... - + Save state file... - + Import GameShark Save... - + Export GameShark Save... - + Report bug... - + About... - + Solar sensor - + Increase solar level - + Decrease solar level - + Force integer scaling 정수 스케일링 강제 수행 - + Bilinear filtering 이중선형 필터링 - + Game Boy Printer... 게임 보이 프린터... - + + Save games (%1) + + + + + Select save game + + + + + mGBA save state files (%1) + + + + + + Select save state + + + + + Load alternate save game... + + + + + Load temporary save game... + + + + BattleChip Gate... - + %1× %1x {1×?} - + Interframe blending - + Native (59.7275) Nativo (59.7) {59.7275)?} - + Record A/V... - + Record GIF/WebP/APNG... - + Adjust layer placement... 레이어 배치 조정... - + Game Pak sensors... - + View &palette... 팔레트 &보기... - + View &sprites... 스프라이트 &보기... - + View &tiles... 타일 &보기... - + View &map... 지도 &보기... - + &Frame inspector... - + View memory... 메모리 보기... - + Search memory... 메모리 검색... - + View &I/O registers... I/O 레지스터 &보기... - + Record debug video log... - + Stop debug video log - + Exit fullscreen 전체화면 종료 - + GameShark Button (held) 게임샤크 버튼 (누름) - + Autofire 연사 - + Autofire A 연사 A - + Autofire B 연사 B - + Autofire L 연사 L - + Autofire R 연사 R - + Autofire Start 연사 시작 - + Autofire Select - + Clear 정리 - + Autofire Up 연사 위쪽 - + Autofire Right 연사 오른쪽 - + Autofire Down 연사 아래쪽 - + Autofire Left 연사 왼쪽 QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4735,6 +4830,110 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + 브라우저 + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + SRAM + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5041,6 +5240,22 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. Fast forward (held) speed: + + + Save state extra data: + + + + + + Save game + + + + + Load state extra data: + + Enable Game Boy Player features by default @@ -5251,12 +5466,6 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. Screenshot 스크린샷 - - - - Save data - 저장 데이터 - @@ -5333,16 +5542,6 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. Idle loops: Idle loops: - - - Savestate extra data: - 추가 데이터 저장상태: - - - - Load extra data: - 추가 데이터 로드: - Preload entire ROM into memory @@ -5449,17 +5648,17 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. 단축키 수정 - + Keyboard 키보드 - + Gamepad 게임패드 - + Clear 정리 diff --git a/src/platform/qt/ts/mgba-nl.ts b/src/platform/qt/ts/mgba-nl.ts index fd69523df..caaa8f697 100644 --- a/src/platform/qt/ts/mgba-nl.ts +++ b/src/platform/qt/ts/mgba-nl.ts @@ -25,7 +25,7 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. @@ -1134,6 +1134,14 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + + QGBA::AboutScreen + + + 2021 + + + QGBA::AssetTile @@ -1223,17 +1231,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::CoreManager - + Failed to open game file: %1 - + Could not load game. Are you sure it's in the correct format? - + Failed to open save file. Is the save directory writable? @@ -1241,52 +1249,52 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::FrameView - + Export frame - + Portable Network Graphics (*.png) - + None - + Background - + Window - + Objwin - + Sprite - + Backdrop - + Frame - + %1 %2 @@ -1294,7 +1302,7 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::GBAApp - + Enable Discord Rich Presence @@ -3485,62 +3493,62 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::MemoryModel - + Copy selection - + Save selection - + Paste - + Load - + All - + Load TBL - + Save selected memory - + Failed to open output file: %1 - + Load memory - + Failed to open input file: %1 - + TBL - + ISO-8859-1 @@ -3710,16 +3718,79 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3863,17 +3934,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 - + Native (%0x%1) - + Select output file @@ -3881,722 +3952,746 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - - + + + Select ROM - + Select folder - - Game Boy Advance save files (%1) - - - - - - + + Select save - - mGBA savestate files (%1) - - - - - - Select savestate - - - - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - - + + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - - Load alternate save... + + Save games (%1) - - Load temporary save... + + Select save game - + + mGBA save state files (%1) + + + + + + Select save state + + + + + Load alternate save game... + + + + + Load temporary save game... + + + + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + + Convert save game... + + + + Import GameShark Save... - + Export GameShark Save... - + New multiplayer window - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Sync to &video - + Sync to &audio - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4732,6 +4827,110 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5088,6 +5287,22 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. Show FPS in title bar + + + Save state extra data: + + + + + + Save game + + + + + Load state extra data: + + Super Game Boy/Game Boy Color model: @@ -5184,34 +5399,18 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. Preload entire ROM into memory - - - Savestate extra data: - - Screenshot - - - - Save data - - Cheat codes - - - Load extra data: - - Enable Game Boy Player features by default @@ -5446,17 +5645,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - + Keyboard - + Gamepad - + Clear diff --git a/src/platform/qt/ts/mgba-pt_BR.ts b/src/platform/qt/ts/mgba-pt_BR.ts index af881d2c3..8f0373090 100644 --- a/src/platform/qt/ts/mgba-pt_BR.ts +++ b/src/platform/qt/ts/mgba-pt_BR.ts @@ -25,9 +25,9 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 – 2020 Jeffrey Pfau, licenciado sob a Licença Pública Mozilla, versão 2.0 + © 2013 – {year} Jeffrey Pfau, licenciado sob a Licença Pública Mozilla, versão 2.0 Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. @@ -1127,7 +1127,7 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. Copy - Copiar + Copiar @@ -1135,6 +1135,14 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. Ampliação + + QGBA::AboutScreen + + + 2021 + 2021 + + QGBA::AssetTile @@ -1224,17 +1232,17 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. QGBA::CoreManager - + Failed to open game file: %1 Falha ao abrir o arquivo do jogo: %1 - + Could not load game. Are you sure it's in the correct format? Não foi possível carregar o jogo. Tem certeza que está no formato correto? - + Failed to open save file. Is the save directory writable? Falha ao abrir o arquivo de salvamento. O diretório para salvar tem permissão de escrita? @@ -1242,52 +1250,52 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. QGBA::FrameView - + Export frame Exportar quadro - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Nenhum - + Background Plano de Fundo - + Window Janela - + Objwin - + Sprite Sprite - + Backdrop Cor de Fundo - + Frame - + %1 %2 %1 %2 @@ -1295,7 +1303,7 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. QGBA::GBAApp - + Enable Discord Rich Presence Habilitar o Discord Rich Presence @@ -3486,62 +3494,62 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. QGBA::MemoryModel - + Copy selection Copiar seleção - + Save selection Salvar seleção - + Paste Colar - + Load Carregar - + All Todos - + Load TBL Carregar TBL - + Save selected memory Salvar memória selecionada - + Failed to open output file: %1 Falha ao abrir arquivo de saída: %1 - + Load memory Carregar memória - + Failed to open input file: %1 Falha ao abrir arquivo de entrada: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3711,13 +3719,76 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) + Arquivo ZIP (*.zip) + + + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms @@ -3864,17 +3935,17 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 Falha ao abrir arquivo de vídeo de saída: %1 - + Native (%0x%1) Nativo (%0x%1) - + Select output file Selecione o arquivo de saída @@ -3882,118 +3953,101 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. QGBA::Window - + Game Boy Advance ROMs (%1) ROMs de Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs de Game Boy (%1) - + All ROMs (%1) Todas as ROMs (%1) - + %1 Video Logs (*.mvl) %1 Logs de Vídeo (*.mvl) - + Archives (%1) Arquivos (%1) - - - + + + Select ROM Selecionar ROM - + Select folder Selecionar pasta - - Game Boy Advance save files (%1) - Arquivos salvos de Game Boy Advance (%1) - - - - - + + Select save Selecionar salvamento - - mGBA savestate files (%1) - Arquivos de savestate do mGBA (%1) - - - - - Select savestate - Selecionar savestate - - - + Select patch Selecione correção - + Patches (*.ips *.ups *.bps) Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode Selecione dotcode do e-Reader - + e-Reader card (*.raw *.bin *.bmp) e-Reader card (*.raw *.bin *.bmp) - + Select image Selecionar imagem - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Arquivo de imagem (*.png *.gif *.jpg *.jpeg);;Todos os arquivos (*) - - + + GameShark saves (*.sps *.xps) GameShark saves (*.sps *.xps) - + Select video log Selecionar registro de vídeo - + Video logs (*.mvl) Video logs (*.mvl) - + Crash Travamento - + The game has crashed with the following error: %1 @@ -4002,604 +4056,645 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. %1 - + Unimplemented BIOS call Chamada de BIOS não implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este jogo usa uma chamada de BIOS que não está implementada. Por favor, use a BIOS oficial para uma melhor experiência. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? Quer mesmo tornar portátil? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Isto fará com que o emulador carregue sua configuração a partir do mesmo diretório que o executável. Você quer continuar? - + Restart needed É necessário reiniciar - + Some changes will not take effect until the emulator is restarted. Algumas alterações não terão efeito até que o emulador seja reiniciado. - + - Player %1 of %2 - Jogador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Arquivo - + Load &ROM... Carregar &ROM... - + Load ROM in archive... Carregar ROM em arquivo... - + Add folder to library... Adicionar pasta à biblioteca... - - Load alternate save... - Carregar salvamento alternativo... - - - - Load temporary save... - Carregar salvamento temporário... - - - + Load &patch... Carregar &patch... - + Boot BIOS Rodar BIOS - + Replace ROM... Substituir ROM... - + ROM &info... &Informações da ROM... - + Recent Recente - + Make portable Tornar portátil - + &Load state &Carregar Estado - + Report bug... - + About... Sobre... - + Game Pak sensors... Sensores de Game Pak... - + Clear Limpar - + Load state file... Carregar arquivo de estado... - + + Save games (%1) + + + + + Select save game + + + + + mGBA save state files (%1) + + + + + + Select save state + + + + + Load alternate save game... + + + + + Load temporary save game... + + + + &Save state &Salvar Estado - + Save state file... Salvar arquivo de estado... - + Quick load Carregamento rápido - + Quick save Salvamento rápido - + Load recent Carregar recente - + Save recent Salvar recente - + Undo load state Desfazer carregar estado - + Undo save state Desfazer salvar estado - - + + State &%1 Estado &%1 - + Load camera image... Carregar imagem da câmera... - + + Convert save game... + + + + New multiplayer window Nova janela multijogador - + E&xit &Sair - + &Emulation &Emulação - + &Reset &Resetar - + Sh&utdown &Desligar - + Yank game pak Remover game pak - + &Pause &Pausar - + &Next frame &Próximo quadro - + Fast forward (held) Avançar rápido (segurado) - + &Fast forward Avanço &Rápido - + Fast forward speed Velocidade de avanço - + Unbounded Ilimitado - + %0x %0x - + Rewind (held) Retroceder (segurado) - + Re&wind Re&troceder - + Step backwards Voltar um passo - + Sync to &video Sincronizar para &vídeo - + Sync to &audio Sincronizar para &áudio - + Solar sensor Sensor solar - + Increase solar level Aumentar nível solar - + Decrease solar level Diminuir nível solar - + Brightest solar level Nível solar mais brilhante - + Darkest solar level Nível solar mais escuro - + Brightness %1 Brilho %1 - + Audio/&Video Áudio/&Vídeo - + Frame size Tamanho do quadro - + Toggle fullscreen Alternar tela cheia - + Lock aspect ratio Fixar proporção - + Force integer scaling Forçar dimensionamento inteiro - + Bilinear filtering Filtragem bilinear - + Frame&skip &Salto de quadro - + Mute Mudo - + FPS target Meta de FPS - + Native (59.7275) Nativo (59,7275) - + Take &screenshot Capturar &tela - + F12 F12 - + Game Boy Printer... Game Boy Printer... - + BattleChip Gate... BattleChip Gate... - + %1× %1× - + Interframe blending Interframe blending - + Record A/V... Gravar A/V... - + Video layers Camadas de vídeo - + Audio channels Canais de áudio - + Adjust layer placement... Ajustar posicionamento da camada... - + &Tools &Ferramentas - + View &logs... Visualizar &registros... - + Game &overrides... Game &overrides... - + Couldn't Start Não foi possível Iniciar - + Could not start game. Não foi possível iniciar o jogo. - + Scan e-Reader dotcodes... Escanear dotcode do e-Reader... - + Import GameShark Save... Importar salvamento do GameShark... - + Export GameShark Save... Exportar salvamento do GameShark... - + Record GIF/WebP/APNG... Gravar GIF/WebP/APNG... - + &Cheats... &Cheats... - + Settings... Configurações... - + Open debugger console... Abrir console de depuração... - + Start &GDB server... Iniciar servidor &GDB... - + View &palette... Visualizar &paleta... - + View &sprites... Visualizar &sprites... - + View &tiles... Visualizar &blocos... - + View &map... Visualizar &mapa... - + &Frame inspector... Inspetor de &quadro... - + View memory... Visualizar memória... - + Search memory... Pesquisar memória... - + View &I/O registers... Visualizar registros de &E/S... - + Record debug video log... Gravar log de vídeo de depuração... - + Stop debug video log Parar log de vídeo de depuração - + Exit fullscreen Sair da tela cheia - + GameShark Button (held) Botão de GameShark (segurado) - + Autofire Disparo automático - + Autofire A Disparo automático A - + Autofire B Disparo automático B - + Autofire L Disparo automático L - + Autofire R Disparo automático R - + Autofire Start Disparo automático Start - + Autofire Select Disparo automático Select - + Autofire Up Disparo automático Cima - + Autofire Right Disparo automático Direita - + Autofire Down Disparo automático Baixo - + Autofire Left Disparo automático Esquerda QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4717,7 +4812,7 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. Save - Salvar + Salvar @@ -4735,6 +4830,110 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + Navegar + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + SRAM + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5036,6 +5235,22 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. Show OSD messages Exibir mensagens OSD + + + Save state extra data: + + + + + + Save game + + + + + Load state extra data: + + Super Game Boy/Game Boy Color model: @@ -5212,34 +5427,18 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. Detect and remove Detectar e remover - - - Savestate extra data: - Savestate extra data: - Screenshot Captura de tela - - - - Save data - Salvar dados - Cheat codes Códigos de cheat - - - Load extra data: - Carregar dados extras: - Preload entire ROM into memory @@ -5449,17 +5648,17 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. Editar Atalhos - + Keyboard Teclado - + Gamepad Controle - + Clear Limpar diff --git a/src/platform/qt/ts/mgba-ru.ts b/src/platform/qt/ts/mgba-ru.ts index b20b53633..a35b0a9bd 100644 --- a/src/platform/qt/ts/mgba-ru.ts +++ b/src/platform/qt/ts/mgba-ru.ts @@ -25,7 +25,7 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. @@ -1134,6 +1134,14 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + + QGBA::AboutScreen + + + 2021 + + + QGBA::AssetTile @@ -1223,17 +1231,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::CoreManager - + Failed to open game file: %1 - + Could not load game. Are you sure it's in the correct format? - + Failed to open save file. Is the save directory writable? @@ -1241,52 +1249,52 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::FrameView - + Export frame - + Portable Network Graphics (*.png) - + None - + Background - + Window - + Objwin - + Sprite - + Backdrop - + Frame - + %1 %2 @@ -1294,7 +1302,7 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::GBAApp - + Enable Discord Rich Presence @@ -3485,62 +3493,62 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::MemoryModel - + Copy selection - + Save selection - + Paste - + Load - + All - + Load TBL - + Save selected memory - + Failed to open output file: %1 - + Load memory - + Failed to open input file: %1 - + TBL - + ISO-8859-1 @@ -3710,16 +3718,79 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3863,17 +3934,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 - + Native (%0x%1) - + Select output file @@ -3881,722 +3952,746 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - - + + + Select ROM - + Select folder - - Game Boy Advance save files (%1) - - - - - - + + Select save - - mGBA savestate files (%1) - - - - - - Select savestate - - - - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - - + + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - - Load alternate save... + + Save games (%1) - - Load temporary save... + + Select save game - + + mGBA save state files (%1) + + + + + + Select save state + + + + + Load alternate save game... + + + + + Load temporary save game... + + + + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + + Convert save game... + + + + Import GameShark Save... - + Export GameShark Save... - + New multiplayer window - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Sync to &video - + Sync to &audio - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4732,6 +4827,110 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5088,6 +5287,22 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. Show FPS in title bar + + + Save state extra data: + + + + + + Save game + + + + + Load state extra data: + + Super Game Boy/Game Boy Color model: @@ -5184,34 +5399,18 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. Preload entire ROM into memory - - - Savestate extra data: - - Screenshot - - - - Save data - - Cheat codes - - - Load extra data: - - Enable Game Boy Player features by default @@ -5446,17 +5645,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - + Keyboard - + Gamepad - + Clear diff --git a/src/platform/qt/ts/mgba-template.ts b/src/platform/qt/ts/mgba-template.ts index 18acc6273..0ede98618 100644 --- a/src/platform/qt/ts/mgba-template.ts +++ b/src/platform/qt/ts/mgba-template.ts @@ -25,7 +25,7 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. @@ -1134,6 +1134,14 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + + QGBA::AboutScreen + + + 2021 + + + QGBA::AssetTile @@ -1223,17 +1231,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::CoreManager - + Failed to open game file: %1 - + Could not load game. Are you sure it's in the correct format? - + Failed to open save file. Is the save directory writable? @@ -1241,52 +1249,52 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::FrameView - + Export frame - + Portable Network Graphics (*.png) - + None - + Background - + Window - + Objwin - + Sprite - + Backdrop - + Frame - + %1 %2 @@ -1294,7 +1302,7 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::GBAApp - + Enable Discord Rich Presence @@ -3485,62 +3493,62 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::MemoryModel - + Copy selection - + Save selection - + Paste - + Load - + All - + Load TBL - + Save selected memory - + Failed to open output file: %1 - + Load memory - + Failed to open input file: %1 - + TBL - + ISO-8859-1 @@ -3710,16 +3718,79 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3863,17 +3934,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 - + Native (%0x%1) - + Select output file @@ -3881,722 +3952,746 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - - + + + Select ROM - + Select folder - - Game Boy Advance save files (%1) - - - - - - + + Select save - - mGBA savestate files (%1) - - - - - - Select savestate - - - - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - - + + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - - Load alternate save... + + Save games (%1) - - Load temporary save... + + Select save game - + + mGBA save state files (%1) + + + + + + Select save state + + + + + Load alternate save game... + + + + + Load temporary save game... + + + + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + + Convert save game... + + + + Import GameShark Save... - + Export GameShark Save... - + New multiplayer window - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Sync to &video - + Sync to &audio - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4732,6 +4827,110 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5181,7 +5380,18 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - Savestate extra data: + Save state extra data: + + + + + + Save game + + + + + Load state extra data: @@ -5190,23 +5400,12 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. Screenshot - - - - Save data - - Cheat codes - - - Load extra data: - - Enable Game Boy Player features by default @@ -5446,17 +5645,17 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - + Keyboard - + Gamepad - + Clear diff --git a/src/platform/qt/ts/mgba-tr.ts b/src/platform/qt/ts/mgba-tr.ts index 0647bed4b..6a35ac4b1 100644 --- a/src/platform/qt/ts/mgba-tr.ts +++ b/src/platform/qt/ts/mgba-tr.ts @@ -25,9 +25,9 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 - 2020 Mozilla Public License, 2.0 sürümünde lisanslı Jeffrey Pfau + © 2013 - {year} Mozilla Public License, 2.0 sürümünde lisanslı Jeffrey Pfau Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. @@ -1135,6 +1135,14 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. + + QGBA::AboutScreen + + + 2021 + + + QGBA::AssetTile @@ -1224,17 +1232,17 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. QGBA::CoreManager - + Failed to open game file: %1 Oyun dosyası açılamadı: %1 - + Could not load game. Are you sure it's in the correct format? Oyun yüklenemedi. Doğru formatta olduğundan emin misin? - + Failed to open save file. Is the save directory writable? @@ -1242,52 +1250,52 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. QGBA::FrameView - + Export frame - + Portable Network Graphics (*.png) - + None Hiçbiri - + Background Arkaplan - + Window - + Objwin - + Sprite - + Backdrop - + Frame - + %1 %2 @@ -1295,7 +1303,7 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. QGBA::GBAApp - + Enable Discord Rich Presence Discord etkinliğini etkinleştir @@ -3486,62 +3494,62 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. QGBA::MemoryModel - + Copy selection Seçileni kopyala - + Save selection Seçilenleri kaydet - + Paste Yapıştır - + Load Yükle - + All Hepsi - + Load TBL TBL yükle - + Save selected memory Seçilen memory'i kaydet - + Failed to open output file: %1 Çıkış dosyası açılamadı:%1 - + Load memory Memory yükle - + Failed to open input file: %1 Giriş dosyası açılamadı:%1 - + TBL - + ISO-8859-1 @@ -3711,16 +3719,79 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3864,17 +3935,17 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. QGBA::VideoView - + Failed to open output video file: %1 Çıkış video dosyası açılamadı:%1 - + Native (%0x%1) - + Select output file Çıkış dosyasını seç @@ -3882,118 +3953,101 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance ROMları (%1) - + Game Boy ROMs (%1) Game Boy ROMları (%1) - + All ROMs (%1) Bütün ROMlar (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) Arşivler (%1) - - - + + + Select ROM ROM seç - + Select folder Klasör seç - - Game Boy Advance save files (%1) - Game Boy Advance kayıt dosyaları (%1) - - - - - + + Select save Kayıt seç - - mGBA savestate files (%1) - mGBA kaydedilmiş konu kayıtları (%1) - - - - - Select savestate - Konumkaydedici seç - - - + Select patch Yama seç - + Patches (*.ips *.ups *.bps) Yamalar (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image Resim seç - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Resim dosyası (*.png *.gif *.jpg *.jpeg);;All files (*) - - + + GameShark saves (*.sps *.xps) GameShark kayıtları (*.sps *.xps) - + Select video log Video günlüğü seç - + Video logs (*.mvl) Video günlükleri (*.mvl) - + Crash Çökme - + The game has crashed with the following error: %1 @@ -4002,604 +4056,645 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. - + Unimplemented BIOS call Uygulanmamış BIOS girişi - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Oyun BIOS dosyasına ihtiyacı var. Lütfen en iyi deneyim için resmi BIOS'u kullanın. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? Taşınabilir yapılsın mı? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Emülatörün yapılandırmasını yürütülebilir dosya ile aynı dizinden yüklemesini sağlar. Devam etmek istiyor musun? - + Restart needed Yeniden başlatma gerekli - + Some changes will not take effect until the emulator is restarted. Bazı değişiklikler emülatör yeniden başlatılıncaya kadar etkili olmaz. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... &ROM yükle... - + Load ROM in archive... ROM'u arşivden yükle ... - + Add folder to library... Kütüphaneye klasör ekle ... - - Load alternate save... - Alternatif kaydetme yükle ... - - - - Load temporary save... - Geçici kaydetmeyi yükle ... - - - + Load &patch... &Patch yükle... - + Boot BIOS BIOS boot et - + Replace ROM... ROM değişti... - + ROM &info... ROM &info... - + Recent Son kullanılanlar - + Make portable Portatif yap - + &Load state &Kaydedilmiş konum yükle - + Load state file... Kaydedilmiş konum dosyası yükle... - + &Save state &Konumu kaydet - + Save state file... Konum dosyasını kaydet... - + Quick load Hızlı Yükle - + Quick save Hızlı kaydet - + Load recent En son yükle - + Save recent Hızlı kaydet - + Undo load state Kaydedilen konum yüklemeyi geri al - + Undo save state Konum kaydetmeyi geri al - - + + State &%1 Konum &%1 - + Load camera image... Kamera resmini yükle ... - + + Convert save game... + + + + New multiplayer window Yeni çokoyunculu ekranı - + Report bug... - + About... Hakkında... - + E&xit Çıkış - + &Emulation Emülasyon - + &Reset &Reset - + Sh&utdown Kapat - + Yank game pak - + &Pause &Durdur - + &Next frame &Sonraki kare - + Fast forward (held) İleriye sar(basılı tutun) - + &Fast forward &İleriye sar - + Fast forward speed İleriye sarma hızı - + Unbounded - + %0x - + Rewind (held) Geri sar (basılı tutun) - + Re&wind Geri sar - + Step backwards Geriye doğru adım - + Sync to &video &Videoya eşitle - + Sync to &audio &Sese eşitle - + Solar sensor - + Increase solar level Solar seviyesini arttır - + Decrease solar level Solar seviyesini düşür - + Brightest solar level En parlak solar seviyesi - + Darkest solar level En karanlık solar seviyesi - + Brightness %1 Parlaklık:%1 - + Game Boy Printer... Game Boy yazıcısı... - + BattleChip Gate... - + Audio/&Video Ses/&Video - + Frame size Çerçeve boyutu - + Toggle fullscreen Tamekranı aç/kapa - + Lock aspect ratio En boy oranını kilitle - + Force integer scaling Tamsayılı ölçeklendirmeyi zorla - + Bilinear filtering Bilinear filtreleme - + Frame&skip Kare atlama - + Mute Sessiz - + FPS target FPS hedefi - + Native (59.7275) - + Take &screenshot Ekran görüntüsü al - + F12 - + Video layers - + Audio channels Ses kanalları - + Adjust layer placement... Katman yerleşimini ayarlayın... - + &Tools &Araçlar - + View &logs... Kayıtları görüntüle... - + Game &overrides... Oyunların üzerine yazılanlar - + Couldn't Start - + + Save games (%1) + + + + + Select save game + + + + + mGBA save state files (%1) + + + + + + Select save state + + + + Could not start game. - + + Load alternate save game... + + + + + Load temporary save game... + + + + Scan e-Reader dotcodes... - + Import GameShark Save... - + Export GameShark Save... - + %1× - + Interframe blending - + Record A/V... - + Record GIF/WebP/APNG... - + Game Pak sensors... - + &Cheats... &Hileler... - + Settings... Ayarlar... - + Open debugger console... Hata ayıklayıcı konsolunu aç ... - + Start &GDB server... &GDB sunucusunu başlat... - + View &palette... &Renk Paletini gör... - + View &sprites... &Spriteları gör... - + View &tiles... &Desenleri gör... - + View &map... &Haritayı gör - + &Frame inspector... - + View memory... Hafıza gör... - + Search memory... Hafızada ara... - + View &I/O registers... &I/O kayıtlarını görüntüle - + Record debug video log... - + Stop debug video log - + Exit fullscreen Tam ekrandan çık - + GameShark Button (held) GameShark Butonu (basılı tutun) - + Autofire Otomatik basma - + Autofire A Otomatik basma A - + Autofire B Otomatik basma B - + Autofire L Otomatik basma L - + Autofire R Otomatik basma R - + Autofire Start Otomatik basma Start - + Autofire Select Otomatik basma Select - + Autofire Up Otomatik basma Up - + Autofire Right Otomatik basma Right - + Autofire Down Otomatik basma Down - + Autofire Left Otomatik basma Sol - + Clear Temizle QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4735,6 +4830,110 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + Gözat + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5091,6 +5290,22 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır.Show FPS in title bar FPS'i başlık çubuğunda göster + + + Save state extra data: + + + + + + Save game + + + + + Load state extra data: + + Super Game Boy/Game Boy Color model: @@ -5187,34 +5402,18 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır.Preload entire ROM into memory Tüm ROM'u belleğe önceden yükle - - - Savestate extra data: - Konum kaydedici kaydeder: - Screenshot Ekran görüntüsü - - - - Save data - Verileri kaydet - Cheat codes Hile kodları - - - Load extra data: - Ekstra veri yükle: - Enable Game Boy Player features by default @@ -5449,17 +5648,17 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır.Kısayolları düzenle - + Keyboard Klavye - + Gamepad - + Clear Temizle diff --git a/src/platform/qt/ts/mgba-zh_CN.ts b/src/platform/qt/ts/mgba-zh_CN.ts index 51dfca93b..e5c7356d8 100644 --- a/src/platform/qt/ts/mgba-zh_CN.ts +++ b/src/platform/qt/ts/mgba-zh_CN.ts @@ -25,9 +25,9 @@ - © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 + © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 – 2020 Jeffrey Pfau,基于 Mozilla 公共许可证(版本 2.0)授权 + © 2013 – {year} Jeffrey Pfau,基于 Mozilla 公共许可证(版本 2.0)授权 Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标。 @@ -1135,6 +1135,14 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 复制 + + QGBA::AboutScreen + + + 2021 + 2021 + + QGBA::AssetTile @@ -1224,17 +1232,17 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::CoreManager - + Failed to open game file: %1 打开游戏文件失败: %1 - + Could not load game. Are you sure it's in the correct format? 无法载入游戏。请确认游戏格式是否正确? - + Failed to open save file. Is the save directory writable? 无法打开存档文件。存档目录是否可写入? @@ -1242,52 +1250,52 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::FrameView - + Export frame 导出框架 - + Portable Network Graphics (*.png) 便携式网络图形 (*.png) - + None - + Background 背景 - + Window 窗口 - + Objwin Objwin - + Sprite 精灵图 - + Backdrop 背幕 - + Frame - + %1 %2 %1 %2 @@ -1295,7 +1303,7 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::GBAApp - + Enable Discord Rich Presence 启用 Discord Rich Presence @@ -3486,62 +3494,62 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::MemoryModel - + Copy selection 复制所选 - + Save selection 保存所选 - + Paste 粘贴 - + Load 载入 - + All 全部 - + Load TBL 载入 TBL - + Save selected memory 保存所选内存 - + Failed to open output file: %1 打开输出文件失败: %1 - + Load memory 载入内存 - + Failed to open input file: %1 打开输入文件失败: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3711,16 +3719,79 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::ReportView - + Bug report archive 错误报告存档 - + ZIP archive (*.zip) ZIP 存档 (*.zip) + + QGBA::SaveConverter + + + Save games and save states (%1) + + + + + Select save game or save state + + + + + Save games (%1) + + + + + Select save game + + + + + Conversion failed + + + + + Failed to convert the save game. This is probably a bug. + + + + + No file selected + + + + + Could not open file + + + + + No valid formats found + + + + + Please select a valid input file + + + + + No valid conversions found + + + + + Cannot convert save games between platforms + + + QGBA::SettingsView @@ -3864,17 +3935,17 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::VideoView - + Failed to open output video file: %1 打开输出视频文件失败: %1 - + Native (%0x%1) 原生 (%0x%1) - + Select output file 选择输出文件 @@ -3882,118 +3953,101 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance ROM (%1) - + Game Boy ROMs (%1) Game Boy ROM (%1) - + All ROMs (%1) 所有 ROM (%1) - + %1 Video Logs (*.mvl) %1 视频日志 (*.mvl) - + Archives (%1) 压缩文件 (%1) - - - + + + Select ROM 选择 ROM - + Select folder 选择文件夹 - - Game Boy Advance save files (%1) - Game Boy Advance 存档文件 (%1) - - - - - + + Select save 选择存档 - - mGBA savestate files (%1) - mGBA 即时存档文件 (%1) - - - - - Select savestate - 选择即时存档 - - - + Select patch 选择补丁 - + Patches (*.ips *.ups *.bps) 补丁 (*.ips *.ups *.bps) - + Select e-Reader dotcode 选择 e-Reader 点码 - + e-Reader card (*.raw *.bin *.bmp) e-Reader 卡 (*.raw *.bin *.bmp) - + Select image 选择图片 - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 图像文件 (*.png *.gif *.jpg *.jpeg);;所有文件 (*) - - + + GameShark saves (*.sps *.xps) GameShark 存档 (*.sps *.xps) - + Select video log 选择视频日志 - + Video logs (*.mvl) 视频日志文件 (*.mvl) - + Crash 崩溃 - + The game has crashed with the following error: %1 @@ -4002,604 +4056,645 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 %1 - + Couldn't Start 无法启动 - + Could not start game. 无法启动游戏。 - + Unimplemented BIOS call 未实现的 BIOS 调用 - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. 此游戏使用尚未实现的 BIOS 调用。请使用官方 BIOS 以获得最佳体验。 - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. 无法创建适合的显示设备,正在回滚到软件显示。游戏的运行速度(特别在大窗口的情况下)可能会变慢。 - + Really make portable? 确定进行程序便携化? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? 进行此操作后,模拟器将从其可执行文件所在目录中载入模拟器配置。您想继续吗? - + Restart needed 需要重新启动 - + Some changes will not take effect until the emulator is restarted. 更改将在模拟器下次重新启动时生效。 - + - Player %1 of %2 - 玩家 %1 共 %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File 文件(&F) - + Load &ROM... 载入 ROM(&R)... - + Load ROM in archive... 从压缩文件中载入 ROM... - + Add folder to library... 将文件夹添加到库中... - - Load alternate save... - 载入其他存档... + + Save games (%1) + - - Load temporary save... - 载入临时存档... + + Select save game + - + + mGBA save state files (%1) + + + + + + Select save state + + + + + Load alternate save game... + + + + + Load temporary save game... + + + + Load &patch... 载入补丁(&P)... - + Boot BIOS 引导 BIOS - + Replace ROM... 替换 ROM... - + Scan e-Reader dotcodes... 扫描 e-Reader 点码... - + ROM &info... ROM 信息(&I)... - + Recent 最近打开 - + Make portable 程序便携化 - + &Load state 载入即时存档(&L) - + Load state file... 载入即时存档文件... - + &Save state 保存即时存档(&S) - + Save state file... 保存即时存档文件... - + Quick load 快速读档 - + Quick save 快速存档 - + Load recent 载入最近存档 - + Save recent 保存最近存档 - + Undo load state 撤消读档 - + Undo save state 撤消存档 - - + + State &%1 即时存档 (&%1) - + Load camera image... 载入相机图片... - + + Convert save game... + + + + Import GameShark Save... 导入 GameShark 存档... - + Export GameShark Save... 导出 GameShark 存档... - + New multiplayer window 新建多人游戏窗口 - + Report bug... 报告错误... - + About... 关于... - + E&xit 退出(&X) - + &Emulation 模拟(&E) - + &Reset 重置(&R) - + Sh&utdown 关机(&U) - + Yank game pak 快速抽出游戏卡带 - + &Pause 暂停(&P) - + &Next frame 下一帧(&N) - + Fast forward (held) 快进 (长按) - + &Fast forward 快进(&F) - + Fast forward speed 快进速度 - + Unbounded 不限制 - + %0x %0x - + Rewind (held) 倒带 (长按) - + Re&wind 倒带(&W) - + Step backwards 步退 - + Sync to &video 视频同步(&V) - + Sync to &audio 音频同步(&A) - + Solar sensor 太阳光传感器 - + Increase solar level 增加太阳光等级 - + Decrease solar level 降低太阳光等级 - + Brightest solar level 太阳光等级为最亮 - + Darkest solar level 太阳光等级为最暗 - + Brightness %1 亮度 %1 - + Game Boy Printer... Game Boy 打印机... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video 音频/视频(&V) - + Frame size 画面大小 - + %1× %1× - + Toggle fullscreen 切换全屏 - + Lock aspect ratio 锁定纵横比 - + Force integer scaling 强制整数缩放 - + Interframe blending 帧间混合 - + Bilinear filtering 双线性过滤 - + Frame&skip 跳帧(&S) - + Mute 静音 - + FPS target 目标 FPS - + Native (59.7275) 原生 (59.7275) - + Take &screenshot 截图(&S) - + F12 F12 - + Record A/V... 录制音频/视频... - + Record GIF/WebP/APNG... 录制 GIF/WebP/APNG... - + Video layers 视频图层 - + Audio channels 音频声道 - + Adjust layer placement... 调整图层布局... - + &Tools 工具(&T) - + View &logs... 查看日志(&L)... - + Game &overrides... 覆写游戏(&O)... - + Game Pak sensors... 游戏卡带传感器... - + &Cheats... 作弊码(&C)... - + Settings... 设置... - + Open debugger console... 打开调试器控制台... - + Start &GDB server... 打开 GDB 服务器(&G)... - + View &palette... 查看调色板(&P)... - + View &sprites... 查看精灵图(&S)... - + View &tiles... 查看图块(&T)... - + View &map... 查看映射(&M)... - + &Frame inspector... 框架检查器(&F)... - + View memory... 查看内存... - + Search memory... 搜索内存... - + View &I/O registers... 查看 I/O 寄存器(&I)... - + Record debug video log... 记录调试视频日志... - + Stop debug video log 停止记录调试视频日志 - + Exit fullscreen 退出全屏 - + GameShark Button (held) GameShark 键 (长按) - + Autofire 连发 - + Autofire A 连发 A - + Autofire B 连发 B - + Autofire L 连发 L - + Autofire R 连发 R - + Autofire Start 连发 Start - + Autofire Select 连发 Select - + Autofire Up 连发 上 - + Autofire Right 连发 右 - + Autofire Down 连发 下 - + Autofire Left 连发 左 - + Clear 清除 QObject + + + %1 byte + + + + + %1 kiB + + + + + %1 MiB + + GBA @@ -4735,6 +4830,110 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 创建并包含即时存档 + + SaveConverter + + + Convert/Extract Save Game + + + + + Input file + + + + + + Browse + 浏览 + + + + Output file + + + + + %1 %2 save game + + + + + little endian + + + + + big endian + + + + + SRAM + SRAM + + + + %1 flash + + + + + %1 EEPROM + + + + + %1 SRAM + RTC + + + + + %1 SRAM + + + + + packed MBC2 + + + + + unpacked MBC2 + + + + + MBC6 flash + + + + + MBC6 combined SRAM + flash + + + + + MBC6 SRAM + + + + + TAMA5 + + + + + %1 (%2) + + + + + %1 save state with embedded %2 save game + + + SensorView @@ -5184,8 +5383,19 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 - Savestate extra data: - 即时存档额外数据: + Save state extra data: + + + + + + Save game + + + + + Load state extra data: + @@ -5193,23 +5403,12 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 Screenshot 截图 - - - - Save data - 保存数据 - Cheat codes 作弊码 - - - Load extra data: - 载入额外数据: - Enable Game Boy Player features by default @@ -5449,17 +5648,17 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 编辑快捷键 - + Keyboard 键盘 - + Gamepad 游戏手柄 - + Clear 清除 diff --git a/src/platform/qt/utils.cpp b/src/platform/qt/utils.cpp index 94b230361..31845e140 100644 --- a/src/platform/qt/utils.cpp +++ b/src/platform/qt/utils.cpp @@ -11,16 +11,16 @@ namespace QGBA { QString niceSizeFormat(size_t filesize) { double size = filesize; - QString unit = "B"; + QString unit = QObject::tr("%1 byte"); if (size >= 1024.0) { size /= 1024.0; - unit = "kiB"; + unit = QObject::tr("%1 kiB"); } if (size >= 1024.0) { size /= 1024.0; - unit = "MiB"; + unit = QObject::tr("%1 MiB"); } - return QString("%0 %1").arg(size, 0, 'f', 1).arg(unit); + return unit.arg(size, 0, 'f', int(size * 10) % 10 ? 1 : 0); } QString nicePlatformFormat(mPlatform platform) { switch (platform) { diff --git a/src/platform/qt/utils.h b/src/platform/qt/utils.h index 5dda75dd5..c66f597f7 100644 --- a/src/platform/qt/utils.h +++ b/src/platform/qt/utils.h @@ -7,11 +7,70 @@ #include +#include +#include #include +#include + namespace QGBA { +enum class Endian { + NONE = 0b00, + BIG = 0b01, + LITTLE = 0b10, + UNKNOWN = 0b11 +}; + QString niceSizeFormat(size_t filesize); QString nicePlatformFormat(mPlatform platform); +inline void lockAspectRatio(const QSize& ref, QSize& size) { + if (size.width() * ref.height() > size.height() * ref.width()) { + size.setWidth(size.height() * ref.width() / ref.height()); + } else if (size.width() * ref.height() < size.height() * ref.width()) { + size.setHeight(size.width() * ref.height() / ref.width()); + } +} + +inline void zoomAspectRatio(const QSize& ref, QSize& size) { + if (size.width() * ref.height() < size.height() * ref.width()) { + size.setWidth(size.height() * ref.width() / ref.height()); + } else if (size.width() * ref.height() > size.height() * ref.width()) { + size.setHeight(size.width() * ref.height() / ref.width()); + } +} + +inline void lockIntegerScaling(const QSize& ref, QSize& size) { + if (size.width() >= ref.width()) { + size.setWidth(size.width() - size.width() % ref.width()); + } + if (size.height() >= ref.height()) { + size.setHeight(size.height() - size.height() % ref.height()); + } +} + +inline QRect clampSize(const QSize& ref, const QSize& size, bool aspectRatio, bool integerScaling, bool zoom = false) { + QSize ds = size; + if (zoom) { + zoomAspectRatio(ref, ds); + } else if (aspectRatio) { + lockAspectRatio(ref, ds); + } + if (integerScaling) { + QGBA::lockIntegerScaling(ref, ds); + } + QPoint origin = QPoint((size.width() - ds.width()) / 2, (size.height() - ds.height()) / 2); + return QRect(origin, ds); +} + +#if __cplusplus >= 201703L +using std::clamp; +#else +template +constexpr const T& clamp(const T& v, const T& lo, const T& hi) { + return std::max(lo, std::min(hi, v)); +} +#endif + } diff --git a/src/sm83/sm83.c b/src/sm83/sm83.c index 28e9e4bd3..b8c9287ec 100644 --- a/src/sm83/sm83.c +++ b/src/sm83/sm83.c @@ -61,6 +61,7 @@ void SM83Reset(struct SM83Core* cpu) { cpu->instruction = 0; + cpu->tMultiplier = 2; cpu->cycles = 0; cpu->nextEvent = 0; cpu->executionState = SM83_CORE_FETCH; @@ -102,7 +103,7 @@ static void _SM83InstructionIRQ(struct SM83Core* cpu) { } static void _SM83Step(struct SM83Core* cpu) { - ++cpu->cycles; + cpu->cycles += cpu->tMultiplier; enum SM83ExecutionState state = cpu->executionState; cpu->executionState = SM83_CORE_IDLE_0; switch (state) { @@ -147,23 +148,31 @@ static void _SM83Step(struct SM83Core* cpu) { } } +static inline bool _SM83TickInternal(struct SM83Core* cpu) { + bool running = true; + _SM83Step(cpu); + int t = cpu->tMultiplier; + if (cpu->cycles + t * 2 >= cpu->nextEvent) { + int32_t diff = cpu->nextEvent - cpu->cycles; + cpu->cycles = cpu->nextEvent; + cpu->executionState += diff >> (t - 1); // NB: This assumes tMultiplier is either 1 or 2 + cpu->irqh.processEvents(cpu); + cpu->cycles += (SM83_CORE_EXECUTE - cpu->executionState) * t; + running = false; + } else { + cpu->cycles += t * 2; + } + cpu->executionState = SM83_CORE_FETCH; + cpu->instruction(cpu); + cpu->cycles += t; + return running; +} + void SM83Tick(struct SM83Core* cpu) { while (cpu->cycles >= cpu->nextEvent) { cpu->irqh.processEvents(cpu); } - _SM83Step(cpu); - if (cpu->cycles + 2 >= cpu->nextEvent) { - int32_t diff = cpu->nextEvent - cpu->cycles; - cpu->cycles = cpu->nextEvent; - cpu->executionState += diff; - cpu->irqh.processEvents(cpu); - cpu->cycles += SM83_CORE_EXECUTE - cpu->executionState; - } else { - cpu->cycles += 2; - } - cpu->executionState = SM83_CORE_FETCH; - cpu->instruction(cpu); - ++cpu->cycles; + _SM83TickInternal(cpu); } void SM83Run(struct SM83Core* cpu) { @@ -173,19 +182,6 @@ void SM83Run(struct SM83Core* cpu) { cpu->irqh.processEvents(cpu); break; } - _SM83Step(cpu); - if (cpu->cycles + 2 >= cpu->nextEvent) { - int32_t diff = cpu->nextEvent - cpu->cycles; - cpu->cycles = cpu->nextEvent; - cpu->executionState += diff; - cpu->irqh.processEvents(cpu); - cpu->cycles += SM83_CORE_EXECUTE - cpu->executionState; - running = false; - } else { - cpu->cycles += 2; - } - cpu->executionState = SM83_CORE_FETCH; - cpu->instruction(cpu); - ++cpu->cycles; + running = _SM83TickInternal(cpu) && running; } } diff --git a/src/util/png-io.c b/src/util/png-io.c index 530ea8f0b..6c25f399c 100644 --- a/src/util/png-io.c +++ b/src/util/png-io.c @@ -210,6 +210,7 @@ void PNGWriteClose(png_structp png, png_infop info) { bool isPNG(struct VFile* source) { png_byte header[PNG_HEADER_BYTES]; + source->seek(source, 0, SEEK_SET); if (source->read(source, header, PNG_HEADER_BYTES) < PNG_HEADER_BYTES) { return false; }