From 511437312ccf917dcc816618e2a0595aecc32e59 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 11 Jan 2025 19:47:21 -0800 Subject: [PATCH 01/31] Qt: Revamp memory view layout --- src/platform/qt/MemoryView.cpp | 20 +- src/platform/qt/MemoryView.ui | 471 +++++++++++++++------------------ 2 files changed, 221 insertions(+), 270 deletions(-) diff --git a/src/platform/qt/MemoryView.cpp b/src/platform/qt/MemoryView.cpp index 4383867e0..cdb754bfe 100644 --- a/src/platform/qt/MemoryView.cpp +++ b/src/platform/qt/MemoryView.cpp @@ -133,20 +133,10 @@ MemoryView::MemoryView(std::shared_ptr controller, QWidget* pare } } - connect(m_ui.width8, &QAbstractButton::clicked, [this]() { - m_ui.hexfield->setAlignment(1); - m_sintValidator.setWidth(1); - m_uintValidator.setWidth(1); - }); - connect(m_ui.width16, &QAbstractButton::clicked, [this]() { - m_ui.hexfield->setAlignment(2); - m_sintValidator.setWidth(2); - m_uintValidator.setWidth(2); - }); - connect(m_ui.width32, &QAbstractButton::clicked, [this]() { - m_ui.hexfield->setAlignment(4); - m_sintValidator.setWidth(4); - m_uintValidator.setWidth(4); + connect(m_ui.width, &QComboBox::currentIndexChanged, [this](int index) { + m_ui.hexfield->setAlignment(1 << index); + m_sintValidator.setWidth(1 << index); + m_uintValidator.setWidth(1 << index); }); connect(m_ui.setAddress, static_cast(&QSpinBox::valueChanged), this, static_cast(&MemoryView::jumpToAddress)); @@ -258,7 +248,7 @@ void MemoryView::updateStatus() { mCore* core = m_controller->thread()->core; QByteArray selection(m_ui.hexfield->serialize()); QString text(m_ui.hexfield->decodeText(selection)); - m_ui.stringVal->setText(text); + m_ui.stringVal->setPlainText(text); if (m_selection.first & (align - 1) || m_selection.second - m_selection.first != align) { m_ui.sintVal->clear(); diff --git a/src/platform/qt/MemoryView.ui b/src/platform/qt/MemoryView.ui index 45879db88..06ab570d1 100644 --- a/src/platform/qt/MemoryView.ui +++ b/src/platform/qt/MemoryView.ui @@ -6,167 +6,14 @@ 0 0 - 874 - 900 + 708 + 549 Memory - - - - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - Inspect Address: - - - - - - - -1 - - - 0 - - - 16 - - - - - - - : - - - - - - - true - - - 0x - - - 268435455 - - - 16 - - - 16 - - - - - - - - - - - Set Alignment: - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - &1 Byte - - - true - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - &2 Bytes - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - &4 Bytes - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - + @@ -175,72 +22,255 @@ 0 + + + 200 + 0 + + - - - + + + + + + - + - Unsigned Integer: + Address: - - - 10 + + + Qt::Horizontal - + + + 0 + 0 + + + + + + + + -1 + + + 0 + + + 16 + + + + + + + : + + + + + + + + 100 + 0 + + + true + + 0x + + + 268435455 + + + 16 + + + 16 + - + - + - Signed Integer: + Alignment: - - - 11 - - - true + + + + 0 + 0 + + + + 1 Byte + + + + + 2 Bytes + + + + + 4 Bytes + + - - - - + + + + + 0 + 0 + + + + + + + + + + Signed: + + + + + + + 11 + + + true + + + + + + + + + + Unsigned: + + + + + + + 10 + + + true + + + + + + + + + + String: + + + + + + + + 0 + 0 + + + + Load TBL + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + + - String: + Copy Selection - - - - true + + + + Save Selection - - + + - Load TBL + Paste + + + + + + + Save Range + + + + + + + + 0 + 0 + + + + Load @@ -248,58 +278,6 @@ - - - - - - Copy Selection - - - - - - - Paste - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Save Selection - - - - - - - Save Range - - - - - - - Load - - - - - @@ -310,23 +288,6 @@ 1 - - regions - segments - setAddress - width8 - width16 - width32 - sintVal - uintVal - stringVal - loadTBL - copy - paste - save - saveRange - load - From 75dc29085307fbf03ceddca5092988c8e0c5f900 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 12 Jan 2025 04:30:12 -0800 Subject: [PATCH 02/31] Debugger: Expose mDebuggerAccessLoggerGetRegion --- .../mgba/internal/debugger/access-logger.h | 2 + src/debugger/access-logger.c | 174 +++++++++--------- 2 files changed, 89 insertions(+), 87 deletions(-) diff --git a/include/mgba/internal/debugger/access-logger.h b/include/mgba/internal/debugger/access-logger.h index 26186ac20..b839bd5b1 100644 --- a/include/mgba/internal/debugger/access-logger.h +++ b/include/mgba/internal/debugger/access-logger.h @@ -46,6 +46,8 @@ int mDebuggerAccessLoggerWatchMemoryBlockName(struct mDebuggerAccessLogger*, con bool mDebuggerAccessLoggerCreateShadowFile(struct mDebuggerAccessLogger*, int region, struct VFile*, uint8_t fill); +struct mDebuggerAccessLogRegion* mDebuggerAccessLoggerGetRegion(struct mDebuggerAccessLogger*, uint32_t address, int segment, size_t* offset); + CXX_GUARD_END #endif diff --git a/src/debugger/access-logger.c b/src/debugger/access-logger.c index 41c780c4e..e38eead03 100644 --- a/src/debugger/access-logger.c +++ b/src/debugger/access-logger.c @@ -62,74 +62,61 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum break; } - size_t i; - for (i = 0; i < mDebuggerAccessLogRegionListSize(&logger->regions); ++i) { - struct mDebuggerAccessLogRegion* region = mDebuggerAccessLogRegionListGetPointer(&logger->regions, i); - if (info->address < region->start || info->address >= region->end) { - continue; - } - size_t offset = info->address - region->start; - if (info->segment > 0) { - uint32_t segmentSize = region->end - region->segmentStart; - offset %= segmentSize; - offset += segmentSize * info->segment; - } + size_t offset; + struct mDebuggerAccessLogRegion* region = mDebuggerAccessLoggerGetRegion(logger, info->address, info->segment, &offset); + if (!region) { + return; + } + offset &= -info->width; - if (offset >= region->size) { - continue; - } - - offset &= -info->width; - - int j; - switch (reason) { - case DEBUGGER_ENTER_WATCHPOINT: - for (j = 0; j < info->width; ++j) { - if (info->type.wp.accessType & WATCHPOINT_WRITE) { - region->block[offset + j] = mDebuggerAccessLogFlagsFillWrite(region->block[offset + j]); - } - if (info->type.wp.accessType & WATCHPOINT_READ) { - region->block[offset + j] = mDebuggerAccessLogFlagsFillRead(region->block[offset + j]); - } + int i; + switch (reason) { + case DEBUGGER_ENTER_WATCHPOINT: + for (i = 0; i < info->width; ++i) { + if (info->type.wp.accessType & WATCHPOINT_WRITE) { + region->block[offset + i] = mDebuggerAccessLogFlagsFillWrite(region->block[offset + i]); } - switch (info->width) { - case 1: - region->block[offset] = mDebuggerAccessLogFlagsFillAccess8(region->block[offset]); - break; - case 2: - region->block[offset] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset]); - region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset + 1]); - break; - case 4: - region->block[offset] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset]); - region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 1]); - region->block[offset + 2] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 2]); - region->block[offset + 3] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 3]); - break; - case 8: - region->block[offset] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset]); - region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 1]); - region->block[offset + 2] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 2]); - region->block[offset + 3] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 3]); - region->block[offset + 4] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 4]); - region->block[offset + 5] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 5]); - region->block[offset + 6] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 6]); - region->block[offset + 7] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 7]); - break; + if (info->type.wp.accessType & WATCHPOINT_READ) { + region->block[offset + i] = mDebuggerAccessLogFlagsFillRead(region->block[offset + i]); } + } + switch (info->width) { + case 1: + region->block[offset] = mDebuggerAccessLogFlagsFillAccess8(region->block[offset]); break; - case DEBUGGER_ENTER_ILLEGAL_OP: - region->block[offset] = mDebuggerAccessLogFlagsFillExecute(region->block[offset]); - if (region->blockEx) { - uint16_t ex; - LOAD_16LE(ex, 0, ®ion->blockEx[offset]); - ex = mDebuggerAccessLogFlagsExFillErrorIllegalOpcode(ex); - STORE_16LE(ex, 0, ®ion->blockEx[offset]); - } + case 2: + region->block[offset] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset]); + region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset + 1]); break; - default: + case 4: + region->block[offset] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset]); + region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 1]); + region->block[offset + 2] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 2]); + region->block[offset + 3] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 3]); + break; + case 8: + region->block[offset] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset]); + region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 1]); + region->block[offset + 2] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 2]); + region->block[offset + 3] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 3]); + region->block[offset + 4] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 4]); + region->block[offset + 5] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 5]); + region->block[offset + 6] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 6]); + region->block[offset + 7] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 7]); break; } + break; + case DEBUGGER_ENTER_ILLEGAL_OP: + region->block[offset] = mDebuggerAccessLogFlagsFillExecute(region->block[offset]); + if (region->blockEx) { + uint16_t ex; + LOAD_16LE(ex, 0, ®ion->blockEx[offset]); + ex = mDebuggerAccessLogFlagsExFillErrorIllegalOpcode(ex); + STORE_16LE(ex, 0, ®ion->blockEx[offset]); + } + break; + default: + break; } } @@ -139,34 +126,22 @@ static void _mDebuggerAccessLoggerCallback(struct mDebuggerModule* debugger) { struct mDebuggerInstructionInfo info; logger->d.p->platform->nextInstructionInfo(logger->d.p->platform, &info); + size_t offset; + struct mDebuggerAccessLogRegion* region = mDebuggerAccessLoggerGetRegion(logger, info.address, info.segment, &offset); + if (!region) { + return; + } + size_t i; - for (i = 0; i < mDebuggerAccessLogRegionListSize(&logger->regions); ++i) { - struct mDebuggerAccessLogRegion* region = mDebuggerAccessLogRegionListGetPointer(&logger->regions, i); - if (info.address < region->start || info.address >= region->end) { - continue; - } - size_t offset = info.address - region->start; - if (info.segment > 0) { - uint32_t segmentSize = region->end - region->segmentStart; - offset %= segmentSize; - offset += segmentSize * info.segment; - } + for (i = 0; i < info.width; ++i) { + uint16_t ex = 0; + region->block[offset + i] = mDebuggerAccessLogFlagsFillExecute(region->block[offset + i]); + region->block[offset + i] |= info.flags[i]; - if (offset >= region->size) { - continue; - } - - size_t j; - for (j = 0; j < info.width; ++j) { - uint16_t ex = 0; - region->block[offset + j] = mDebuggerAccessLogFlagsFillExecute(region->block[offset + j]); - region->block[offset + j] |= info.flags[j]; - - if (region->blockEx) { - LOAD_16LE(ex, 0, ®ion->blockEx[offset + j]); - ex |= info.flagsEx[j]; - STORE_16LE(ex, 0, ®ion->blockEx[offset + j]); - } + if (region->blockEx) { + LOAD_16LE(ex, 0, ®ion->blockEx[offset + i]); + ex |= info.flagsEx[i]; + STORE_16LE(ex, 0, ®ion->blockEx[offset + i]); } } } @@ -518,3 +493,28 @@ bool mDebuggerAccessLoggerCreateShadowFile(struct mDebuggerAccessLogger* logger, } return true; } + +struct mDebuggerAccessLogRegion* mDebuggerAccessLoggerGetRegion(struct mDebuggerAccessLogger* logger, uint32_t address, int segment, size_t* offsetOut) { + size_t i; + for (i = 0; i < mDebuggerAccessLogRegionListSize(&logger->regions); ++i) { + struct mDebuggerAccessLogRegion* region = mDebuggerAccessLogRegionListGetPointer(&logger->regions, i); + if (address < region->start || address >= region->end) { + continue; + } + size_t offset = address - region->start; + if (segment > 0) { + uint32_t segmentSize = region->end - region->segmentStart; + offset %= segmentSize; + offset += segmentSize * segment; + } + + if (offset >= region->size) { + continue; + } + if (offsetOut) { + *offsetOut = offset; + } + return region; + } + return NULL; +} From 159b0dc445e97712ac2cd2cbdb4178bd4ce09407 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 12 Jan 2025 06:00:40 -0800 Subject: [PATCH 03/31] Qt: Add access log view to memory view --- src/platform/qt/CMakeLists.txt | 1 + src/platform/qt/MemoryAccessLogController.cpp | 41 +++ src/platform/qt/MemoryAccessLogController.h | 15 + src/platform/qt/MemoryAccessLogModel.cpp | 283 ++++++++++++++++++ src/platform/qt/MemoryAccessLogModel.h | 55 ++++ src/platform/qt/MemoryView.cpp | 24 ++ src/platform/qt/MemoryView.h | 5 + src/platform/qt/MemoryView.ui | 60 +++- 8 files changed, 473 insertions(+), 11 deletions(-) create mode 100644 src/platform/qt/MemoryAccessLogModel.cpp create mode 100644 src/platform/qt/MemoryAccessLogModel.h diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 910ab9b57..9858fddb0 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -262,6 +262,7 @@ if(ENABLE_DEBUGGERS) DebuggerConsole.cpp DebuggerConsoleController.cpp MemoryAccessLogController.cpp + MemoryAccessLogModel.cpp MemoryAccessLogView.cpp) endif() diff --git a/src/platform/qt/MemoryAccessLogController.cpp b/src/platform/qt/MemoryAccessLogController.cpp index 95200e53e..9691dcadf 100644 --- a/src/platform/qt/MemoryAccessLogController.cpp +++ b/src/platform/qt/MemoryAccessLogController.cpp @@ -10,8 +10,14 @@ #include "utils.h" #include "VFileDevice.h" +#include + using namespace QGBA; +int MemoryAccessLogController::Flags::count() const { + return popcount32(flags) + popcount32(flagsEx); +} + MemoryAccessLogController::MemoryAccessLogController(CoreController* controller, QObject* parent) : QObject(parent) , m_controller(controller) @@ -39,6 +45,17 @@ bool MemoryAccessLogController::canExport() const { return m_regionMapping.contains("cart0"); } +MemoryAccessLogController::Flags MemoryAccessLogController::flagsForAddress(uint32_t addresss, int segment) { + uint32_t offset = cacheRegion(addresss, segment); + if (!m_cachedRegion) { + return { 0, 0 }; + } + return { + m_cachedRegion->blockEx ? m_cachedRegion->blockEx[offset] : mDebuggerAccessLogFlagsEx{}, + m_cachedRegion->block ? m_cachedRegion->block[offset] : mDebuggerAccessLogFlags{}, + }; +} + void MemoryAccessLogController::updateRegion(const QString& internalName, bool checked) { if (checked) { m_watchedRegions += internalName; @@ -116,3 +133,27 @@ void MemoryAccessLogController::exportFile(const QString& filename) { mDebuggerAccessLoggerCreateShadowFile(&m_logger, m_regionMapping[QString("cart0")], vf, 0); vf->close(vf); } + +uint32_t MemoryAccessLogController::cacheRegion(uint32_t address, int segment) { + if (m_cachedRegion && (address < m_cachedRegion->start || address >= m_cachedRegion->end)) { + m_cachedRegion = nullptr; + } + if (!m_cachedRegion) { + m_cachedRegion = mDebuggerAccessLoggerGetRegion(&m_logger, address, segment, nullptr); + } + if (!m_cachedRegion) { + return 0; + } + + size_t offset = address - m_cachedRegion->start; + if (segment > 0) { + uint32_t segmentSize = m_cachedRegion->end - m_cachedRegion->segmentStart; + offset %= segmentSize; + offset += segmentSize * segment; + } + if (offset >= m_cachedRegion->size) { + m_cachedRegion = nullptr; + return cacheRegion(address, segment); + } + return offset; +} diff --git a/src/platform/qt/MemoryAccessLogController.h b/src/platform/qt/MemoryAccessLogController.h index 42ef655c3..79553b333 100644 --- a/src/platform/qt/MemoryAccessLogController.h +++ b/src/platform/qt/MemoryAccessLogController.h @@ -12,6 +12,7 @@ #include "CoreController.h" +#include #include namespace QGBA { @@ -25,6 +26,16 @@ public: QString internalName; }; + struct Flags { + mDebuggerAccessLogFlagsEx flagsEx; + mDebuggerAccessLogFlags flags; + + int count() const; + bool operator==(const Flags& other) const { return flags == other.flags && flagsEx == other.flagsEx; } + bool operator!=(const Flags& other) const { return flags != other.flags || flagsEx != other.flagsEx; } + operator bool() const { return flags || flagsEx; } + }; + MemoryAccessLogController(CoreController* controller, QObject* parent = nullptr); ~MemoryAccessLogController(); @@ -34,6 +45,8 @@ public: bool canExport() const; mPlatform platform() const { return m_controller->platform(); } + Flags flagsForAddress(uint32_t address, int segment = -1); + QString file() const { return m_path; } bool active() const { return m_active; } @@ -59,8 +72,10 @@ private: QVector m_regions; struct mDebuggerAccessLogger m_logger{}; bool m_active = false; + mDebuggerAccessLogRegion* m_cachedRegion = nullptr; mDebuggerAccessLogRegionFlags activeFlags() const; + uint32_t cacheRegion(uint32_t address, int segment); }; } diff --git a/src/platform/qt/MemoryAccessLogModel.cpp b/src/platform/qt/MemoryAccessLogModel.cpp new file mode 100644 index 000000000..23eb34f4c --- /dev/null +++ b/src/platform/qt/MemoryAccessLogModel.cpp @@ -0,0 +1,283 @@ +/* Copyright (c) 2013-2025 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 "MemoryAccessLogModel.h" + +#include + +using namespace QGBA; + +MemoryAccessLogModel::MemoryAccessLogModel(std::weak_ptr controller, mPlatform platform) + : m_controller(controller) + , m_platform(platform) +{ +} + +QVariant MemoryAccessLogModel::data(const QModelIndex& index, int role) const { + if (role != Qt::DisplayRole) { + return {}; + } + if (index.column() != 0) { + return {}; + } + int blockIndex = -1; + int flagIndex = -1; + QModelIndex parent = index.parent(); + if (!parent.isValid()) { + blockIndex = index.row(); + } else { + blockIndex = parent.row(); + flagIndex = index.row(); + } + + if (blockIndex < 0 || blockIndex >= m_cachedBlocks.count()) { + return {}; + } + + const Block& block = m_cachedBlocks[blockIndex]; + + if (flagIndex < 0) { + return QString("0x%1 – 0x%2") + .arg(QString("%0").arg(block.region.first, 8, 16, QChar('0')).toUpper()) + .arg(QString("%0").arg(block.region.second, 8, 16, QChar('0')).toUpper()); + } + for (int i = 0; i < 8; ++i) { + if (!(block.flags.flags & (1 << i))) { + continue; + } + if (flagIndex == 0) { + switch (i) { + case 0: + return tr("Data read"); + case 1: + return tr("Data written"); + case 2: + return tr("Code executed"); + case 3: + return tr("Code aborted"); + case 4: + return tr("8-bit access"); + case 5: + return tr("16-bit access"); + case 6: + return tr("32-bit access"); + case 7: + return tr("64-bit access"); + default: + Q_UNREACHABLE(); + } + } + --flagIndex; + } + for (int i = 0; i < 16; ++i) { + if (!(block.flags.flagsEx & (1 << i))) { + continue; + } + if (flagIndex == 0) { + switch (i) { + case 0: + return tr("Accessed by instruction"); + case 1: + return tr("Accessed by DMA"); + case 2: + return tr("Accessed by BIOS"); + case 3: + return tr("Compressed data"); + case 4: + return tr("Accessed by memory copy"); + case 5: + return tr("(Unknown extra bit 5)"); + case 6: + return tr("(Unknown extra bit 6)"); + case 7: + return tr("(Unknown extra bit 7)"); + case 8: + return tr("Invalid instruction"); + case 9: + return tr("Invalid read"); + case 10: + return tr("Invalid write"); + case 11: + return tr("Invalid executable address"); + case 12: + return tr("(Private bit 0)"); + case 13: + return tr("(Private bit 1)"); + case 14: + switch (m_platform) { + case mPLATFORM_GBA: + return tr("ARM code"); + default: + return tr("(Private bit 2)"); + } + case 15: + switch (m_platform) { + case mPLATFORM_GBA: + return tr("Thumb code"); + default: + return tr("(Private bit 2)"); + } + default: + Q_UNREACHABLE(); + } + } + --flagIndex; + } + return tr("(Unknown)"); +} + +QModelIndex MemoryAccessLogModel::index(int row, int column, const QModelIndex& parent) const { + if (column != 0) { + return {}; + } + if (parent.isValid()) { + return createIndex(row, 0, parent.row()); + } + return createIndex(row, 0, std::numeric_limits::max()); +} + +QModelIndex MemoryAccessLogModel::parent(const QModelIndex& index) const { + if (!index.isValid()) { + return {}; + } + quintptr row = index.internalId(); + if (row >= std::numeric_limits::max()) { + return {}; + } + return createIndex(row, 0, std::numeric_limits::max()); +} + +int MemoryAccessLogModel::rowCount(const QModelIndex& parent) const { + int blockIndex = -1; + if (!parent.isValid()) { + return m_cachedBlocks.count(); + } else if (parent.column() != 0) { + return 0; + } else if (parent.parent().isValid()) { + return 0; + } else { + blockIndex = parent.row(); + } + + if (blockIndex < 0 || blockIndex >= m_cachedBlocks.count()) { + return 0; + } + + const Block& block = m_cachedBlocks[blockIndex]; + return block.flags.count(); +} + +void MemoryAccessLogModel::updateSelection(uint32_t start, uint32_t end) { + std::shared_ptr controller = m_controller.lock(); + if (!controller) { + return; + } + QVector newBlocks; + uint32_t lastStart = start; + auto lastFlags = controller->flagsForAddress(m_base + start, m_segment); + + for (uint32_t address = start; address < end; ++address) { + auto flags = controller->flagsForAddress(m_base + address, m_segment); + if (flags == lastFlags) { + continue; + } + if (lastFlags) { + newBlocks.append({ lastFlags, qMakePair(lastStart, address) }); + } + lastFlags = flags; + lastStart = address; + } + if (lastFlags) { + newBlocks.append({ lastFlags, qMakePair(lastStart, end) }); + } + + if (m_cachedBlocks.count() == 0 || newBlocks.count() == 0) { + beginResetModel(); + m_cachedBlocks = newBlocks; + endResetModel(); + return; + } + + QPair changed{ -1, -1 }; + for (int i = 0; i < m_cachedBlocks.count() && i < newBlocks.count(); ++i) { + const Block& oldBlock = m_cachedBlocks.at(i); + const Block& newBlock = newBlocks.at(i); + + if (oldBlock != newBlock) { + changed = qMakePair(i, m_cachedBlocks.count()); + break; + } + } + + if (m_cachedBlocks.count() > newBlocks.count()) { + beginRemoveRows({}, newBlocks.count(), m_cachedBlocks.count()); + m_cachedBlocks.resize(newBlocks.count()); + endRemoveRows(); + changed.second = newBlocks.count(); + } + + if (m_cachedBlocks.count() < newBlocks.count()) { + beginInsertRows({}, m_cachedBlocks.count(), newBlocks.count()); + if (changed.first < 0) { + // Only new rows + m_cachedBlocks = newBlocks; + endInsertRows(); + return; + } + } + + if (changed.first < 0) { + // No changed rows, though some might have been removed + return; + } + + for (int i = 0; i < m_cachedBlocks.count() && i < newBlocks.count(); ++i) { + const Block& oldBlock = m_cachedBlocks.at(i); + const Block& newBlock = newBlocks.at(i); + if (oldBlock.flags != newBlock.flags) { + int oldFlags = oldBlock.flags.count(); + int newFlags = newBlock.flags.count(); + if (oldFlags > newFlags) { + beginRemoveRows(createIndex(i, 0, std::numeric_limits::max()), newFlags, oldFlags); + } else if (oldFlags < newFlags) { + beginInsertRows(createIndex(i, 0, std::numeric_limits::max()), oldFlags, newFlags); + } + m_cachedBlocks[i] = newBlock; + emit dataChanged(createIndex(0, 0, i), createIndex(std::min(oldFlags, newFlags), 0, i)); + if (oldFlags > newFlags) { + endRemoveRows(); + } else if (oldFlags < newFlags) { + endInsertRows(); + } + } + } + emit dataChanged(createIndex(changed.first, 0, std::numeric_limits::max()), + createIndex(changed.second, 0, std::numeric_limits::max())); + + if (m_cachedBlocks.count() < newBlocks.count()) { + m_cachedBlocks = newBlocks; + endInsertRows(); + } +} + +void MemoryAccessLogModel::setSegment(int segment) { + if (m_segment == segment) { + return; + } + beginResetModel(); + m_segment = segment; + m_cachedBlocks.clear(); + endResetModel(); +} + +void MemoryAccessLogModel::setRegion(uint32_t base, uint32_t, bool useSegments) { + if (m_base == base) { + return; + } + beginResetModel(); + m_segment = useSegments ? 0 : -1; + m_cachedBlocks.clear(); + endResetModel(); +} diff --git a/src/platform/qt/MemoryAccessLogModel.h b/src/platform/qt/MemoryAccessLogModel.h new file mode 100644 index 000000000..b18f0dee5 --- /dev/null +++ b/src/platform/qt/MemoryAccessLogModel.h @@ -0,0 +1,55 @@ +/* Copyright (c) 2013-2025 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 + +#include "MemoryAccessLogController.h" + +struct mCheatDevice; +struct mCheatSet; + +namespace QGBA { + +class MemoryAccessLogModel : public QAbstractItemModel { +Q_OBJECT + +public: + MemoryAccessLogModel(std::weak_ptr controller, mPlatform platform); + + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + + virtual QModelIndex index(int row, int column, const QModelIndex& parent) const override; + virtual QModelIndex parent(const QModelIndex& index) const override; + + virtual int columnCount(const QModelIndex& = QModelIndex()) const override { return 1; } + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; + +public slots: + void updateSelection(uint32_t start, uint32_t end); + void setSegment(int segment); + void setRegion(uint32_t base, uint32_t segmentSize, bool useSegments); + +private: + struct Block { + MemoryAccessLogController::Flags flags; + QPair region; + + bool operator==(const Block& other) const { return flags == other.flags && region == other.region; } + bool operator!=(const Block& other) const { return flags != other.flags || region != other.region; } + }; + + int flagCount(int index) const; + + std::weak_ptr m_controller; + mPlatform m_platform; + uint32_t m_base = 0; + int m_segment = -1; + QVector m_cachedBlocks; +}; + +} diff --git a/src/platform/qt/MemoryView.cpp b/src/platform/qt/MemoryView.cpp index cdb754bfe..009d789aa 100644 --- a/src/platform/qt/MemoryView.cpp +++ b/src/platform/qt/MemoryView.cpp @@ -7,6 +7,7 @@ #include "MemoryView.h" #include "CoreController.h" +#include "MemoryAccessLogView.h" #include "MemoryDump.h" #include @@ -107,6 +108,9 @@ QValidator::State IntValidator::validate(QString& input, int&) const { MemoryView::MemoryView(std::shared_ptr controller, QWidget* parent) : QWidget(parent) , m_controller(controller) +#ifdef ENABLE_DEBUGGERS + , m_malModel(controller->memoryAccessLogController(), controller->platform()) +#endif { m_ui.setupUi(this); @@ -189,6 +193,22 @@ MemoryView::MemoryView(std::shared_ptr controller, QWidget* pare } update(); }); + +#ifdef ENABLE_DEBUGGERS + connect(m_ui.hexfield, &MemoryModel::selectionChanged, &m_malModel, &MemoryAccessLogModel::updateSelection); + connect(m_ui.segments, static_cast(&QSpinBox::valueChanged), + &m_malModel, &MemoryAccessLogModel::setSegment); + connect(m_ui.accessLoggerButton, &QAbstractButton::clicked, this, [this]() { + std::weak_ptr controller = m_controller->memoryAccessLogController(); + MemoryAccessLogView* view = new MemoryAccessLogView(controller); + connect(m_controller.get(), &CoreController::stopping, view, &QWidget::close); + view->setAttribute(Qt::WA_DeleteOnClose); + view->show(); + }); + m_ui.accessLog->setModel(&m_malModel); +#else + m_ui.accessLog->hide(); +#endif } void MemoryView::setIndex(int index) { @@ -206,6 +226,10 @@ void MemoryView::setIndex(int index) { m_ui.segmentColon->setVisible(info.maxSegment > 0); m_ui.segments->setMaximum(info.maxSegment); m_ui.hexfield->setRegion(info.start, info.end - info.start, info.shortName); + +#ifdef ENABLE_DEBUGGERS + m_malModel.setRegion(info.start, info.segmentStart - info.start, info.maxSegment > 0); +#endif } void MemoryView::setSegment(int segment) { diff --git a/src/platform/qt/MemoryView.h b/src/platform/qt/MemoryView.h index f68052a06..d6a5c6f93 100644 --- a/src/platform/qt/MemoryView.h +++ b/src/platform/qt/MemoryView.h @@ -8,6 +8,7 @@ #include #include "MemoryModel.h" +#include "MemoryAccessLogModel.h" #include "ui_MemoryView.h" @@ -54,6 +55,10 @@ private: std::shared_ptr m_controller; QPair m_region; QPair m_selection; + +#ifdef ENABLE_DEBUGGERS + MemoryAccessLogModel m_malModel; +#endif }; } diff --git a/src/platform/qt/MemoryView.ui b/src/platform/qt/MemoryView.ui index 06ab570d1..73407fdd1 100644 --- a/src/platform/qt/MemoryView.ui +++ b/src/platform/qt/MemoryView.ui @@ -31,14 +31,14 @@ - + - + - + Address: @@ -105,9 +105,9 @@ - + - + Alignment: @@ -141,7 +141,7 @@ - + 0 @@ -151,9 +151,9 @@ - + - + Signed: @@ -173,7 +173,7 @@ - + Unsigned: @@ -193,7 +193,7 @@ - + String: @@ -232,7 +232,7 @@ - + @@ -276,6 +276,44 @@ + + + + + 0 + 0 + + + + Selected address accesses + + + + + + + 0 + 0 + + + + Qt::ElideNone + + + false + + + + + + + Logging configuration + + + + + + From 762a54a388aca616c799c4a8542a89aae9450c45 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 12 Jan 2025 06:01:10 -0800 Subject: [PATCH 04/31] Core: Threads should not attempt to exit a thread that is already dead --- src/core/thread.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/thread.c b/src/core/thread.c index 988ce0848..92d134120 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -507,6 +507,10 @@ void mCoreThreadClearCrashed(struct mCoreThread* threadContext) { void mCoreThreadEnd(struct mCoreThread* threadContext) { MutexLock(&threadContext->impl->stateMutex); + if (threadContext->impl->state == mTHREAD_SHUTDOWN) { + MutexUnlock(&threadContext->impl->stateMutex); + return; + } _waitOnInterrupt(threadContext->impl); threadContext->impl->state = mTHREAD_EXITING; ConditionWake(&threadContext->impl->stateOnThreadCond); From 6be223d84a4f319f82d07b9569541934cc1f66d9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 12 Jan 2025 06:14:10 -0800 Subject: [PATCH 05/31] Qt: Defer destroying the CoreController until after the CoreController::stopping slots finish --- src/platform/qt/Window.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 1be4a998c..a224c3ba4 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -972,7 +972,12 @@ void Window::gameStopped() { #endif } - m_controller.reset(); + std::shared_ptr controller; + m_controller.swap(controller); + QTimer::singleShot(0, this, [controller]() { + // Destroy the controller after everything else has cleaned up + Q_UNUSED(controller); + }); detachWidget(); updateTitle(); @@ -2155,11 +2160,6 @@ void Window::setController(CoreController* controller, const QString& fname) { connect(m_controller.get(), &CoreController::started, this, &Window::gameStarted); connect(m_controller.get(), &CoreController::started, GBAApp::app(), &GBAApp::suspendScreensaver); connect(m_controller.get(), &CoreController::stopping, this, &Window::gameStopped); - { - connect(m_controller.get(), &CoreController::stopping, [this]() { - m_controller.reset(); - }); - } connect(m_controller.get(), &CoreController::stopping, GBAApp::app(), &GBAApp::resumeScreensaver); connect(m_controller.get(), &CoreController::paused, this, &Window::updateFrame); From 8c2e2e1d4628e8794fa547a9acce5d18fe8f585a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 12 Jan 2025 16:22:34 -0800 Subject: [PATCH 06/31] Qt: Fix build --- src/platform/qt/MemoryView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/MemoryView.cpp b/src/platform/qt/MemoryView.cpp index 009d789aa..dd0bc18a3 100644 --- a/src/platform/qt/MemoryView.cpp +++ b/src/platform/qt/MemoryView.cpp @@ -137,7 +137,7 @@ MemoryView::MemoryView(std::shared_ptr controller, QWidget* pare } } - connect(m_ui.width, &QComboBox::currentIndexChanged, [this](int index) { + connect(m_ui.width, static_cast(&QComboBox::currentIndexChanged), [this](int index) { m_ui.hexfield->setAlignment(1 << index); m_sintValidator.setWidth(1 << index); m_uintValidator.setWidth(1 << index); From deb4f547fa395e182cf2af5bc6feebb5d2bb3470 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 12 Jan 2025 22:41:29 -0800 Subject: [PATCH 07/31] Qt: GB memory access logger fixes --- src/platform/qt/MemoryAccessLogModel.cpp | 26 ++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/platform/qt/MemoryAccessLogModel.cpp b/src/platform/qt/MemoryAccessLogModel.cpp index 23eb34f4c..6fa8592d0 100644 --- a/src/platform/qt/MemoryAccessLogModel.cpp +++ b/src/platform/qt/MemoryAccessLogModel.cpp @@ -39,9 +39,23 @@ QVariant MemoryAccessLogModel::data(const QModelIndex& index, int role) const { const Block& block = m_cachedBlocks[blockIndex]; if (flagIndex < 0) { - return QString("0x%1 – 0x%2") - .arg(QString("%0").arg(block.region.first, 8, 16, QChar('0')).toUpper()) - .arg(QString("%0").arg(block.region.second, 8, 16, QChar('0')).toUpper()); + if (m_platform == mPLATFORM_GB) { + if (m_segment < 0) { + return QString("$%1 – $%2") + .arg(QString("%0").arg(block.region.first, 4, 16, QChar('0')).toUpper()) + .arg(QString("%0").arg(block.region.second, 4, 16, QChar('0')).toUpper()); + } else { + return QString("$%1:%3 – $%2:%4") + .arg(QString("%0").arg(m_segment, 2, 16, QChar('0')).toUpper()) + .arg(QString("%0").arg(m_segment, 2, 16, QChar('0')).toUpper()) + .arg(QString("%0").arg(block.region.first, 4, 16, QChar('0')).toUpper()) + .arg(QString("%0").arg(block.region.second, 4, 16, QChar('0')).toUpper()); + } + } else { + return QString("0x%1 – 0x%2") + .arg(QString("%0").arg(block.region.first, 8, 16, QChar('0')).toUpper()) + .arg(QString("%0").arg(block.region.second, 8, 16, QChar('0')).toUpper()); + } } for (int i = 0; i < 8; ++i) { if (!(block.flags.flags & (1 << i))) { @@ -109,6 +123,8 @@ QVariant MemoryAccessLogModel::data(const QModelIndex& index, int role) const { switch (m_platform) { case mPLATFORM_GBA: return tr("ARM code"); + case mPLATFORM_GB: + return tr("Instruction opcode"); default: return tr("(Private bit 2)"); } @@ -116,8 +132,10 @@ QVariant MemoryAccessLogModel::data(const QModelIndex& index, int role) const { switch (m_platform) { case mPLATFORM_GBA: return tr("Thumb code"); + case mPLATFORM_GB: + return tr("Instruction operand"); default: - return tr("(Private bit 2)"); + return tr("(Private bit 3)"); } default: Q_UNREACHABLE(); From b8c890e1bc3c4910044ce00413214ee9c48930db Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 14 Jan 2025 03:20:01 -0800 Subject: [PATCH 08/31] Debugger: Plumb access source information through to access logger --- include/mgba/core/cpu.h | 9 ++++++ include/mgba/debugger/debugger.h | 1 + include/mgba/internal/arm/arm.h | 2 ++ include/mgba/internal/sm83/sm83.h | 2 ++ src/arm/debugger/memory-debugger.c | 1 + src/debugger/access-logger.c | 43 +++++++++++++++++++++++++++++ src/gb/memory.c | 8 ++++++ src/gba/bios.c | 27 ++++++++++++++++++ src/gba/dma.c | 3 ++ src/gba/memory.c | 10 +++++++ src/sm83/debugger/memory-debugger.c | 1 + 11 files changed, 107 insertions(+) diff --git a/include/mgba/core/cpu.h b/include/mgba/core/cpu.h index 71f3398c2..e538f4a59 100644 --- a/include/mgba/core/cpu.h +++ b/include/mgba/core/cpu.h @@ -20,6 +20,15 @@ enum mCPUComponentType { CPU_COMPONENT_MAX }; +enum mMemoryAccessSource { + mACCESS_UNKNOWN = 0, + mACCESS_PROGRAM, + mACCESS_DMA, + mACCESS_SYSTEM, + mACCESS_DECOMPRESS, + mACCESS_COPY, +}; + struct mCPUComponent { uint32_t id; void (*init)(void* cpu, struct mCPUComponent* component); diff --git a/include/mgba/debugger/debugger.h b/include/mgba/debugger/debugger.h index eb69faaf4..7cf89882b 100644 --- a/include/mgba/debugger/debugger.h +++ b/include/mgba/debugger/debugger.h @@ -111,6 +111,7 @@ struct mDebuggerEntryInfo { uint32_t newValue; enum mWatchpointType watchType; enum mWatchpointType accessType; + enum mMemoryAccessSource accessSource; } wp; struct { diff --git a/include/mgba/internal/arm/arm.h b/include/mgba/internal/arm/arm.h index 5f25acf90..5ef2da965 100644 --- a/include/mgba/internal/arm/arm.h +++ b/include/mgba/internal/arm/arm.h @@ -132,6 +132,8 @@ struct ARMMemory { uint32_t activeNonseqCycles16; int32_t (*stall)(struct ARMCore*, int32_t wait); void (*setActiveRegion)(struct ARMCore*, uint32_t address); + + enum mMemoryAccessSource accessSource; }; struct ARMCoprocessor { diff --git a/include/mgba/internal/sm83/sm83.h b/include/mgba/internal/sm83/sm83.h index 86b4d374b..7f0fabd7a 100644 --- a/include/mgba/internal/sm83/sm83.h +++ b/include/mgba/internal/sm83/sm83.h @@ -61,6 +61,8 @@ struct SM83Memory { uint16_t activeMask; uint16_t activeRegionEnd; void (*setActiveRegion)(struct SM83Core*, uint16_t address); + + enum mMemoryAccessSource accessSource; }; struct SM83InterruptHandler { diff --git a/src/arm/debugger/memory-debugger.c b/src/arm/debugger/memory-debugger.c index 7dce87795..b0b48423b 100644 --- a/src/arm/debugger/memory-debugger.c +++ b/src/arm/debugger/memory-debugger.c @@ -121,6 +121,7 @@ static void _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, en info.type.wp.newValue = newValue; info.type.wp.watchType = watchpoint->type; info.type.wp.accessType = type; + info.type.wp.accessSource = debugger->cpu->memory.accessSource; info.address = address; info.segment = 0; info.width = width; diff --git a/src/debugger/access-logger.c b/src/debugger/access-logger.c index e38eead03..d8275a970 100644 --- a/src/debugger/access-logger.c +++ b/src/debugger/access-logger.c @@ -69,9 +69,29 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum } offset &= -info->width; + mDebuggerAccessLogFlagsEx flagsEx = 0; int i; switch (reason) { case DEBUGGER_ENTER_WATCHPOINT: + switch (info->type.wp.accessSource) { + case mACCESS_PROGRAM: + flagsEx = mDebuggerAccessLogFlagsExFillAccessProgram(flagsEx); + break; + case mACCESS_DMA: + flagsEx = mDebuggerAccessLogFlagsExFillAccessDMA(flagsEx); + break; + case mACCESS_SYSTEM: + flagsEx = mDebuggerAccessLogFlagsExFillAccessSystem(flagsEx); + break; + case mACCESS_DECOMPRESS: + flagsEx = mDebuggerAccessLogFlagsExFillAccessDecompress(flagsEx); + break; + case mACCESS_COPY: + flagsEx = mDebuggerAccessLogFlagsExFillAccessCopy(flagsEx); + break; + case mACCESS_UNKNOWN: + break; + } for (i = 0; i < info->width; ++i) { if (info->type.wp.accessType & WATCHPOINT_WRITE) { region->block[offset + i] = mDebuggerAccessLogFlagsFillWrite(region->block[offset + i]); @@ -83,16 +103,29 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum switch (info->width) { case 1: region->block[offset] = mDebuggerAccessLogFlagsFillAccess8(region->block[offset]); + if (region->blockEx) { + region->blockEx[offset] |= flagsEx; + } break; case 2: region->block[offset] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset]); region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset + 1]); + if (region->blockEx) { + region->blockEx[offset] |= flagsEx; + region->blockEx[offset + 1] |= flagsEx; + } break; case 4: region->block[offset] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset]); region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 1]); region->block[offset + 2] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 2]); region->block[offset + 3] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 3]); + if (region->blockEx) { + region->blockEx[offset] |= flagsEx; + region->blockEx[offset + 1] |= flagsEx; + region->blockEx[offset + 2] |= flagsEx; + region->blockEx[offset + 3] |= flagsEx; + } break; case 8: region->block[offset] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset]); @@ -103,6 +136,16 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum region->block[offset + 5] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 5]); region->block[offset + 6] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 6]); region->block[offset + 7] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 7]); + if (region->blockEx) { + region->blockEx[offset] |= flagsEx; + region->blockEx[offset + 1] |= flagsEx; + region->blockEx[offset + 2] |= flagsEx; + region->blockEx[offset + 3] |= flagsEx; + region->blockEx[offset + 4] |= flagsEx; + region->blockEx[offset + 5] |= flagsEx; + region->blockEx[offset + 6] |= flagsEx; + region->blockEx[offset + 7] |= flagsEx; + } break; } break; diff --git a/src/gb/memory.c b/src/gb/memory.c index dccd91e08..fdacc1a9b 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -148,6 +148,7 @@ void GBMemoryInit(struct GB* gb) { cpu->memory.store8 = GBStore8; cpu->memory.currentSegment = GBCurrentSegment; cpu->memory.setActiveRegion = GBSetActiveRegion; + cpu->memory.accessSource = mACCESS_UNKNOWN; gb->memory.wram = 0; gb->memory.wramBank = 0; @@ -205,6 +206,7 @@ void GBMemoryReset(struct GB* gb) { gb->memory.hdmaDest = 0; gb->memory.isHdma = false; + gb->cpu->memory.accessSource = mACCESS_UNKNOWN; gb->memory.dmaEvent.context = gb; gb->memory.dmaEvent.name = "GB DMA"; @@ -576,10 +578,13 @@ void _GBMemoryDMAService(struct mTiming* timing, void* context, uint32_t cyclesL struct GB* gb = context; int dmaRemaining = gb->memory.dmaRemaining; gb->memory.dmaRemaining = 0; + enum mMemoryAccessSource oldAccess = gb->cpu->memory.accessSource; + gb->cpu->memory.accessSource = mACCESS_DMA; uint8_t b = GBLoad8(gb->cpu, gb->memory.dmaSource); // TODO: Can DMA write OAM during modes 2-3? gb->video.oam.raw[gb->memory.dmaDest] = b; gb->video.renderer->writeOAM(gb->video.renderer, gb->memory.dmaDest); + gb->cpu->memory.accessSource = oldAccess; ++gb->memory.dmaSource; ++gb->memory.dmaDest; gb->memory.dmaRemaining = dmaRemaining - 1; @@ -591,8 +596,11 @@ void _GBMemoryDMAService(struct mTiming* timing, void* context, uint32_t cyclesL void _GBMemoryHDMAService(struct mTiming* timing, void* context, uint32_t cyclesLate) { struct GB* gb = context; gb->cpuBlocked = true; + enum mMemoryAccessSource oldAccess = gb->cpu->memory.accessSource; + gb->cpu->memory.accessSource = mACCESS_DMA; uint8_t b = gb->cpu->memory.load8(gb->cpu, gb->memory.hdmaSource); gb->cpu->memory.store8(gb->cpu, gb->memory.hdmaDest, b); + gb->cpu->memory.accessSource = oldAccess; ++gb->memory.hdmaSource; ++gb->memory.hdmaDest; --gb->memory.hdmaRemaining; diff --git a/src/gba/bios.c b/src/gba/bios.c index 1ff5004d3..c7b963a40 100644 --- a/src/gba/bios.c +++ b/src/gba/bios.c @@ -174,6 +174,8 @@ static void _BgAffineSet(struct GBA* gba) { int destination = cpu->gprs[1]; float a, b, c, d; float rx, ry; + enum mMemoryAccessSource oldAccess = cpu->memory.accessSource; + cpu->memory.accessSource = mACCESS_SYSTEM; while (i--) { // [ sx 0 0 ] [ cos(theta) -sin(theta) 0 ] [ 1 0 cx - ox ] [ A B rx ] // [ 0 sy 0 ] * [ sin(theta) cos(theta) 0 ] * [ 0 1 cy - oy ] = [ C D ry ] @@ -205,6 +207,7 @@ static void _BgAffineSet(struct GBA* gba) { cpu->memory.store32(cpu, destination + 12, ry * 256, 0); destination += 16; } + cpu->memory.accessSource = oldAccess; } static void _ObjAffineSet(struct GBA* gba) { @@ -216,6 +219,8 @@ static void _ObjAffineSet(struct GBA* gba) { int destination = cpu->gprs[1]; int diff = cpu->gprs[3]; float a, b, c, d; + enum mMemoryAccessSource oldAccess = cpu->memory.accessSource; + cpu->memory.accessSource = mACCESS_SYSTEM; while (i--) { // [ sx 0 ] [ cos(theta) -sin(theta) ] [ A B ] // [ 0 sy ] * [ sin(theta) cos(theta) ] = [ C D ] @@ -237,6 +242,7 @@ static void _ObjAffineSet(struct GBA* gba) { cpu->memory.store16(cpu, destination + diff * 3, d * 256, 0); destination += diff * 4; } + cpu->memory.accessSource = oldAccess; } static void _MidiKey2Freq(struct GBA* gba) { @@ -244,7 +250,10 @@ static void _MidiKey2Freq(struct GBA* gba) { int oldRegion = gba->memory.activeRegion; gba->memory.activeRegion = GBA_REGION_BIOS; + enum mMemoryAccessSource oldAccess = cpu->memory.accessSource; + cpu->memory.accessSource = mACCESS_SYSTEM; uint32_t key = cpu->memory.load32(cpu, cpu->gprs[0] + 4, 0); + cpu->memory.accessSource = oldAccess; gba->memory.activeRegion = oldRegion; cpu->gprs[0] = key / exp2f((180.f - cpu->gprs[1] - cpu->gprs[2] / 256.f) / 12.f); @@ -624,6 +633,8 @@ static void _unLz77(struct GBA* gba, int width) { uint32_t source = cpu->gprs[0]; uint32_t dest = cpu->gprs[1]; int cycles = 20; + enum mMemoryAccessSource oldAccess = cpu->memory.accessSource; + cpu->memory.accessSource = mACCESS_DECOMPRESS; int remaining = (cpu->memory.load32(cpu, source, &cycles) & 0xFFFFFF00) >> 8; // We assume the signature byte (0x10) is correct int blockheader = 0; // Some compilers warn if this isn't set, even though it's trivially provably always set @@ -698,6 +709,7 @@ static void _unLz77(struct GBA* gba, int width) { blocksRemaining = 8; } } + cpu->memory.accessSource = oldAccess; cpu->gprs[0] = source; cpu->gprs[1] = dest; cpu->gprs[3] = 0; @@ -713,6 +725,8 @@ static void _unHuffman(struct GBA* gba) { struct ARMCore* cpu = gba->cpu; uint32_t source = cpu->gprs[0] & 0xFFFFFFFC; uint32_t dest = cpu->gprs[1]; + enum mMemoryAccessSource oldAccess = cpu->memory.accessSource; + cpu->memory.accessSource = mACCESS_DECOMPRESS; uint32_t header = cpu->memory.load32(cpu, source, 0); int remaining = header >> 8; unsigned bits = header & 0xF; @@ -722,6 +736,7 @@ static void _unHuffman(struct GBA* gba) { } if (32 % bits || bits == 1) { mLOG(GBA_BIOS, STUB, "Unimplemented unaligned Huffman"); + cpu->memory.accessSource = oldAccess; return; } // We assume the signature byte (0x20) is correct @@ -773,6 +788,7 @@ static void _unHuffman(struct GBA* gba) { } } } + cpu->memory.accessSource = oldAccess; cpu->gprs[0] = source; cpu->gprs[1] = dest; } @@ -780,6 +796,8 @@ static void _unHuffman(struct GBA* gba) { static void _unRl(struct GBA* gba, int width) { struct ARMCore* cpu = gba->cpu; uint32_t source = cpu->gprs[0]; + enum mMemoryAccessSource oldAccess = cpu->memory.accessSource; + cpu->memory.accessSource = mACCESS_DECOMPRESS; int remaining = (cpu->memory.load32(cpu, source & 0xFFFFFFFC, 0) & 0xFFFFFF00) >> 8; int padding = (4 - remaining) & 0x3; // We assume the signature byte (0x30) is correct @@ -846,6 +864,7 @@ static void _unRl(struct GBA* gba, int width) { ++dest; } } + cpu->memory.accessSource = oldAccess; cpu->gprs[0] = source; cpu->gprs[1] = dest; } @@ -854,6 +873,8 @@ static void _unFilter(struct GBA* gba, int inwidth, int outwidth) { struct ARMCore* cpu = gba->cpu; uint32_t source = cpu->gprs[0] & 0xFFFFFFFC; uint32_t dest = cpu->gprs[1]; + enum mMemoryAccessSource oldAccess = cpu->memory.accessSource; + cpu->memory.accessSource = mACCESS_DECOMPRESS; uint32_t header = cpu->memory.load32(cpu, source, 0); int remaining = header >> 8; // We assume the signature nybble (0x8) is correct @@ -888,6 +909,7 @@ static void _unFilter(struct GBA* gba, int inwidth, int outwidth) { old = new; source += inwidth; } + cpu->memory.accessSource = oldAccess; cpu->gprs[0] = source; cpu->gprs[1] = dest; } @@ -897,6 +919,8 @@ static void _unBitPack(struct GBA* gba) { uint32_t source = cpu->gprs[0]; uint32_t dest = cpu->gprs[1]; uint32_t info = cpu->gprs[2]; + enum mMemoryAccessSource oldAccess = cpu->memory.accessSource; + cpu->memory.accessSource = mACCESS_DECOMPRESS; unsigned sourceLen = cpu->memory.load16(cpu, info, 0); unsigned sourceWidth = cpu->memory.load8(cpu, info + 2, 0); unsigned destWidth = cpu->memory.load8(cpu, info + 3, 0); @@ -908,6 +932,7 @@ static void _unBitPack(struct GBA* gba) { break; default: mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack source width: %u", sourceWidth); + cpu->memory.accessSource = oldAccess; return; } switch (destWidth) { @@ -920,6 +945,7 @@ static void _unBitPack(struct GBA* gba) { break; default: mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack destination width: %u", destWidth); + cpu->memory.accessSource = oldAccess; return; } uint32_t bias = cpu->memory.load32(cpu, info + 4, 0); @@ -949,6 +975,7 @@ static void _unBitPack(struct GBA* gba) { dest += 4; } } + cpu->memory.accessSource = oldAccess; cpu->gprs[0] = source; cpu->gprs[1] = dest; } diff --git a/src/gba/dma.c b/src/gba/dma.c index e9044d26a..3e3e8222d 100644 --- a/src/gba/dma.c +++ b/src/gba/dma.c @@ -248,10 +248,12 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { uint32_t dest = info->nextDest; uint32_t sourceRegion = source >> BASE_OFFSET; uint32_t destRegion = dest >> BASE_OFFSET; + enum mMemoryAccessSource oldAccess = cpu->memory.accessSource; int32_t cycles = 2; gba->cpuBlocked = true; gba->performingDMA = 1 | (number << 1); + cpu->memory.accessSource = mACCESS_DMA; if (info->count == info->nextCount) { if (width == 4) { @@ -315,6 +317,7 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { --info->nextCount; gba->performingDMA = 0; + cpu->memory.accessSource = oldAccess; int i; for (i = 0; i < 4; ++i) { diff --git a/src/gba/memory.c b/src/gba/memory.c index 4f074657a..27e289c8e 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -82,6 +82,7 @@ void GBAMemoryInit(struct GBA* gba) { cpu->memory.activeSeqCycles16 = 0; cpu->memory.activeNonseqCycles32 = 0; cpu->memory.activeNonseqCycles16 = 0; + cpu->memory.accessSource = mACCESS_UNKNOWN; gba->memory.biosPrefetch = 0; gba->memory.agbPrintProtect = 0; @@ -132,6 +133,7 @@ void GBAMemoryReset(struct GBA* gba) { gba->memory.prefetch = false; gba->memory.lastPrefetchedPc = 0; + gba->cpu->memory.accessSource = mACCESS_UNKNOWN; if (!gba->memory.wram || !gba->memory.iwram) { GBAMemoryDeinit(gba); @@ -299,22 +301,27 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { memory->activeRegion = newRegion; switch (newRegion) { case GBA_REGION_BIOS: + cpu->memory.accessSource = mACCESS_SYSTEM; cpu->memory.activeRegion = memory->bios; cpu->memory.activeMask = GBA_SIZE_BIOS - 1; break; case GBA_REGION_EWRAM: + cpu->memory.accessSource = mACCESS_PROGRAM; cpu->memory.activeRegion = memory->wram; cpu->memory.activeMask = GBA_SIZE_EWRAM - 1; break; case GBA_REGION_IWRAM: + cpu->memory.accessSource = mACCESS_PROGRAM; cpu->memory.activeRegion = memory->iwram; cpu->memory.activeMask = GBA_SIZE_IWRAM - 1; break; case GBA_REGION_PALETTE_RAM: + cpu->memory.accessSource = mACCESS_PROGRAM; cpu->memory.activeRegion = (uint32_t*) gba->video.palette; cpu->memory.activeMask = GBA_SIZE_PALETTE_RAM - 1; break; case GBA_REGION_VRAM: + cpu->memory.accessSource = mACCESS_PROGRAM; if (address & 0x10000) { cpu->memory.activeRegion = (uint32_t*) &gba->video.vram[0x8000]; cpu->memory.activeMask = 0x00007FFF; @@ -324,6 +331,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { } break; case GBA_REGION_OAM: + cpu->memory.accessSource = mACCESS_PROGRAM; cpu->memory.activeRegion = (uint32_t*) gba->video.oam.raw; cpu->memory.activeMask = GBA_SIZE_OAM - 1; break; @@ -333,6 +341,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { case GBA_REGION_ROM1_EX: case GBA_REGION_ROM2: case GBA_REGION_ROM2_EX: + cpu->memory.accessSource = mACCESS_PROGRAM; cpu->memory.activeRegion = memory->rom; cpu->memory.activeMask = memory->romMask; if ((address & (GBA_SIZE_ROM0 - 1)) < memory->romSize) { @@ -345,6 +354,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { } // Fall through default: + cpu->memory.accessSource = mACCESS_UNKNOWN; memory->activeRegion = -1; cpu->memory.activeRegion = (uint32_t*) _deadbeef; cpu->memory.activeMask = 0; diff --git a/src/sm83/debugger/memory-debugger.c b/src/sm83/debugger/memory-debugger.c index a35c2afeb..345dc50bf 100644 --- a/src/sm83/debugger/memory-debugger.c +++ b/src/sm83/debugger/memory-debugger.c @@ -61,6 +61,7 @@ static void _checkWatchpoints(struct SM83Debugger* debugger, uint16_t address, e info.type.wp.newValue = newValue; info.type.wp.watchType = watchpoint->type; info.type.wp.accessType = type; + info.type.wp.accessSource = debugger->cpu->memory.accessSource; info.address = address; info.segment = debugger->originalMemory.currentSegment(debugger->cpu, address); info.width = 1; From 311d9f3550824c473958b66ce6211a5092d23b66 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 14 Jan 2025 03:38:30 -0800 Subject: [PATCH 09/31] Debugger: Unroll watchpoint access loop --- src/debugger/access-logger.c | 43 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/debugger/access-logger.c b/src/debugger/access-logger.c index d8275a970..fbe681432 100644 --- a/src/debugger/access-logger.c +++ b/src/debugger/access-logger.c @@ -69,6 +69,7 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum } offset &= -info->width; + mDebuggerAccessLogFlags flags = 0; mDebuggerAccessLogFlagsEx flagsEx = 0; int i; switch (reason) { @@ -92,34 +93,32 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum case mACCESS_UNKNOWN: break; } - for (i = 0; i < info->width; ++i) { - if (info->type.wp.accessType & WATCHPOINT_WRITE) { - region->block[offset + i] = mDebuggerAccessLogFlagsFillWrite(region->block[offset + i]); - } - if (info->type.wp.accessType & WATCHPOINT_READ) { - region->block[offset + i] = mDebuggerAccessLogFlagsFillRead(region->block[offset + i]); - } + if (info->type.wp.accessType & WATCHPOINT_WRITE) { + flags = mDebuggerAccessLogFlagsFillWrite(flags); + } + if (info->type.wp.accessType & WATCHPOINT_READ) { + flags = mDebuggerAccessLogFlagsFillRead(flags); } switch (info->width) { case 1: - region->block[offset] = mDebuggerAccessLogFlagsFillAccess8(region->block[offset]); + region->block[offset] = flags | mDebuggerAccessLogFlagsFillAccess8(region->block[offset]); if (region->blockEx) { region->blockEx[offset] |= flagsEx; } break; case 2: - region->block[offset] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset]); - region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset + 1]); + region->block[offset] = flags | mDebuggerAccessLogFlagsFillAccess16(region->block[offset]); + region->block[offset + 1] = flags | mDebuggerAccessLogFlagsFillAccess16(region->block[offset + 1]); if (region->blockEx) { region->blockEx[offset] |= flagsEx; region->blockEx[offset + 1] |= flagsEx; } break; case 4: - region->block[offset] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset]); - region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 1]); - region->block[offset + 2] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 2]); - region->block[offset + 3] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 3]); + region->block[offset] = flags | mDebuggerAccessLogFlagsFillAccess32(region->block[offset]); + region->block[offset + 1] = flags | mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 1]); + region->block[offset + 2] = flags | mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 2]); + region->block[offset + 3] = flags | mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 3]); if (region->blockEx) { region->blockEx[offset] |= flagsEx; region->blockEx[offset + 1] |= flagsEx; @@ -128,14 +127,14 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum } break; case 8: - region->block[offset] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset]); - region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 1]); - region->block[offset + 2] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 2]); - region->block[offset + 3] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 3]); - region->block[offset + 4] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 4]); - region->block[offset + 5] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 5]); - region->block[offset + 6] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 6]); - region->block[offset + 7] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 7]); + region->block[offset] = flags | mDebuggerAccessLogFlagsFillAccess64(region->block[offset]); + region->block[offset + 1] = flags | mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 1]); + region->block[offset + 2] = flags | mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 2]); + region->block[offset + 3] = flags | mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 3]); + region->block[offset + 4] = flags | mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 4]); + region->block[offset + 5] = flags | mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 5]); + region->block[offset + 6] = flags | mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 6]); + region->block[offset + 7] = flags | mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 7]); if (region->blockEx) { region->blockEx[offset] |= flagsEx; region->blockEx[offset + 1] |= flagsEx; From 7012f9c6662e564d9a64e3d0dd86aa1028f8853d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 15 Jan 2025 23:46:20 -0800 Subject: [PATCH 10/31] Debugger: Allow memory access logs to operate read-only --- include/mgba/debugger/debugger.h | 1 + .../mgba/internal/debugger/access-logger.h | 4 ++ src/debugger/access-logger.c | 48 +++++++++++++++---- src/platform/qt/MemoryAccessLogController.cpp | 1 + src/platform/test/fuzz-main.c | 1 + 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/include/mgba/debugger/debugger.h b/include/mgba/debugger/debugger.h index 7cf89882b..230a95564 100644 --- a/include/mgba/debugger/debugger.h +++ b/include/mgba/debugger/debugger.h @@ -257,6 +257,7 @@ bool mDebuggerIsShutdown(const struct mDebugger*); struct mDebuggerModule* mDebuggerCreateModule(enum mDebuggerType type, struct mCore*); void mDebuggerModuleSetNeedsCallback(struct mDebuggerModule*); +void mDebuggerModuleClearNeedsCallback(struct mDebuggerModule*); bool mDebuggerLookupIdentifier(struct mDebugger* debugger, const char* name, int32_t* value, int* segment); diff --git a/include/mgba/internal/debugger/access-logger.h b/include/mgba/internal/debugger/access-logger.h index b839bd5b1..180168f3a 100644 --- a/include/mgba/internal/debugger/access-logger.h +++ b/include/mgba/internal/debugger/access-logger.h @@ -23,6 +23,7 @@ struct mDebuggerAccessLogRegion { uint32_t segmentStart; mDebuggerAccessLogFlags* block; mDebuggerAccessLogFlagsEx* blockEx; + ssize_t watchpoint; }; DECLARE_VECTOR(mDebuggerAccessLogRegionList, struct mDebuggerAccessLogRegion); @@ -41,6 +42,9 @@ void mDebuggerAccessLoggerDeinit(struct mDebuggerAccessLogger*); bool mDebuggerAccessLoggerOpen(struct mDebuggerAccessLogger*, struct VFile*, int mode); bool mDebuggerAccessLoggerClose(struct mDebuggerAccessLogger*); +void mDebuggerAccessLoggerStart(struct mDebuggerAccessLogger*); +void mDebuggerAccessLoggerStop(struct mDebuggerAccessLogger*); + int mDebuggerAccessLoggerWatchMemoryBlockId(struct mDebuggerAccessLogger*, size_t id, mDebuggerAccessLogRegionFlags); int mDebuggerAccessLoggerWatchMemoryBlockName(struct mDebuggerAccessLogger*, const char* internalName, mDebuggerAccessLogRegionFlags); diff --git a/src/debugger/access-logger.c b/src/debugger/access-logger.c index fbe681432..7133565e9 100644 --- a/src/debugger/access-logger.c +++ b/src/debugger/access-logger.c @@ -71,7 +71,6 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum mDebuggerAccessLogFlags flags = 0; mDebuggerAccessLogFlagsEx flagsEx = 0; - int i; switch (reason) { case DEBUGGER_ENTER_WATCHPOINT: switch (info->type.wp.accessSource) { @@ -257,13 +256,18 @@ static bool _setupRegion(struct mDebuggerAccessLogger* logger, struct mDebuggerA return false; } - struct mWatchpoint wp = { - .segment = -1, - .minAddress = region->start, - .maxAddress = region->end, - .type = WATCHPOINT_RW, - }; - logger->d.p->platform->setWatchpoint(logger->d.p->platform, &logger->d, &wp); + if (region->watchpoint < 0) { + struct mWatchpoint wp = { + .segment = -1, + .minAddress = region->start, + .maxAddress = region->end, + .type = WATCHPOINT_RW, + }; + region->watchpoint = logger->d.p->platform->setWatchpoint(logger->d.p->platform, &logger->d, &wp); + } + if (region->watchpoint < 0) { + return false; + } mDebuggerModuleSetNeedsCallback(&logger->d); return true; } @@ -307,7 +311,7 @@ static bool mDebuggerAccessLoggerLoad(struct mDebuggerAccessLogger* logger) { LOAD_32LE(region->end, 0, &info->end); LOAD_32LE(region->size, 0, &info->size); LOAD_32LE(region->segmentStart, 0, &info->segmentStart); - if (!_setupRegion(logger, region, info)) { + if (!_mapRegion(logger, region, info)) { mDebuggerAccessLogRegionListClear(&logger->regions); return false; } @@ -352,6 +356,30 @@ bool mDebuggerAccessLoggerOpen(struct mDebuggerAccessLogger* logger, struct VFil return loaded; } +void mDebuggerAccessLoggerStart(struct mDebuggerAccessLogger* logger) { + size_t i; + for (i = 0; i < logger->mapped->header.nRegions; ++i) { + struct mDebuggerAccessLogRegionInfo* info = &logger->mapped->regionInfo[i]; + struct mDebuggerAccessLogRegion* region = mDebuggerAccessLogRegionListGetPointer(&logger->regions, i); + if (!_setupRegion(logger, region, info)) { + return; + } + } +} + +void mDebuggerAccessLoggerStop(struct mDebuggerAccessLogger* logger) { + size_t i; + for (i = 0; i < logger->mapped->header.nRegions; ++i) { + struct mDebuggerAccessLogRegion* region = mDebuggerAccessLogRegionListGetPointer(&logger->regions, i); + if (region->watchpoint < 0) { + continue; + } + logger->d.p->platform->clearBreakpoint(logger->d.p->platform, region->watchpoint); + region->watchpoint = -1; + } + logger->d.needsCallback = false; +} + static int _mDebuggerAccessLoggerWatchMemoryBlock(struct mDebuggerAccessLogger* logger, const struct mCoreMemoryBlock* block, mDebuggerAccessLogRegionFlags flags) { if (mDebuggerAccessLogRegionListSize(&logger->regions) >= logger->mapped->header.regionCapacity) { return -1; @@ -423,6 +451,7 @@ static int _mDebuggerAccessLoggerWatchMemoryBlock(struct mDebuggerAccessLogger* region->size = block->size; region->segmentStart = block->segmentStart; region->block = (mDebuggerAccessLogFlags*) ((uintptr_t) logger->backing + fileEnd); + region->watchpoint = -1; struct mDebuggerAccessLogRegionInfo* info = &logger->mapped->regionInfo[id]; STORE_32LE(region->start, 0, &info->start); @@ -451,6 +480,7 @@ bool mDebuggerAccessLoggerClose(struct mDebuggerAccessLogger* logger) { if (!logger->backing) { return true; } + mDebuggerAccessLoggerStop(logger); mDebuggerAccessLogRegionListClear(&logger->regions); logger->backing->unmap(logger->backing, logger->mapped, logger->backing->size(logger->backing)); logger->mapped = NULL; diff --git a/src/platform/qt/MemoryAccessLogController.cpp b/src/platform/qt/MemoryAccessLogController.cpp index 9691dcadf..c2f2216d5 100644 --- a/src/platform/qt/MemoryAccessLogController.cpp +++ b/src/platform/qt/MemoryAccessLogController.cpp @@ -93,6 +93,7 @@ void MemoryAccessLogController::start(bool loadExisting, bool logExtra) { LOG(QT, ERROR) << tr("Failed to open memory log file"); return; } + mDebuggerAccessLoggerStart(&m_logger); m_active = true; emit loggingChanged(true); diff --git a/src/platform/test/fuzz-main.c b/src/platform/test/fuzz-main.c index 143edaba1..5fdfff8a3 100644 --- a/src/platform/test/fuzz-main.c +++ b/src/platform/test/fuzz-main.c @@ -130,6 +130,7 @@ int main(int argc, char** argv) { mDebuggerAccessLoggerInit(&accessLog); mDebuggerAttachModule(&debugger, &accessLog.d); mDebuggerAccessLoggerOpen(&accessLog, vf, O_RDWR); + mDebuggerAccessLoggerStart(&accessLog); hasDebugger = true; } From 4cc49a670079a8e3c6b6c7cf5b4a30091e7f5ddc Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 18 Jan 2025 23:46:24 -0800 Subject: [PATCH 11/31] Qt: Let memory access logs be loaded read-only --- src/platform/qt/MemoryAccessLogController.cpp | 59 ++++++++++++----- src/platform/qt/MemoryAccessLogController.h | 6 ++ src/platform/qt/MemoryAccessLogView.cpp | 54 +++++++++++---- src/platform/qt/MemoryAccessLogView.h | 4 ++ src/platform/qt/MemoryAccessLogView.ui | 65 +++++++++++++++++-- 5 files changed, 155 insertions(+), 33 deletions(-) diff --git a/src/platform/qt/MemoryAccessLogController.cpp b/src/platform/qt/MemoryAccessLogController.cpp index c2f2216d5..d62b2f8a5 100644 --- a/src/platform/qt/MemoryAccessLogController.cpp +++ b/src/platform/qt/MemoryAccessLogController.cpp @@ -65,7 +65,9 @@ void MemoryAccessLogController::updateRegion(const QString& internalName, bool c if (!m_active) { return; } - m_regionMapping[internalName] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, internalName.toUtf8().constData(), activeFlags()); + if (checked && !m_regionMapping.contains(internalName)) { + m_regionMapping[internalName] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, internalName.toUtf8().constData(), activeFlags()); + } emit regionMappingChanged(internalName, checked); } @@ -74,6 +76,38 @@ void MemoryAccessLogController::setFile(const QString& path) { } void MemoryAccessLogController::start(bool loadExisting, bool logExtra) { + if (!m_loaded) { + load(loadExisting); + } + if (!m_loaded) { + return; + } + CoreController::Interrupter interrupter(m_controller); + mDebuggerAccessLoggerStart(&m_logger); + m_logExtra = logExtra; + + m_active = true; + for (const auto& region : m_watchedRegions) { + m_regionMapping[region] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, region.toUtf8().constData(), activeFlags()); + } + emit loggingChanged(true); +} + +void MemoryAccessLogController::stop() { + if (!m_active) { + return; + } + CoreController::Interrupter interrupter(m_controller); + mDebuggerAccessLoggerStop(&m_logger); + emit loggingChanged(false); + interrupter.resume(); + m_active = false; +} + +void MemoryAccessLogController::load(bool loadExisting) { + if (m_loaded) { + return; + } int flags = O_CREAT | O_RDWR; if (!loadExisting) { flags |= O_TRUNC; @@ -83,7 +117,6 @@ void MemoryAccessLogController::start(bool loadExisting, bool logExtra) { LOG(QT, ERROR) << tr("Failed to open memory log file"); return; } - m_logExtra = logExtra; mDebuggerAccessLoggerInit(&m_logger); CoreController::Interrupter interrupter(m_controller); @@ -93,26 +126,22 @@ void MemoryAccessLogController::start(bool loadExisting, bool logExtra) { LOG(QT, ERROR) << tr("Failed to open memory log file"); return; } - mDebuggerAccessLoggerStart(&m_logger); - - m_active = true; - emit loggingChanged(true); - for (const auto& region : m_watchedRegions) { - m_regionMapping[region] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, region.toUtf8().constData(), activeFlags()); - } - interrupter.resume(); + emit loaded(true); + m_loaded = true; } -void MemoryAccessLogController::stop() { - if (!m_active) { +void MemoryAccessLogController::unload() { + if (m_active) { + stop(); + } + if (m_active) { return; } CoreController::Interrupter interrupter(m_controller); m_controller->detachDebuggerModule(&m_logger.d); mDebuggerAccessLoggerDeinit(&m_logger); - emit loggingChanged(false); - interrupter.resume(); - m_active = false; + emit loaded(false); + m_loaded = false; } mDebuggerAccessLogRegionFlags MemoryAccessLogController::activeFlags() const { diff --git a/src/platform/qt/MemoryAccessLogController.h b/src/platform/qt/MemoryAccessLogController.h index 79553b333..b2df55214 100644 --- a/src/platform/qt/MemoryAccessLogController.h +++ b/src/platform/qt/MemoryAccessLogController.h @@ -49,6 +49,7 @@ public: QString file() const { return m_path; } bool active() const { return m_active; } + bool isLoaded() const { return m_loaded; } public slots: void updateRegion(const QString& internalName, bool enable); @@ -57,9 +58,13 @@ public slots: void start(bool loadExisting, bool logExtra); void stop(); + void load(bool loadExisting); + void unload(); + void exportFile(const QString& filename); signals: + void loaded(bool loaded); void loggingChanged(bool active); void regionMappingChanged(const QString& internalName, bool active); @@ -71,6 +76,7 @@ private: QHash m_regionMapping; QVector m_regions; struct mDebuggerAccessLogger m_logger{}; + bool m_loaded = false; bool m_active = false; mDebuggerAccessLogRegion* m_cachedRegion = nullptr; diff --git a/src/platform/qt/MemoryAccessLogView.cpp b/src/platform/qt/MemoryAccessLogView.cpp index 97a0c932e..a06c649ae 100644 --- a/src/platform/qt/MemoryAccessLogView.cpp +++ b/src/platform/qt/MemoryAccessLogView.cpp @@ -26,8 +26,10 @@ MemoryAccessLogView::MemoryAccessLogView(std::weak_ptractive(); + bool loaded = controllerPtr->isLoaded(); auto watchedRegions = controllerPtr->watchedRegions(); QVBoxLayout* regionBox = static_cast(m_ui.regionBox->layout()); @@ -46,11 +48,14 @@ MemoryAccessLogView::MemoryAccessLogView(std::weak_ptrsetEnabled(false); +void MemoryAccessLogView::updateRegion(const QString& internalName, bool checked) { + if (checked) { + m_regionBoxes[internalName]->setEnabled(false); + } } void MemoryAccessLogView::start() { @@ -68,10 +73,23 @@ void MemoryAccessLogView::stop() { return; } controllerPtr->stop(); - for (const auto& region : controllerPtr->watchedRegions()) { - m_regionBoxes[region]->setEnabled(true); +} + +void MemoryAccessLogView::load() { + std::shared_ptr controllerPtr = m_controller.lock(); + if (!controllerPtr) { + return; } - m_ui.exportButton->setEnabled(false); + controllerPtr->setFile(m_ui.filename->text()); + controllerPtr->load(m_ui.loadExisting->isChecked()); +} + +void MemoryAccessLogView::unload() { + std::shared_ptr controllerPtr = m_controller.lock(); + if (!controllerPtr) { + return; + } + controllerPtr->unload(); } void MemoryAccessLogView::selectFile() { @@ -110,12 +128,26 @@ void MemoryAccessLogView::handleStartStop(bool start) { m_regionBoxes[region]->setChecked(true); } - if (watchedRegions.contains(QString("cart0"))) { - m_ui.exportButton->setEnabled(start); - } - m_ui.start->setDisabled(start); m_ui.stop->setEnabled(start); - m_ui.filename->setDisabled(start); - m_ui.browse->setDisabled(start); + m_ui.unload->setDisabled(start || !controllerPtr->isLoaded()); +} + +void MemoryAccessLogView::handleLoadUnload(bool load) { + std::shared_ptr controllerPtr = m_controller.lock(); + if (!controllerPtr) { + return; + } + m_ui.filename->setText(controllerPtr->file()); + + if (load && controllerPtr->canExport()) { + m_ui.exportButton->setEnabled(true); + } else if (!load) { + m_ui.exportButton->setEnabled(false); + } + + m_ui.load->setDisabled(load); + m_ui.unload->setEnabled(load); + m_ui.filename->setDisabled(load); + m_ui.browse->setDisabled(load); } diff --git a/src/platform/qt/MemoryAccessLogView.h b/src/platform/qt/MemoryAccessLogView.h index e221a5d9d..f1f7c0388 100644 --- a/src/platform/qt/MemoryAccessLogView.h +++ b/src/platform/qt/MemoryAccessLogView.h @@ -34,9 +34,13 @@ private slots: void start(); void stop(); + void load(); + void unload(); + void exportFile(); void handleStartStop(bool start); + void handleLoadUnload(bool load); private: Ui::MemoryAccessLogView m_ui; diff --git a/src/platform/qt/MemoryAccessLogView.ui b/src/platform/qt/MemoryAccessLogView.ui index fe9450f53..9fadd0870 100644 --- a/src/platform/qt/MemoryAccessLogView.ui +++ b/src/platform/qt/MemoryAccessLogView.ui @@ -6,8 +6,8 @@ 0 0 - 385 - 380 + 311 + 387 @@ -22,25 +22,25 @@ Log file - - + + - + Browse - + Log additional information (uses 3× space) - + Load existing file if present @@ -50,6 +50,23 @@ + + + + Load + + + + + + + false + + + Unload + + + @@ -124,9 +141,43 @@ + + load + clicked() + QGBA::MemoryAccessLogView + load() + + + 81 + 152 + + + 192 + 189 + + + + + unload + clicked() + QGBA::MemoryAccessLogView + unload() + + + 226 + 152 + + + 192 + 189 + + + start() stop() + load() + unload() From 4189a4d7317040cc0b6317fac2049043a8a24d82 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Sat, 18 Jan 2025 22:07:01 +0900 Subject: [PATCH 12/31] docs: add Japanese README I created Japanese translated README. --- README_JP.md | 268 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 README_JP.md diff --git a/README_JP.md b/README_JP.md new file mode 100644 index 000000000..41bca336b --- /dev/null +++ b/README_JP.md @@ -0,0 +1,268 @@ +mGBA +==== + +mGBAは、ゲームボーイアドバンスのゲームを実行するためのエミュレーターです。mGBAの目標は、既存の多くのゲームボーイアドバンスエミュレーターよりも高速かつ正確であり、他のエミュレーターにはない機能を追加することです。また、ゲームボーイおよびゲームボーイカラーのゲームもサポートしています。 + +最新のニュースとダウンロードは、[mgba.io](https://mgba.io/)で見つけることができます。 + +[![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) + +特徴 +-------- + +- 高精度なゲームボーイアドバンスハードウェアのサポート[[1]](#missing)。 +- ゲームボーイ/ゲームボーイカラーのハードウェアサポート。 +- 高速なエミュレーション。ネットブックなどの低スペックハードウェアでもフルスピードで動作することが知られています。 +- 重量級と軽量級のフロントエンドのためのQtおよびSDLポート。 +- ローカル(同じコンピュータ)リンクケーブルのサポート。 +- フラッシュメモリサイズを含む保存タイプの検出[[2]](#flashdetect)。 +- モーションセンサーと振動機能を備えたカートリッジのサポート(ゲームコントローラーでのみ使用可能)。 +- 設定なしでもリアルタイムクロックのサポート。 +- ボクタイゲームのためのソーラーセンサーのサポート。 +- ゲームボーイカメラとゲームボーイプリンターのサポート。 +- 内蔵BIOS実装と外部BIOSファイルの読み込み機能。 +- Luaを使用したスクリプトサポート。 +- Tabキーを押し続けることでターボ/早送りサポート。 +- バッククォートを押し続けることで巻き戻し。 +- 最大10まで設定可能なフレームスキップ。 +- スクリーンショットのサポート。 +- チートコードのサポート。 +- 9つのセーブステートスロット。セーブステートはスクリーンショットとしても表示可能。 +- ビデオ、GIF、WebP、およびAPNGの録画。 +- e-Readerのサポート。 +- キーボードとゲームパッドのリマップ可能なコントロール。 +- ZIPおよび7zファイルからの読み込み。 +- IPS、UPS、およびBPSパッチのサポート。 +- コマンドラインインターフェースとGDBリモートサポートを介したゲームデバッグ、GhidraおよびIDA Proと互換性あり。 +- 設定可能なエミュレーションの巻き戻し。 +- GameSharkおよびAction Replayスナップショットの読み込みおよびエクスポートのサポート。 +- RetroArch/LibretroおよびOpenEmu用のコア。 +- [Weblate](https://hosted.weblate.org/engage/mgba)を介した複数の言語のコミュニティ提供の翻訳。 +- その他、多くの小さな機能。 + +#### ゲームボーイマッパー + +以下のマッパーが完全にサポートされています: + +- MBC1 +- MBC1M +- MBC2 +- MBC3 +- MBC3+RTC +- MBC30 +- MBC5 +- MBC5+Rumble +- MBC7 +- Wisdom Tree(非公式) +- NT "old type" 1 and 2(非公式マルチカート) +- NT "new type"(非公式MBC5類似) +- Pokémon Jade/Diamond(非公式) +- Sachen MMC1(非公式) + +以下のマッパーが部分的にサポートされています: + +- MBC6(フラッシュメモリ書き込みサポートなし) +- MMM01 +- Pocket Cam +- TAMA5(RTCサポート不完全) +- HuC-1(IRサポートなし) +- HuC-3(IRサポートなし) +- Sachen MMC2(代替配線サポートなし) +- BBD(ロゴ切り替えなし) +- Hitek(ロゴ切り替えなし) +- GGB-81(ロゴ切り替えなし) +- Li Cheng(ロゴ切り替えなし) + +### 計画されている機能 + +- ネットワーク対応のマルチプレイヤーリンクケーブルサポート。 +- Dolphin/JOYバスリンクケーブルサポート。 +- MP2kオーディオミキシング、ハードウェアより高品質のサウンド。 +- ツールアシストランのための再録サポート。 +- 包括的なデバッグスイート。 +- ワイヤレスアダプターのサポート。 + +サポートされているプラットフォーム +------------------- + +- Windows 7以降 +- OS X 10.9(Mavericks)[[3]](#osxver)以降 +- Linux +- FreeBSD +- Nintendo 3DS +- Nintendo Switch +- Wii +- PlayStation Vita + +他のUnix系プラットフォーム(OpenBSDなど)も動作することが知られていますが、テストされておらず、完全にはサポートされていません。 + +### システム要件 + +要件は最小限です。Windows Vista以降を実行できるコンピュータであれば、エミュレーションを処理できるはずです。OpenGL 1.1以降のサポートも必要であり、シェーダーや高度な機能にはOpenGL 3.2以降が必要です。 + +ダウンロード +--------- + +ダウンロードは公式ウェブサイトの[ダウンロード][downloads]セクションで見つけることができます。ソースコードは[GitHub][source]で見つけることができます。 + +コントロール +-------- + +コントロールは設定メニューで設定可能です。多くのゲームコントローラーはデフォルトで自動的にマッピングされるはずです。デフォルトのキーボードコントロールは次のとおりです: + +- **A**:X +- **B**:Z +- **L**:A +- **R**:S +- **Start**:Enter +- **Select**:Backspace + +コンパイル +--------- + +コンパイルにはCMake 3.1以降の使用が必要です。GCC、Clang、およびVisual Studio 2019はmGBAのコンパイルに使用できることが知られています。 + +#### Dockerビルド + +ほとんどのプラットフォームでのビルドにはDockerを使用することをお勧めします。いくつかのプラットフォームでmGBAをビルドするために必要なツールチェーンと依存関係を含むいくつかのDockerイメージが提供されています。 + +注意:Windows 10以前の古いWindowsシステムを使用している場合、DockerがVirtualBox共有フォルダーを使用して現在の`mgba`チェックアウトディレクトリをDockerイメージの作業ディレクトリに正しくマッピングするように構成する必要がある場合があります。(詳細については、issue [#1985](https://mgba.io/i/1985)を参照してください。) + +Dockerイメージを使用してmGBAをビルドするには、mGBAのチェックアウトのルートで次のコマンドを実行します: + + docker run --rm -it -v ${PWD}:/home/mgba/src mgba/windows:w32 + +Dockerコンテナを起動した後、ビルド成果物を含む`build-win32`ディレクトリが生成されます。他のプラットフォーム用のDockerイメージに置き換えると、対応する他のディレクトリが生成されます。Docker Hubで利用可能なDockerイメージは次のとおりです: + +- mgba/3ds +- mgba/switch +- mgba/ubuntu:xenial +- mgba/ubuntu:bionic +- mgba/ubuntu:focal +- mgba/ubuntu:groovy +- mgba/vita +- mgba/wii +- mgba/windows:w32 +- mgba/windows:w64 + +ビルドプロセスを高速化したい場合は、`-e MAKEFLAGS=-jN`フラグを追加して、`N`個のCPUコアでmGBAの並列ビルドを行うことを検討してください。 + +#### *nixビルド + +UnixベースのシステムでCMakeを使用してビルドするには、次のコマンドを実行することをお勧めします: + + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .. + make + sudo make install + +これにより、mGBAがビルドされ、`/usr/bin`および`/usr/lib`にインストールされます。インストールされている依存関係は自動的に検出され、依存関係が見つからない場合に無効になる機能は、`cmake`コマンドを実行した後に警告として表示されます。 + +macOSを使用している場合、手順は少し異なります。homebrewパッケージマネージャーを使用していると仮定すると、依存関係を取得してビルドするための推奨コマンドは次のとおりです: + + brew install cmake ffmpeg libzip qt5 sdl2 libedit lua pkg-config + mkdir build + cd build + cmake -DCMAKE_PREFIX_PATH=`brew --prefix qt5` .. + make + +macOSでは`make install`を実行しないでください。正しく動作しないためです。 + +#### Windows開発者ビルド + +##### MSYS2 + +Windowsでの開発用ビルドにはMSYS2を使用することをお勧めします。MSYS2の[ウェブサイト](https://msys2.github.io)に記載されているインストール手順に従ってください。32ビットバージョン(「MSYS2 MinGW 32-bit」)を実行していることを確認してください(x86_64用にビルドする場合は64ビットバージョン「MSYS2 MinGW 64-bit」を実行してください)。必要な依存関係をインストールするために次の追加コマンド(中括弧を含む)を実行します(このコマンドは1100MiB以上のパッケージをダウンロードするため、長時間かかることに注意してください): + + pacman -Sy --needed base-devel git ${MINGW_PACKAGE_PREFIX}-{cmake,ffmpeg,gcc,gdb,libelf,libepoxy,libzip,lua,pkgconf,qt5,SDL2,ntldd-git} + +次のコマンドを実行してソースコードをチェックアウトします: + + git clone https://github.com/mgba-emu/mgba.git + +最後に、次のコマンドを実行してビルドします: + + mkdir -p mgba/build + cd mgba/build + cmake .. -G "MSYS Makefiles" + make -j$(nproc --ignore=1) + +このWindows用mGBAビルドは、実行に必要なDLLが分散しているため、配布には適していないことに注意してください。ただし、開発には最適です。ただし、そのようなビルドを配布する必要がある場合(たとえば、MSYS2環境がインストールされていないマシンでのテスト用)、`cpack -G ZIP`を実行すると、必要なDLLをすべて含むzipファイルが準備されます。 + +##### Visual Studio + +Visual Studioを使用してビルドするには、同様に複雑なセットアップが必要です。まず、[vcpkg](https://github.com/Microsoft/vcpkg)をインストールする必要があります。vcpkgをインストールした後、いくつかの追加パッケージをインストールする必要があります: + + vcpkg install ffmpeg[vpx,x264] libepoxy libpng libzip lua sdl2 sqlite3 + +このインストールでは、Nvidiaハードウェアでのハードウェアアクセラレーションビデオエンコーディングはサポートされません。これが重要な場合は、事前にCUDAをインストールし、前のコマンドに`ffmpeg[vpx,x264,nvcodec]`を置き換えます。 + +Qtもインストールする必要があります。ただし、Qtは合理的な組織ではなく、困窮している会社によって所有および運営されているため、最新バージョンのオフラインオープンソースエディションインストーラーは存在しないため、[旧バージョンのインストーラー](https://download.qt.io/official_releases/qt/5.12/5.12.9/qt-opensource-windows-x86-5.12.9.exe)に戻る必要があります(これには無用なアカウントの作成が必要ですが、一時的に無効なプロキシを設定するか、ネットワークを無効にすることで回避できます)、オンラインインストーラーを使用する(いずれにしてもアカウントが必要です)、またはvcpkgを使用してビルドする(遅い)。これらはすべて良い選択肢ではありません。インストーラーを使用する場合は、適用可能なMSVCバージョンをインストールする必要があります。オフラインインストーラーはMSVC 2019をサポートしていないことに注意してください。vcpkgを使用する場合、次のようにインストールする必要があります。特にクアッドコア以下のコンピュータではかなりの時間がかかります: + + vcpkg install qt5-base qt5-multimedia + +次に、Visual Studioを開き、「リポジトリのクローンを作成」を選択し、`https://github.com/mgba-emu/mgba.git`を入力します。Visual Studioがクローンを完了したら、「ファイル」>「CMake」に移動し、チェックアウトされたリポジトリのルートにあるCMakeLists.txtファイルを開きます。そこから、他のVisual Studio CMakeプロジェクトと同様にVisual StudioでmGBAを開発できます。 + +#### ツールチェーンビルド + +devkitARM(3DS用)、devkitPPC(Wii用)、devkitA64(Switch用)、またはvitasdk(PS Vita用)を持っている場合は、次のコマンドを使用してビルドできます: + + mkdir build + cd build + cmake -DCMAKE_TOOLCHAIN_FILE=../src/platform/3ds/CMakeToolchain.txt .. + make + +次のプラットフォーム用に`-DCMAKE_TOOLCHAIN_FILE`パラメータを置き換えます: + +- 3DS:`../src/platform/3ds/CMakeToolchain.txt` +- Switch:`../src/platform/switch/CMakeToolchain.txt` +- Vita:`../src/platform/psp2/CMakeToolchain.vitasdk` +- Wii:`../src/platform/wii/CMakeToolchain.txt` + +### 依存関係 + +mGBAには厳密な依存関係はありませんが、特定の機能には次のオプションの依存関係が必要です。依存関係が見つからない場合、これらの機能は無効になります。 + +- Qt 5:GUIフロントエンド用。オーディオにはQt MultimediaまたはSDLが必要です。 +- SDL:より基本的なフロントエンドおよびQtフロントエンドでのゲームパッドサポート用。SDL 2が推奨されますが、1.2もサポートされています。 +- zlibおよびlibpng:スクリーンショットサポートおよびPNG内セーブステートサポート用。 +- libedit:コマンドラインデバッガーサポート用。 +- ffmpegまたはlibav:ビデオ、GIF、WebP、およびAPNGの録画用。 +- libzipまたはzlib:zipファイルに保存されたROMの読み込み用。 +- SQLite3:ゲームデータベース用。 +- libelf:ELF読み込み用。 +- Lua:スクリプト用。 +- json-c:スクリプトの`storage` API用。 + +SQLite3、libpng、およびzlibはエミュレーターに含まれているため、最初に外部でコンパイルする必要はありません。 + +脚注 +--------- + +[1] 現在欠けている機能は次のとおりです + +- モード3、4、および5のOBJウィンドウ([バグ#5](http://mgba.io/b/5)) + +[2] フラッシュメモリサイズの検出は一部のケースで機能しません。これらは実行時に構成できますが、そのようなケースに遭遇した場合はバグを報告することをお勧めします。 + +[3] 10.9はQtポートにのみ必要です。10.7またはそれ以前のバージョンでQtポートをビルドまたは実行することは可能かもしれませんが、公式にはサポートされていません。SDLポートは10.5で動作することが知られており、古いバージョンでも動作する可能性があります。 + +[downloads]: http://mgba.io/downloads.html +[source]: https://github.com/mgba-emu/mgba/ + +著作権 +--------- + +mGBAの著作権は© 2013 – 2023 Jeffrey Pfauに帰属します。これは[Mozilla Public License version 2.0](https://www.mozilla.org/MPL/2.0/)の下で配布されています。配布されたLICENSEファイルにライセンスのコピーが含まれています。 + +mGBAには次のサードパーティライブラリが含まれています: + +- [inih](https://github.com/benhoyt/inih)、著作権© 2009 – 2020 Ben Hoyt、BSD 3-clauseライセンスの下で使用。 +- [LZMA SDK](http://www.7-zip.org/sdk.html)、パブリックドメイン。 +- [MurmurHash3](https://github.com/aappleby/smhasher)、Austin Applebyによる実装、パブリックドメイン。 +- [getopt for MSVC](https://github.com/skandhurkat/Getopt-for-Visual-Studio/)、パブリックドメイン。 +- [SQLite3](https://www.sqlite.org)、パブリックドメイン。 + +ゲームパブリッシャーであり、商業利用のためにmGBAのライセンスを取得したい場合は、[licensing@mgba.io](mailto:licensing@mgba.io)までメールでお問い合わせください。 From e518a5ced001834ad09b23b489159c1b00d70035 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 19 Jan 2025 16:57:30 -0800 Subject: [PATCH 13/31] Debugger: Define and use mDebuggerModuleClearNeedsCallback --- src/debugger/access-logger.c | 2 +- src/debugger/debugger.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/debugger/access-logger.c b/src/debugger/access-logger.c index 7133565e9..b9e8222d1 100644 --- a/src/debugger/access-logger.c +++ b/src/debugger/access-logger.c @@ -377,7 +377,7 @@ void mDebuggerAccessLoggerStop(struct mDebuggerAccessLogger* logger) { logger->d.p->platform->clearBreakpoint(logger->d.p->platform, region->watchpoint); region->watchpoint = -1; } - logger->d.needsCallback = false; + mDebuggerModuleClearNeedsCallback(&logger->d); } static int _mDebuggerAccessLoggerWatchMemoryBlock(struct mDebuggerAccessLogger* logger, const struct mCoreMemoryBlock* block, mDebuggerAccessLogRegionFlags flags) { diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index a03f106d9..995a28099 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -320,3 +320,8 @@ void mDebuggerModuleSetNeedsCallback(struct mDebuggerModule* debugger) { debugger->needsCallback = true; mDebuggerUpdatePaused(debugger->p); } + +void mDebuggerModuleClearNeedsCallback(struct mDebuggerModule* debugger) { + debugger->needsCallback = false; + mDebuggerUpdatePaused(debugger->p); +} From ed64b35db7b933dc77cdd706ab7662d1e1166925 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 19 Jan 2025 18:41:06 -0800 Subject: [PATCH 14/31] CMake: Default macOS SDK version to OS version if not found --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 42712e91c..ad464bab0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,6 +241,10 @@ endif() if(APPLE) execute_process(COMMAND xcrun --show-sdk-version OUTPUT_VARIABLE MACOSX_SDK) + if(NOT MACOSX_SDK) + message(WARNING "Could not detect SDK version; defaulting to system version. Is SDKROOT set?") + set(MACOSX_SDK ${CMAKE_SYSTEM_VERSION}) + endif() add_definitions(-D_DARWIN_C_SOURCE) list(APPEND OS_LIB "-framework Foundation") From 2c0e57284104a6ed5824a8bc678775f699c0ec43 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 20 Jan 2025 00:26:05 -0800 Subject: [PATCH 15/31] CHANGES: Add missing entries --- CHANGES | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGES b/CHANGES index 68638bb67..b740f4657 100644 --- a/CHANGES +++ b/CHANGES @@ -1,11 +1,17 @@ 0.11.0: (Future) Features: + - Forwarder support for 3DS and Vita + - Custom border support - New option to lock the maximum frame size + - Memory access and information logging - Scripting: New `input` API for getting raw keyboard/mouse/controller state - Scripting: New `storage` API for saving data for a script, e.g. settings + - Scripting: New `image` and `canvas` APIs for drawing images and displaying on-screen - Scripting: Debugger integration to allow for breakpoints and watchpoints - New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81 + - Initial support for bootleg GBA multicarts - Debugger: Add range watchpoints + - "Headless" frontend for running tests, automation, etc. Emulation fixes: - ARM: Add framework for coprocessor support - GB Serialize: Add missing Pocket Cam state to savestates @@ -30,6 +36,7 @@ Misc: - Core: Handle relative paths for saves, screenshots, etc consistently (fixes mgba.io/i/2826) - Core: Improve rumble emulation by averaging state over entire frame (fixes mgba.io/i/3232) - Core: Add MD5 hashing for ROMs + - Core: Add support for specifying an arbitrary portable directory - GB: Prevent incompatible BIOSes from being used on differing models - GB Serialize: Add missing savestate support for MBC6 and NT (newer) - GBA: Improve detection of valid ELF ROMs @@ -48,7 +55,11 @@ Misc: - Qt: Show maker code and game version in ROM info - Qt: Show a dummy shader settings tab if shaders aren't supported - Qt: Allow passing multiple games on command line for multiplayer (closes mgba.io/i/3061) + - Qt: Support building against Qt 6 + - Qt: Add shortcuts to increment fast forward speed (mgba.io/i/2903) + - Res: Port hq2x and OmniScale shaders from SameBoy - Res: Port NSO-gba-colors shader (closes mgba.io/i/2834) + - Res: Update gba-colors shader (closes mgba.io/i/2976) - Scripting: Add `callbacks:oneshot` for single-call callbacks - Updater: Fix rewriting folders and files on Windows (fixes mgba.io/i/3384) From 7fe4f4593ed4124412dc1224404f55131a5c0238 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 20 Jan 2025 16:51:18 -0800 Subject: [PATCH 16/31] GBA Savedata: Rename flash ID constants, add missing entries --- include/mgba/internal/gba/savedata.h | 10 +++++++--- src/gba/savedata.c | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/mgba/internal/gba/savedata.h b/include/mgba/internal/gba/savedata.h index e69d07834..7fec242c4 100644 --- a/include/mgba/internal/gba/savedata.h +++ b/include/mgba/internal/gba/savedata.h @@ -45,9 +45,13 @@ enum FlashStateMachine { FLASH_STATE_CONTINUE = 2, }; -enum FlashManufacturer { - FLASH_MFG_PANASONIC = 0x1B32, - FLASH_MFG_SANYO = 0x1362 +enum FlashId { + FLASH_ATMEL_AT29LV512 = 0x3D1F, // 512k + FLASH_MACRONIX_MX29L512 = 0x1CC2, // 512k, unused + FLASH_MACRONIX_MX29L010 = 0x09C2, // 1M + FLASH_PANASONIC_MN63F805MNP = 0x1B32, // 512k, unused + FLASH_SANYO_LE26FV10N1TS = 0x1362, // 1M + FLASH_SST_39LVF512 = 0xD4BF, // 512k }; enum { diff --git a/src/gba/savedata.c b/src/gba/savedata.c index 50d2be381..13204cbb3 100644 --- a/src/gba/savedata.c +++ b/src/gba/savedata.c @@ -372,11 +372,11 @@ uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address) { if (savedata->command == FLASH_COMMAND_ID) { if (savedata->type == GBA_SAVEDATA_FLASH512) { if (address < 2) { - return FLASH_MFG_PANASONIC >> (address * 8); + return FLASH_PANASONIC_MN63F805MNP >> (address * 8); } } else if (savedata->type == GBA_SAVEDATA_FLASH1M) { if (address < 2) { - return FLASH_MFG_SANYO >> (address * 8); + return FLASH_SANYO_LE26FV10N1TS >> (address * 8); } } } From 2dd11712db3cb8763c6b9f06b6b12ce1ffd34945 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 21 Jan 2025 00:33:20 -0800 Subject: [PATCH 17/31] Python: Fix some missing constants (fixes #3402) --- src/platform/python/mgba/gba.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/platform/python/mgba/gba.py b/src/platform/python/mgba/gba.py index 0c249cec5..91ac3254e 100644 --- a/src/platform/python/mgba/gba.py +++ b/src/platform/python/mgba/gba.py @@ -54,7 +54,7 @@ class GBA(Core): class GBAMemory(Memory): - def __init__(self, core, romSize=lib.SIZE_CART0): + def __init__(self, core, romSize=lib.GBA_SIZE_ROM0): super(GBAMemory, self).__init__(core, 0x100000000) self.bios = Memory(core, lib.GBA_SIZE_BIOS, lib.GBA_BASE_BIOS) @@ -64,11 +64,10 @@ class GBAMemory(Memory): self.palette = Memory(core, lib.GBA_SIZE_PALETTE_RAM, lib.GBA_BASE_PALETTE_RAM) self.vram = Memory(core, lib.GBA_SIZE_VRAM, lib.GBA_BASE_VRAM) self.oam = Memory(core, lib.GBA_SIZE_OAM, lib.GBA_BASE_OAM) - self.cart0 = Memory(core, romSize, lib.BASE_CART0) - self.cart1 = Memory(core, romSize, lib.BASE_CART1) - self.cart2 = Memory(core, romSize, lib.BASE_CART2) - self.cart = self.cart0 - self.rom = self.cart0 + self.rom0 = Memory(core, romSize, lib.GBA_BASE_ROM0) + self.rom1 = Memory(core, romSize, lib.GBA_BASE_ROM1) + self.rom2 = Memory(core, romSize, lib.GBA_BASE_ROM2) + self.rom = self.rom0 self.sram = Memory(core, lib.GBA_SIZE_SRAM, lib.GBA_BASE_SRAM) From 92e10f31eaadb64b96c73e0da23406c8565a0ed3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 21 Jan 2025 00:50:34 -0800 Subject: [PATCH 18/31] Qt: Fix regression where loading BIOS creates a save file (fixes #3359) --- CHANGES | 1 + src/platform/qt/CoreController.cpp | 3 +++ src/platform/qt/CoreController.h | 2 ++ src/platform/qt/CoreManager.cpp | 1 + 4 files changed, 7 insertions(+) diff --git a/CHANGES b/CHANGES index b740f4657..a4057d775 100644 --- a/CHANGES +++ b/CHANGES @@ -32,6 +32,7 @@ Other fixes: - mGUI: Load parent directory if last used directory is missing (fixes mgba.io/i/3379) - Qt: Fix savestate preview sizes with different scales (fixes mgba.io/i/2560) - Qt: Fix potential crash when configuring shortcuts + - Qt: Fix regression where loading BIOS creates a save file (fixes mgba.io/i/3359) Misc: - Core: Handle relative paths for saves, screenshots, etc consistently (fixes mgba.io/i/2826) - Core: Improve rumble emulation by averaging state over entire frame (fixes mgba.io/i/3232) diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 152efc222..53d5b3892 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -1267,6 +1267,9 @@ void CoreController::finishFrame() { } void CoreController::updatePlayerSave() { + if (m_saveBlocked) { + return; + } int savePlayerId = m_multiplayer->saveId(this); QString saveSuffix; diff --git a/src/platform/qt/CoreController.h b/src/platform/qt/CoreController.h index a2ebe410e..4de454d4b 100644 --- a/src/platform/qt/CoreController.h +++ b/src/platform/qt/CoreController.h @@ -176,6 +176,7 @@ public slots: void scanCards(const QStringList&); void replaceGame(const QString&); void yankPak(); + void blockSave() { m_saveBlocked = true; } void addKey(int key); void clearKey(int key); @@ -263,6 +264,7 @@ private: bool m_patched = false; bool m_preload = false; + bool m_saveBlocked = false; uint32_t m_crc32; QString m_internalTitle; diff --git a/src/platform/qt/CoreManager.cpp b/src/platform/qt/CoreManager.cpp index b2f7cabf0..385b3440b 100644 --- a/src/platform/qt/CoreManager.cpp +++ b/src/platform/qt/CoreManager.cpp @@ -169,6 +169,7 @@ CoreController* CoreManager::loadBIOS(int platform, const QString& path) { mDirectorySetAttachBase(&core->dirs, VDirOpen(bytes.constData())); CoreController* cc = new CoreController(core); + cc->blockSave(); if (m_multiplayer) { cc->setMultiplayerController(m_multiplayer); } From 2e7918d8b2ccc0c92d212a14884df655fbb3abeb Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 7 Feb 2025 03:03:09 -0800 Subject: [PATCH 19/31] GBA: Update some register information with new stereoscopy discoveries --- include/mgba/internal/gba/io.h | 2 +- include/mgba/internal/gba/renderers/video-software.h | 2 +- include/mgba/internal/gba/video.h | 4 +++- src/gba/io.c | 2 +- src/gba/renderers/video-software.c | 8 ++++---- src/gba/video.c | 2 +- src/platform/qt/IOViewer.cpp | 2 +- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/mgba/internal/gba/io.h b/include/mgba/internal/gba/io.h index 197e19d62..2891c650c 100644 --- a/include/mgba/internal/gba/io.h +++ b/include/mgba/internal/gba/io.h @@ -17,7 +17,7 @@ CXX_GUARD_START enum GBAIORegisters { // Video GBA_REG_DISPCNT = 0x000, - GBA_REG_GREENSWP = 0x002, + GBA_REG_STEREOCNT = 0x002, GBA_REG_DISPSTAT = 0x004, GBA_REG_VCOUNT = 0x006, GBA_REG_BG0CNT = 0x008, diff --git a/include/mgba/internal/gba/renderers/video-software.h b/include/mgba/internal/gba/renderers/video-software.h index d9a012fa8..ce918775a 100644 --- a/include/mgba/internal/gba/renderers/video-software.h +++ b/include/mgba/internal/gba/renderers/video-software.h @@ -110,7 +110,7 @@ struct GBAVideoSoftwareRenderer { uint16_t bldy; GBAMosaicControl mosaic; - bool greenswap; + bool stereo; struct WindowN { struct GBAVideoWindowRegion h; diff --git a/include/mgba/internal/gba/video.h b/include/mgba/internal/gba/video.h index 5fc68eb59..5ee2bc36f 100644 --- a/include/mgba/internal/gba/video.h +++ b/include/mgba/internal/gba/video.h @@ -42,7 +42,8 @@ enum { enum GBAVideoObjMode { OBJ_MODE_NORMAL = 0, OBJ_MODE_SEMITRANSPARENT = 1, - OBJ_MODE_OBJWIN = 2 + OBJ_MODE_OBJWIN = 2, + OBJ_MODE_STEREO = 3, }; enum GBAVideoObjShape { @@ -142,6 +143,7 @@ DECL_BITS(GBARegisterDISPSTAT, VcountSetting, 8, 8); DECL_BITFIELD(GBARegisterBGCNT, uint16_t); DECL_BITS(GBARegisterBGCNT, Priority, 0, 2); DECL_BITS(GBARegisterBGCNT, CharBase, 2, 2); +DECL_BITS(GBARegisterBGCNT, StereoMode, 4, 2); DECL_BIT(GBARegisterBGCNT, Mosaic, 6); DECL_BIT(GBARegisterBGCNT, 256Color, 7); DECL_BITS(GBARegisterBGCNT, ScreenBase, 8, 5); diff --git a/src/gba/io.c b/src/gba/io.c index cb6058f7f..0747986f0 100644 --- a/src/gba/io.c +++ b/src/gba/io.c @@ -934,7 +934,7 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { } // Fall through case GBA_REG_DISPCNT: - case GBA_REG_GREENSWP: + case GBA_REG_STEREOCNT: case GBA_REG_DISPSTAT: case GBA_REG_VCOUNT: case GBA_REG_BG0CNT: diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index 83550bcfa..e2dab9033 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -136,7 +136,7 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) { softwareRenderer->oamMax = 0; softwareRenderer->mosaic = 0; - softwareRenderer->greenswap = false; + softwareRenderer->stereo = false; softwareRenderer->nextY = 0; softwareRenderer->objOffsetX = 0; @@ -195,8 +195,8 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender softwareRenderer->dispcnt = value; GBAVideoSoftwareRendererUpdateDISPCNT(softwareRenderer); break; - case GBA_REG_GREENSWP: - softwareRenderer->greenswap = value & 1; + case GBA_REG_STEREOCNT: + softwareRenderer->stereo = value & 1; break; case GBA_REG_BG0CNT: value &= 0xDFFF; @@ -705,7 +705,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render } int x; - if (softwareRenderer->greenswap) { + if (softwareRenderer->stereo) { for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; x += 4) { row[x] = softwareRenderer->row[x] & (M_COLOR_RED | M_COLOR_BLUE); row[x] |= softwareRenderer->row[x + 1] & M_COLOR_GREEN; diff --git a/src/gba/video.c b/src/gba/video.c index 749a29be0..a86413251 100644 --- a/src/gba/video.c +++ b/src/gba/video.c @@ -128,7 +128,7 @@ void GBAVideoAssociateRenderer(struct GBAVideo* video, struct GBAVideoRenderer* video->renderer->init(video->renderer); video->renderer->reset(video->renderer); renderer->writeVideoRegister(renderer, GBA_REG_DISPCNT, video->p->memory.io[GBA_REG(DISPCNT)]); - renderer->writeVideoRegister(renderer, GBA_REG_GREENSWP, video->p->memory.io[GBA_REG(GREENSWP)]); + renderer->writeVideoRegister(renderer, GBA_REG_STEREOCNT, video->p->memory.io[GBA_REG(STEREOCNT)]); int address; for (address = GBA_REG_BG0CNT; address < 0x56; address += 2) { if (address == 0x4E) { diff --git a/src/platform/qt/IOViewer.cpp b/src/platform/qt/IOViewer.cpp index 9b44af04f..8ef921b7c 100644 --- a/src/platform/qt/IOViewer.cpp +++ b/src/platform/qt/IOViewer.cpp @@ -60,7 +60,7 @@ const QList& IOViewer::registerDescriptions(mPlat { tr("Enable Window 1"), 14 }, { tr("Enable OBJ Window"), 15 }, }); - // 0x04000002: Green swap + // 0x04000002: STEREOCNT regGBA.append({ { tr("Swap green components"), 0 }, }); From d3653127571b8fe1421e5d5acaa8f4c6d5dbfca1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 7 Feb 2025 18:02:53 -0800 Subject: [PATCH 20/31] ARM Debugger: Fix disassembly of ror r0 barrel shift (fixes #3412) --- CHANGES | 1 + src/arm/decoder-arm.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index a4057d775..035e9ae8c 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,7 @@ Emulation fixes: - GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722) - GBA Video: Improve emulation of window start/end conditions (fixes mgba.io/i/1945) Other fixes: + - ARM Debugger: Fix disassembly of ror r0 barrel shift (fixes mgba.io/i/3412) - Core: Fix inconsistencies with setting game-specific overrides (fixes mgba.io/i/2963) - Debugger: Fix writing to specific segment in command-line debugger - FFmpeg: Fix failing to record videos with CRF video (fixes mgba.io/i/3368) diff --git a/src/arm/decoder-arm.c b/src/arm/decoder-arm.c index 73d1717e9..074c04314 100644 --- a/src/arm/decoder-arm.c +++ b/src/arm/decoder-arm.c @@ -36,7 +36,7 @@ #define ADDR_MODE_1_ASR ADDR_MODE_1_SHIFT(ASR) #define ADDR_MODE_1_ROR \ ADDR_MODE_1_SHIFT(ROR) \ - if (!info->op3.shifterImm) { \ + if ((info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_3) && !info->op3.shifterImm) { \ info->op3.shifterOp = ARM_SHIFT_RRX; \ } From 55f21cd9512a1d062f8186d075f54e4867e464f2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 9 Feb 2025 16:26:36 -0800 Subject: [PATCH 21/31] mGUI: Fix saving integer config values --- src/feature/gui/gui-config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feature/gui/gui-config.c b/src/feature/gui/gui-config.c index 6214abc15..6ad52d090 100644 --- a/src/feature/gui/gui-config.c +++ b/src/feature/gui/gui-config.c @@ -341,7 +341,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t mCoreConfigSetUIntValue(&runner->config, item->data.v.s, v->v.u); break; case GUI_VARIANT_INT: - mCoreConfigSetUIntValue(&runner->config, item->data.v.s, v->v.i); + mCoreConfigSetIntValue(&runner->config, item->data.v.s, v->v.i); break; case GUI_VARIANT_FLOAT: mCoreConfigSetFloatValue(&runner->config, item->data.v.s, v->v.f); From fc14b4b0da6ea6987f9f3be3d94ed6bace022e3b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 9 Feb 2025 16:27:34 -0800 Subject: [PATCH 22/31] mGUI: Add better description of the fastForwardMute option --- src/feature/gui/gui-config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feature/gui/gui-config.c b/src/feature/gui/gui-config.c index 6ad52d090..228a3f647 100644 --- a/src/feature/gui/gui-config.c +++ b/src/feature/gui/gui-config.c @@ -109,7 +109,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t .nStates = 2 }; *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { - .title = "Fast forward mute", + .title = "Mute while fast forwarding", .data = GUI_V_S("fastForwardMute"), .submenu = 0, .state = false, From a9041b122ff7d6d16482a3ca2a58c24b103d69ed Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 10 Feb 2025 02:23:53 -0800 Subject: [PATCH 23/31] GBA Video: Allow proxy flush timing configuration --- include/mgba/internal/gba/renderers/proxy.h | 1 + src/gba/core.c | 12 ++++++++++++ src/gba/extra/proxy.c | 8 +++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/mgba/internal/gba/renderers/proxy.h b/include/mgba/internal/gba/renderers/proxy.h index 6cb58d092..3d70d5666 100644 --- a/include/mgba/internal/gba/renderers/proxy.h +++ b/include/mgba/internal/gba/renderers/proxy.h @@ -17,6 +17,7 @@ struct GBAVideoProxyRenderer { struct GBAVideoRenderer d; struct GBAVideoRenderer* backend; struct mVideoLogger* logger; + int flushScanline; }; void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct GBAVideoRenderer* backend, struct mVideoLogger* logger); diff --git a/src/gba/core.c b/src/gba/core.c index da782d06c..b369c92df 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -479,6 +479,14 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c GBAVideoAssociateRenderer(&gba->video, renderer); } } + +#ifndef MINIMAL_CORE + if (strcmp("threadedVideo.flushScanline", option) == 0) { + int flushScanline = -1; + mCoreConfigGetIntValue(config, "threadedVideo.flushScanline", &flushScanline); + gbacore->proxyRenderer.flushScanline = flushScanline; + } +#endif } static void _GBACoreSetOverride(struct mCore* core, const void* override) { @@ -730,6 +738,10 @@ static void _GBACoreReset(struct mCore* core) { if (renderer && core->videoLogger) { GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer, core->videoLogger); renderer = &gbacore->proxyRenderer.d; + + int flushScanline = -1; + mCoreConfigGetIntValue(&core->config, "threadedVideo.flushScanline", &flushScanline); + gbacore->proxyRenderer.flushScanline = flushScanline; } #endif if (renderer) { diff --git a/src/gba/extra/proxy.c b/src/gba/extra/proxy.c index e33c7b568..bcf91f5f4 100644 --- a/src/gba/extra/proxy.c +++ b/src/gba/extra/proxy.c @@ -75,6 +75,7 @@ void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct logger->vramSize = GBA_SIZE_VRAM; logger->oamSize = GBA_SIZE_OAM; + renderer->flushScanline = -1; renderer->backend = backend; } @@ -359,6 +360,9 @@ void GBAVideoProxyRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t o void GBAVideoProxyRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) { struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; + if (proxyRenderer->flushScanline == y) { + mVideoLoggerRendererFlush(proxyRenderer->logger); + } if (!proxyRenderer->logger->block) { _copyExtraState(proxyRenderer); proxyRenderer->backend->drawScanline(proxyRenderer->backend, y); @@ -375,7 +379,9 @@ void GBAVideoProxyRendererFinishFrame(struct GBAVideoRenderer* renderer) { proxyRenderer->backend->finishFrame(proxyRenderer->backend); } mVideoLoggerRendererFinishFrame(proxyRenderer->logger); - mVideoLoggerRendererFlush(proxyRenderer->logger); + if (proxyRenderer->flushScanline < 0) { + mVideoLoggerRendererFlush(proxyRenderer->logger); + } } static void GBAVideoProxyRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) { From daf01b03d5316dac966acd4b05318a225cab12f5 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 10 Feb 2025 02:24:15 -0800 Subject: [PATCH 24/31] 3DS: Expose late thread flush as "loose sync" --- CHANGES | 1 + src/feature/gui/gui-runner.c | 1 + src/platform/3ds/main.c | 17 +++++++++++++++++ 3 files changed, 19 insertions(+) diff --git a/CHANGES b/CHANGES index 035e9ae8c..af0702264 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ Features: - Custom border support - New option to lock the maximum frame size - Memory access and information logging + - 3DS: Add faster "loose" sync mode, default enabled - Scripting: New `input` API for getting raw keyboard/mouse/controller state - Scripting: New `storage` API for saving data for a script, e.g. settings - Scripting: New `image` and `canvas` APIs for drawing images and displaying on-screen diff --git a/src/feature/gui/gui-runner.c b/src/feature/gui/gui-runner.c index 76e15cdad..407a59781 100644 --- a/src/feature/gui/gui-runner.c +++ b/src/feature/gui/gui-runner.c @@ -702,6 +702,7 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) { mCoreConfigGetIntValue(&runner->config, "showOSD", &showOSD); mCoreConfigGetIntValue(&runner->config, "mute", &mute); mCoreConfigGetIntValue(&runner->config, "fastForwardMute", &fastForwardMute); + runner->core->reloadConfigOption(runner->core, "threadedVideo.flushScanline", &runner->config); #ifdef M_CORE_GB if (runner->core->platform(runner->core) == mPLATFORM_GB) { runner->core->reloadConfigOption(runner->core, "gb.pal", &runner->config); diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c index 2d7f80d15..7bac5f61e 100644 --- a/src/platform/3ds/main.c +++ b/src/platform/3ds/main.c @@ -273,6 +273,7 @@ static void _resetCamera(struct m3DSImageSource* imageSource) { static void _setup(struct mGUIRunner* runner) { if (core2) { mCoreConfigSetDefaultIntValue(&runner->config, "threadedVideo", 1); + mCoreConfigSetDefaultIntValue(&runner->config, "threadedVideo.flushScanline", 0); mCoreLoadForeignConfig(runner->core, &runner->config); } @@ -968,6 +969,22 @@ int main(int argc, char* argv[]) { { .id = 0 } }, .configExtra = (struct GUIMenuItem[]) { +#ifdef M_CORE_GBA + { + .title = "Sync", + .data = GUI_V_S("threadedVideo.flushScanline"), + .state = 0, + .validStates = (const char*[]) { + "Loose (faster, can tear)", "Strict (slower, less input lag)" + }, + .stateMappings = (const struct GUIVariant[]) { + GUI_V_I(0), + GUI_V_I(-1), + }, + .nStates = 2 + }, +#endif + { .title = "Screen mode", .data = GUI_V_S("screenMode"), From 6221cd2d066713da656d45b84ab15ad99df085a7 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 11 Feb 2025 05:12:35 -0800 Subject: [PATCH 25/31] Qt: Enable ROM preloading by default --- CHANGES | 1 + src/platform/qt/ConfigController.cpp | 1 + src/platform/qt/CoreController.cpp | 2 +- src/platform/qt/CoreController.h | 2 +- src/platform/qt/CoreManager.h | 2 +- src/platform/qt/SettingsView.cpp | 2 +- src/platform/qt/SettingsView.ui | 3 +++ 7 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index af0702264..cdef7640e 100644 --- a/CHANGES +++ b/CHANGES @@ -60,6 +60,7 @@ Misc: - Qt: Allow passing multiple games on command line for multiplayer (closes mgba.io/i/3061) - Qt: Support building against Qt 6 - Qt: Add shortcuts to increment fast forward speed (mgba.io/i/2903) + - Qt: Enable ROM preloading by default - Res: Port hq2x and OmniScale shaders from SameBoy - Res: Port NSO-gba-colors shader (closes mgba.io/i/2834) - Res: Update gba-colors shader (closes mgba.io/i/2976) diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp index a12768709..eae75fea4 100644 --- a/src/platform/qt/ConfigController.cpp +++ b/src/platform/qt/ConfigController.cpp @@ -149,6 +149,7 @@ ConfigController::ConfigController(QObject* parent) mCoreConfigSetDefaultIntValue(&m_config, "sgb.borders", 1); mCoreConfigSetDefaultIntValue(&m_config, "gb.colors", GB_COLORS_CGB); #endif + mCoreConfigSetDefaultIntValue(&m_config, "preload", true); mCoreConfigMap(&m_config, &m_opts); mSubParserGraphicsInit(&m_subparsers[0], &m_graphicsOpts); diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 53d5b3892..7cd6c58d5 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -305,7 +305,7 @@ void CoreController::loadConfig(ConfigController* config) { m_fastForwardMute = config->getOption("fastForwardMute", -1).toInt(); mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "volume"); mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "mute"); - m_preload = config->getOption("preload").toInt(); + m_preload = config->getOption("preload", true).toInt(); QSize sizeBefore = screenDimensions(); m_activeBuffer.resize(256 * 224 * sizeof(mColor)); diff --git a/src/platform/qt/CoreController.h b/src/platform/qt/CoreController.h index 4de454d4b..a6b6a03ca 100644 --- a/src/platform/qt/CoreController.h +++ b/src/platform/qt/CoreController.h @@ -263,7 +263,7 @@ private: QString m_savePath; bool m_patched = false; - bool m_preload = false; + bool m_preload = true; bool m_saveBlocked = false; uint32_t m_crc32; diff --git a/src/platform/qt/CoreManager.h b/src/platform/qt/CoreManager.h index da7460f22..e910886f6 100644 --- a/src/platform/qt/CoreManager.h +++ b/src/platform/qt/CoreManager.h @@ -36,7 +36,7 @@ signals: private: const mCoreConfig* m_config = nullptr; MultiplayerController* m_multiplayer = nullptr; - bool m_preload = false; + bool m_preload = true; }; } diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index f4eea01db..195fe0441 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -747,7 +747,7 @@ void SettingsView::reloadConfig() { loadSetting("patchPath", m_ui.patchPath); loadSetting("cheatsPath", m_ui.cheatsPath); loadSetting("showLibrary", m_ui.showLibrary); - loadSetting("preload", m_ui.preload); + loadSetting("preload", m_ui.preload, true); loadSetting("showFps", m_ui.showFps, true); loadSetting("cheatAutoload", m_ui.cheatAutoload, true); loadSetting("cheatAutosave", m_ui.cheatAutosave, true); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 8539e6bdb..bce56f730 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -1263,6 +1263,9 @@ Preload entire ROM into memory + + true + From 7607a5bea9fe608751eb705adbff55339755b47a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 12 Feb 2025 03:52:03 -0800 Subject: [PATCH 26/31] GB MBC: Add Sintax support --- CHANGES | 2 +- README.md | 1 + include/mgba/gb/interface.h | 1 + include/mgba/internal/gb/memory.h | 8 +++ include/mgba/internal/gb/serialize.h | 6 ++ src/gb/mbc.c | 21 +++++- src/gb/mbc/mbc-private.h | 2 + src/gb/mbc/unlicensed.c | 99 ++++++++++++++++++++++++++++ src/gb/memory.c | 12 ++++ src/platform/qt/GameBoy.cpp | 2 + 10 files changed, 152 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index cdef7640e..d7b13c1aa 100644 --- a/CHANGES +++ b/CHANGES @@ -9,7 +9,7 @@ Features: - Scripting: New `storage` API for saving data for a script, e.g. settings - Scripting: New `image` and `canvas` APIs for drawing images and displaying on-screen - Scripting: Debugger integration to allow for breakpoints and watchpoints - - New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81 + - New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81, Sintax - Initial support for bootleg GBA multicarts - Debugger: Add range watchpoints - "Headless" frontend for running tests, automation, etc. diff --git a/README.md b/README.md index d937fa0c9..5bb847e9f 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ The following mappers are partially supported: - Hitek (missing logo switching) - GGB-81 (missing logo switching) - Li Cheng (missing logo switching) +- Sintax (missing logo switching) ### Planned features diff --git a/include/mgba/gb/interface.h b/include/mgba/gb/interface.h index de26ef731..e9bec3044 100644 --- a/include/mgba/gb/interface.h +++ b/include/mgba/gb/interface.h @@ -50,6 +50,7 @@ enum GBMemoryBankControllerType { GB_UNL_GGB81 = 0x223, GB_UNL_SACHEN_MMC1 = 0x230, GB_UNL_SACHEN_MMC2 = 0x231, + GB_UNL_SINTAX = 0x240, }; enum GBVideoLayer { diff --git a/include/mgba/internal/gb/memory.h b/include/mgba/internal/gb/memory.h index e4b34088b..2d1278feb 100644 --- a/include/mgba/internal/gb/memory.h +++ b/include/mgba/internal/gb/memory.h @@ -261,6 +261,13 @@ struct GBSachenState { uint8_t baseBank; }; +struct GBSintaxState { + uint8_t mode; + uint8_t xorValues[4]; + uint8_t bankNo; + uint8_t romBankXor; +}; + union GBMBCState { struct GBMBC1State mbc1; struct GBMBC6State mbc6; @@ -274,6 +281,7 @@ union GBMBCState { struct GBPKJDState pkjd; struct GBBBDState bbd; struct GBSachenState sachen; + struct GBSintaxState sintax; }; struct mRotationSource; diff --git a/include/mgba/internal/gb/serialize.h b/include/mgba/internal/gb/serialize.h index e76d0accb..4963340e5 100644 --- a/include/mgba/internal/gb/serialize.h +++ b/include/mgba/internal/gb/serialize.h @@ -451,6 +451,12 @@ struct GBSerializedState { uint8_t unmaskedBank; uint8_t baseBank; } sachen; + struct { + uint8_t mode; + uint8_t xorValues[4]; + uint8_t bankNo; + uint8_t romBankXor; + } sintax; struct { uint8_t reserved[16]; } padding; diff --git a/src/gb/mbc.c b/src/gb/mbc.c index 397b50088..2a19575a8 100644 --- a/src/gb/mbc.c +++ b/src/gb/mbc.c @@ -113,7 +113,7 @@ static struct { {"M161", GB_MBC_AUTODETECT}, // TODO {"BBD", GB_UNL_BBD}, {"HITK", GB_UNL_HITEK}, - {"SNTX", GB_MBC_AUTODETECT}, // TODO + {"SNTX", GB_UNL_SINTAX}, {"NTO1", GB_UNL_NT_OLD_1}, {"NTO2", GB_UNL_NT_OLD_2}, {"NTN", GB_UNL_NT_NEW}, @@ -128,6 +128,8 @@ static struct { {"NGHK", GB_MBC_AUTODETECT}, // TODO {"GB81", GB_UNL_GGB81}, {"TPP1", GB_MBC_AUTODETECT}, // TODO + {"VF01", GB_MBC_AUTODETECT}, // TODO + {"SKL8", GB_MBC_AUTODETECT}, // TODO {NULL, GB_MBC_AUTODETECT}, }; @@ -223,6 +225,12 @@ static enum GBMemoryBankControllerType _detectUnlMBC(const uint8_t* mem, size_t return GB_UNL_LI_CHENG; } break; + case 0x6c1dcf2d: + case 0x99e3449d: + if (mem[0x7FFF] != 0x01) { // Make sure we're not using a "fixed" version + return GB_UNL_SINTAX; + } + break; } if (mem[0x104] == 0xCE && mem[0x144] == 0xED && mem[0x114] == 0x66) { @@ -504,6 +512,14 @@ void GBMBCInit(struct GB* gb) { gb->memory.sramAccess = true; } break; + case GB_UNL_SINTAX: + gb->memory.mbcWrite = _GBSintax; + gb->memory.mbcRead = _GBSintaxRead; + gb->memory.mbcReadBank1 = true; + if (gb->sramSize) { + gb->memory.sramAccess = true; + } + break; } gb->memory.currentBank = 1; @@ -559,6 +575,9 @@ void GBMBCReset(struct GB* gb) { GBMBCSwitchBank0(gb, gb->memory.romSize / GB_SIZE_CART_BANK0 - 2); GBMBCSwitchBank(gb, gb->memory.romSize / GB_SIZE_CART_BANK0 - 1); break; + case GB_UNL_SINTAX: + gb->memory.mbcState.sintax.mode = 0xF; + break; default: break; } diff --git a/src/gb/mbc/mbc-private.h b/src/gb/mbc/mbc-private.h index 4a07ab716..b6f7671a5 100644 --- a/src/gb/mbc/mbc-private.h +++ b/src/gb/mbc/mbc-private.h @@ -38,6 +38,7 @@ void _GBHitek(struct GB* gb, uint16_t address, uint8_t value); void _GBLiCheng(struct GB* gb, uint16_t address, uint8_t value); void _GBGGB81(struct GB* gb, uint16_t address, uint8_t value); void _GBSachen(struct GB* gb, uint16_t address, uint8_t value); +void _GBSintax(struct GB* gb, uint16_t address, uint8_t value); uint8_t _GBMBC2Read(struct GBMemory*, uint16_t address); uint8_t _GBMBC6Read(struct GBMemory*, uint16_t address); @@ -54,6 +55,7 @@ uint8_t _GBHitekRead(struct GBMemory*, uint16_t address); uint8_t _GBGGB81Read(struct GBMemory*, uint16_t address); uint8_t _GBSachenMMC1Read(struct GBMemory*, uint16_t address); uint8_t _GBSachenMMC2Read(struct GBMemory*, uint16_t address); +uint8_t _GBSintaxRead(struct GBMemory*, uint16_t address); void _GBMBCLatchRTC(struct mRTCSource* rtc, uint8_t* rtcRegs, time_t* rtcLastLatch); void _GBMBCAppendSaveSuffix(struct GB* gb, const void* buffer, size_t size); diff --git a/src/gb/mbc/unlicensed.c b/src/gb/mbc/unlicensed.c index 844c0d0cd..00b0ef303 100644 --- a/src/gb/mbc/unlicensed.c +++ b/src/gb/mbc/unlicensed.c @@ -500,3 +500,102 @@ uint8_t _GBSachenMMC2Read(struct GBMemory* memory, uint16_t address) { return 0xFF; } } + +static const uint8_t _sintaxReordering[16][8] = { + { 2, 1, 4, 3, 6, 5, 0, 7 }, + { 3, 2, 5, 4, 7, 6, 1, 0 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unknown + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unknown + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unknown + { 4, 5, 2, 3, 0, 1, 6, 7 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unknown + { 6, 7, 4, 5, 1, 3, 0, 2 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unknown + { 7, 6, 1, 0, 3, 2, 5, 4 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unknown + { 5, 4, 7, 6, 1, 0, 3, 2 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unknown + { 2, 3, 4, 5, 6, 7, 0, 1 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unknown + { 0, 1, 2, 3, 4, 5, 6, 7 }, +}; + +void _GBSintax(struct GB* gb, uint16_t address, uint8_t value) { + struct GBSintaxState* state = &gb->memory.mbcState.sintax; + + if (address >= 0x2000 && address < 0x3000) { + state->bankNo = value; + value = _reorderBits(value, _sintaxReordering[state->mode]); + state->romBankXor = state->xorValues[state->bankNo & 0x3]; + } + + if ((address & 0xF0F0) == 0x5010) { + // contrary to previous belief it IS possible to change the mode after setting it initially + // The reason Metal Max was breaking is because it only recognises writes to 5x1x + // and that game writes to a bunch of other 5xxx addresses before battles + state->mode = value & 0xF; + + mLOG(GB_MBC, DEBUG, "Sintax bank reorder mode: %X", state->mode); + + switch (state->mode) { + // Supported modes + case 0x00: // Lion King, Golden Sun + case 0x01: // Langrisser + case 0x05: // Maple Story, Pokemon Platinum + case 0x07: // Bynasty Warriors 5 + case 0x09: // ??? + case 0x0B: // Shaolin Legend + case 0x0D: // Older games + case 0x0F: // Default mode, no reordering + break; + default: + mLOG(GB_MBC, DEBUG, "Bank reorder mode unsupported - %X", state->mode); + break; + } + + _GBSintax(gb, 0x2000, state->bankNo); // fake a bank switch to select the correct bank + return; + } + + if (address >= 0x7000 && address < 0x8000) { + int xorNo = (address & 0x00F0) >> 4; + switch (xorNo) { + case 2: + state->xorValues[0] = value; + mLOG(GB_MBC, DEBUG, "Sintax XOR 0: %X", value); + break; + case 3: + state->xorValues[1] = value; + mLOG(GB_MBC, DEBUG, "Sintax XOR 1: %X", value); + break; + case 4: + state->xorValues[2] = value; + mLOG(GB_MBC, DEBUG, "Sintax XOR 2: %X", value); + break; + case 5: + state->xorValues[3] = value; + mLOG(GB_MBC, DEBUG, "Sintax XOR 3: %X", value); + break; + } + + // xor is applied immediately to the current bank + state->romBankXor = state->xorValues[state->bankNo & 0x3]; + } + _GBMBC5(gb, address, value); +} + +uint8_t _GBSintaxRead(struct GBMemory* memory, uint16_t address) { + struct GBSintaxState* state = &memory->mbcState.sintax; + switch (address >> 13) { + case 0x2: + case 0x3: + return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)] ^ state->romBankXor; + case 0x5: + if (memory->sramAccess && memory->sram) { + return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)]; + } + return 0xFF; + default: + return 0xFF; + } +} diff --git a/src/gb/memory.c b/src/gb/memory.c index fdacc1a9b..05d4a9669 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -840,6 +840,12 @@ void GBMemorySerialize(const struct GB* gb, struct GBSerializedState* state) { state->memory.sachen.unmaskedBank = memory->mbcState.sachen.unmaskedBank; state->memory.sachen.baseBank = memory->mbcState.sachen.baseBank; break; + case GB_UNL_SINTAX: + state->memory.sintax.mode = memory->mbcState.sintax.mode; + memcpy(state->memory.sintax.xorValues, memory->mbcState.sintax.xorValues, sizeof(state->memory.sintax.xorValues)); + state->memory.sintax.bankNo = memory->mbcState.sintax.bankNo; + state->memory.sintax.romBankXor = memory->mbcState.sintax.romBankXor; + break; default: break; } @@ -1008,6 +1014,12 @@ void GBMemoryDeserialize(struct GB* gb, const struct GBSerializedState* state) { memory->mbcState.sachen.baseBank = state->memory.sachen.baseBank; GBMBCSwitchBank0(gb, memory->mbcState.sachen.baseBank & memory->mbcState.sachen.mask); break; + case GB_UNL_SINTAX: + memory->mbcState.sintax.mode = state->memory.sintax.mode; + memcpy(memory->mbcState.sintax.xorValues, state->memory.sintax.xorValues, sizeof(memory->mbcState.sintax.xorValues)); + memory->mbcState.sintax.bankNo = state->memory.sintax.bankNo; + memory->mbcState.sintax.romBankXor = state->memory.sintax.romBankXor; + break; default: break; } diff --git a/src/platform/qt/GameBoy.cpp b/src/platform/qt/GameBoy.cpp index b07982721..9f64ae3b1 100644 --- a/src/platform/qt/GameBoy.cpp +++ b/src/platform/qt/GameBoy.cpp @@ -44,6 +44,7 @@ static const QList s_mbcList{ GB_UNL_LI_CHENG, GB_UNL_SACHEN_MMC1, GB_UNL_SACHEN_MMC2, + GB_UNL_SINTAX, }; static QMap s_gbModelNames; @@ -102,6 +103,7 @@ QString GameBoy::mbcName(GBMemoryBankControllerType mbc) { s_mbcNames[GB_UNL_LI_CHENG] = tr("Li Cheng"); s_mbcNames[GB_UNL_SACHEN_MMC1] = tr("Sachen (MMC1)"); s_mbcNames[GB_UNL_SACHEN_MMC2] = tr("Sachen (MMC2)"); + s_mbcNames[GB_UNL_SINTAX] = tr("Sintax"); } return s_mbcNames[mbc]; From 8c98eafc77cd58e899734e272e672871010c8fce Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Wed, 12 Feb 2025 18:02:34 -0600 Subject: [PATCH 27/31] Qt: Fix use-after-free in shader settings --- src/platform/qt/SettingsView.cpp | 4 ++-- src/platform/qt/SettingsView.h | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 195fe0441..967cf1a4d 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -437,9 +437,9 @@ void SettingsView::setShaderSelector(ShaderSelector* shaderSelector) { QObject::disconnect(m_shader, nullptr, this, nullptr); } m_shader = shaderSelector; - QObject::connect(this, &SettingsView::saveSettingsRequested, m_shader, &ShaderSelector::saveSettings); - QObject::connect(m_ui.buttonBox, &QDialogButtonBox::rejected, m_shader, &ShaderSelector::revert); if (shaderSelector) { + QObject::connect(this, &SettingsView::saveSettingsRequested, m_shader, &ShaderSelector::saveSettings); + QObject::connect(m_ui.buttonBox, &QDialogButtonBox::rejected, m_shader, &ShaderSelector::revert); addPage(tr("Shaders"), m_shader, Page::SHADERS); } else { addPage(tr("Shaders"), m_dummyShader, Page::SHADERS); diff --git a/src/platform/qt/SettingsView.h b/src/platform/qt/SettingsView.h index 1e45ec87a..710456958 100644 --- a/src/platform/qt/SettingsView.h +++ b/src/platform/qt/SettingsView.h @@ -7,10 +7,12 @@ #include #include +#include #include #include "ColorPicker.h" #include "LogConfigModel.h" +#include "ShaderSelector.h" #include @@ -25,7 +27,6 @@ namespace QGBA { class ConfigController; class InputController; class ShortcutController; -class ShaderSelector; class SettingsView : public QDialog { Q_OBJECT @@ -80,7 +81,7 @@ private: ConfigController* m_controller; InputController* m_input; - ShaderSelector* m_shader = nullptr; + QPointer m_shader; QLabel* m_dummyShader; LogConfigModel m_logModel; QTimer m_checkTimer; From 9c4c541c91ceddfcb5db92398f38045f615085bb Mon Sep 17 00:00:00 2001 From: reimu105 Date: Sat, 11 Jan 2025 12:02:09 +0000 Subject: [PATCH 28/31] Qt: Update translation (Chinese (Traditional Han script)) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/zh_Hant/ --- src/platform/qt/ts/mgba-zh_Hant.ts | 1000 ++++++++++++++-------------- 1 file changed, 501 insertions(+), 499 deletions(-) diff --git a/src/platform/qt/ts/mgba-zh_Hant.ts b/src/platform/qt/ts/mgba-zh_Hant.ts index e764abb92..8c22f649c 100644 --- a/src/platform/qt/ts/mgba-zh_Hant.ts +++ b/src/platform/qt/ts/mgba-zh_Hant.ts @@ -34,29 +34,29 @@ <a href="http://mgba.io/">Website</a> • <a href="https://forums.mgba.io/">Forums / Support</a> • <a href="https://patreon.com/mgba">Donate</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">Source</a> - <a href="http://mgba.io/">網站</a> • <a href="https://forums.mgba.io/">論壇、取得協助</a> • <a href="https://patreon.com/mgba">贊助</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">原始碼</a> + <a href="http://mgba.io/">網站</a> • <a href="https://forums.mgba.io/">論壇、取得協助</a> • <a href="https://patreon.com/mgba">贊助</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">原始碼</a> Branch: <tt>{gitBranch}</tt><br/>Revision: <tt>{gitCommit}</tt> - 分支: <tt>{gitBranch}</tt><br/>修訂版: <tt>{gitCommit}</tt> + 分支: <tt>{gitBranch}</tt><br/>修訂版: <tt>{gitCommit}</tt> {projectName} would like to thank the following patrons from Patreon: - {projectName} 感謝以下 Patreon 贊助者: + {projectName}感謝以下 Patreon 贊助者: © 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 – {year} Jeffrey Pfau,基於 Mozilla 公共許可證(版本 2.0)授權 + © 2013 – {year} Jeffrey Pfau,基於 Mozilla 公共許可證(版本 2.0)授權 Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的註冊商標。 {projectName} is an open-source Game Boy Advance emulator - {projectName} 是開源的 Game Boy Advance 模擬器 + {projectName} 是開源的 Game Boy Advance 模擬器 @@ -109,7 +109,7 @@ Download size: %3 An update is available - 有可用的更新 + 有可用的更新 @@ -140,12 +140,12 @@ Download size: %3 Open in archive... - 在壓縮文件中打開... + 在壓縮文件中打開... Loading... - 正在載入... + 正在載入... @@ -160,32 +160,32 @@ Download size: %3 Tile # - 圖塊 # + 圖塊 # Palette # - 調色盤 # + 調色盤 # Address - 位址 + 位址 Red - + Green - + Blue - + @@ -227,17 +227,17 @@ Download size: %3 BattleChip Gate - 戰鬥晶片閘 + BattleChip Gate Chip name - 晶片名稱 + 晶片名稱 Insert - 插入 + 插入 @@ -252,37 +252,37 @@ Download size: %3 Add - 加入 + 加入 Remove - 移除 + 移除 Gate type - 閘門類別 + Gate 類型 Inserted - 已插入 + 已插入 Chip ID - 晶片ID + 晶片ID Update Chip data - 更新晶片資料 + 更新晶片資料 Show advanced - 顯示進階選項 + 顯示進階選項 @@ -346,12 +346,12 @@ Download size: %3 Cheats - 金手指 + 金手指 Add New Code - 新增金手指 + 新增金手指 @@ -366,22 +366,22 @@ Download size: %3 Remove - 移除 + 移除 Enter codes here... - 在此輸入代碼... + 在此輸入代碼... Add Lines - 新增一行 + 新增一行 Code type - 代碼類型 + 作弊碼類型 @@ -456,17 +456,17 @@ Download size: %3 Debugger - 除錯器 + 除錯器 Enter command (try `help` for more info) - 輸入指令 (更多資訊請見「幫助」) + 輸入指令(嘗試“help”以取得更多資訊) Break - 中斷 + 中斷 @@ -490,37 +490,37 @@ Download size: %3 Connect to Dolphin - 連接 Dolphin + 連接 Dolphin Local computer - 區域電腦 + 區域電腦 IP address - IP位址 + IP位址 Connect - 連接 + 連接 Disconnect - 中斷連接 + 中斷連接 Close - 關閉 + 關閉 Reset on connect - 連接後重新啟動 + 連接後重新啟動 @@ -569,7 +569,7 @@ Download size: %3 Background - 背景 + 背景 @@ -599,7 +599,7 @@ Download size: %3 Browse - 瀏覽 + 瀏覽 @@ -782,37 +782,37 @@ Download size: %3 Inspect frame - 檢查畫格 + 檢查畫格 Magnification - 放大 + 放大 Freeze frame - 暫停畫格 + 暫停畫格 Backdrop color - 背景顏色 + 背景顏色 Disable scanline effects - 停用掃描線特效 + 停用掃描線特效 Export - 匯出 + 匯出 Reset - 重新啟動 + 重新啟動 @@ -929,12 +929,12 @@ Download size: %3 Record GIF/WebP/APNG - 錄製 GIF/WebP/APNG + 錄製 GIF/WebP/APNG Loop - 循環 + 循環 @@ -944,32 +944,32 @@ Download size: %3 Stop - 停止 + 停止 Select File - 選擇檔案 + 選擇檔案 APNG - APNG + APNG GIF - GIF + GIF WebP - WebP + WebP Frameskip - 跳過畫格 + 跳過畫格 @@ -978,7 +978,7 @@ Download size: %3 Autodetect - 自動偵測 + 自動偵測 @@ -1083,7 +1083,7 @@ Download size: %3 TAMA5 - TAMA5 + TAMA5 @@ -2406,12 +2406,12 @@ Download size: %3 I/O Viewer - I/O 檢視器 + I/O 檢視器 0x0000 - 0x0000 + 0x0000 @@ -2471,7 +2471,7 @@ Download size: %3 Condition - Condition + 狀態 @@ -2938,7 +2938,7 @@ Download size: %3 VRAM bank - VRAM bank + 顯存庫 @@ -3008,7 +3008,7 @@ Download size: %3 WRAM bank - WRAM bank + 記憶體庫 @@ -3025,27 +3025,27 @@ Download size: %3 Name - 名稱 + 名稱 Location - 位置 + 位置 Platform - 平台 + 平台 Size - 大小 + 大小 CRC32 - CRC32 + CRC32 @@ -3079,7 +3079,7 @@ Download size: %3 %1 State - %1 即時存檔 + %1 即時存檔 @@ -3092,57 +3092,57 @@ Download size: %3 No Save - 無存檔 + 無存檔 5 - 5 + 5 6 - 6 + 6 8 - 8 + 8 4 - 4 + 4 1 - 1 + 1 3 - 3 + 3 7 - 7 + 7 9 - 9 + 9 2 - 2 + 2 Cancel - 取消 + 取消 @@ -3242,62 +3242,62 @@ Download size: %3 Logs - 記錄 + 記錄 Enabled Levels - 已啟用的關卡 + 已啟用的關卡 Debug - 除錯 + 除錯 Stub - 測試樁 + 測試樁 Info - 資訊 + 資訊 Warning - 警告 + 警告 Error - 錯誤 + 錯誤 Fatal - 嚴重 + 致命錯誤 Game Error - 遊戲錯誤 + 遊戲錯誤 Advanced settings - 進階設定 + 進階設定 Clear - 清除 + 清除 Max Lines - 最大行數 + 最大行數 @@ -3385,22 +3385,22 @@ Download size: %3 Maps - 映射 + 貼圖 Magnification - 放大 + 放大 Export - 匯出 + 匯出 Copy - 複製 + 複製 @@ -3409,7 +3409,7 @@ Download size: %3 Failed to open memory log file - 打開記憶體日誌檔案失敗 + 打開記憶體日誌檔案失敗 @@ -3427,7 +3427,7 @@ Download size: %3 Browse - 瀏覽 + 瀏覽 @@ -3457,7 +3457,7 @@ Download size: %3 Stop - 停止 + 停止 @@ -3486,22 +3486,22 @@ Download size: %3 Save Memory Range - 記憶體儲存範圍 + 記憶體儲存範圍 Start Address: - 起始位址: + 起始位址: Byte Count: - 位元組數: + 位元組數: Dump across banks - 跨記憶庫傾印 + 跨記憶庫傾印 @@ -3592,149 +3592,149 @@ Download size: %3 Memory Search - 搜尋記憶體 + 搜尋記憶體 Address - 位址 + 位址 Current Value - 目前的值 + 目前的值 Type - 型別 + 型別 Value - + Numeric - 數字 + 數字 Text - 文字 + 文字 Width - 寬度 + 寬度 Guess - 預測 + 預測 1 Byte (8-bit) - 1 位元組 (8 位元) + 1 位元組 (8 位元) 2 Bytes (16-bit) - 2 位元組 (16 位元) + 2 位元組 (16 位元) 4 Bytes (32-bit) - 4 位元組 (32 位元) + 4 位元組 (32 位元) Number type - 數字型別 + 數字型別 Decimal - 十進位 + 十進位 Hexadecimal - 十六進位 + 十六進位 Search type - 搜尋型別 + 搜尋型別 Equal to value - 等於值 + 等於值 Greater than value - 大於值 + 大於值 Less than value - 小於值 + 小於值 Unknown/changed - 未知/已變更 + 未知/已變更 Changed by value - 數值變更 + 數值變更 Unchanged - 未變更 + 未變更 Increased - 增加 + 增加 Decreased - 減少 + 減少 Search ROM - 搜尋 ROM + 搜尋 ROM New Search - 新的搜尋 + 新的搜尋 Search Within - 在...裡搜尋 + 在範圍內搜尋 Open in Memory Viewer - 在記憶體檢視器中打開 + 在記憶體檢視器中打開 Refresh - 重新整理 + 重新整理 @@ -3742,72 +3742,72 @@ Download size: %3 Memory - 記憶體 + 記憶體 Inspect Address: - 檢查位址: + 檢查位址: Set Alignment: - 資料對齊設定: + 資料對齊設定: &1 Byte - 1 位元組 (&1) + 1 位元組 (&1) &2 Bytes - 2 位元組 (&2) + 2 位元組 (&2) &4 Bytes - 4 位元組 (&4) + 4 位元組 (&4) Unsigned Integer: - 無符號整數: + 無符號整數: Signed Integer: - 有符號整數: + 有符號整數: String: - 字串: + 字串: Load TBL - 讀取 TBL + 讀取 TBL Copy Selection - 複製所選 + 複製所選 Paste - 貼上 + 貼上 Save Selection - 儲存所選 + 儲存所選 Save Range - 儲存範圍 + 儲存範圍 @@ -3843,12 +3843,12 @@ Download size: %3 Trying to get player ID for a multiplayer player that's not attached - + 嘗試取得多人線上未連線上的玩家ID Trying to get save ID for a multiplayer player that's not attached - + 嘗試取得未連線的多人玩家的存檔 ID @@ -3862,57 +3862,57 @@ Download size: %3 Sprites - 角色圖 + 角色圖 Address - 位址 + 位址 Copy - 複製 + 複製 Magnification - 放大 + 縮放率 Geometry - 幾何 + 幾何圖 Position - 位置 + 位置 Dimensions - 維度 + 維度 Matrix - 矩陣 + 矩陣 Export - 匯出 + 匯出 Attributes - 屬性 + 屬性 Transform - 變換 + 變換 @@ -3923,61 +3923,61 @@ Download size: %3 Palette - 調色盤 + 調色盤 Double Size - 兩倍大小 + 兩倍大小 Flipped - 已翻轉 + 已翻轉 H Short for horizontal - H + H Return, Ctrl+R - 返回,Ctrl+R + 返回,Ctrl+R V Short for vertical - V + V Mode - 模式 + 模式 Mosaic - 馬賽克 + 馬賽克 Enabled - 已啟用 + 已啟用 Priority - 優先度 + 優先度 Tile - 圖塊 + 圖塊 @@ -4049,12 +4049,12 @@ Download size: %3 Game Overrides - 遊戲替代 + 遊戲替代 Game Boy Advance - Game Boy Advance + Game Boy Advance @@ -4062,122 +4062,122 @@ Download size: %3 Autodetect - 自動偵測 + 自動偵測 Realtime clock - 實時計時器 + 實時時鐘 Gyroscope - 陀螺儀 + 陀螺儀 Tilt - 傾斜 + 傾斜 Light sensor - 光感測器 + 光感測器 Rumble - 震動 + 震動 Save type - 存檔類型 + 存檔類型 None - + SRAM - SRAM + SRAM Flash 512kb - Flash 512kb + Flash 512kb Flash 1Mb - Flash 1Mb + Flash 1Mb EEPROM 8kB - EEPROM 8kB + EEPROM 8kB EEPROM 512 bytes - EEPROM 512 bytes + EEPROM 512 位元組 SRAM 64kB (bootlegs only) - SRAM 64kB (僅用於盜版卡帶) + SRAM 64kB (僅用於盜版卡帶) Idle loop - 閒置迴圈 + 閒置迴圈 Game Boy Player features - Game Boy Player 特性 + Game Boy Player 特性 VBA bug compatibility mode - VBA 錯誤相容性模式 + VBA 錯誤相容性模式 Game Boy - Game Boy + Game Boy Game Boy model - Game Boy 型號 + Game Boy 型號 Memory bank controller - 記憶庫控制器 + 記憶庫控制器 Background Colors - 背景顏色 + 背景顏色 Sprite Colors 1 - 角色圖顏色 1 + 角色圖顏色 1 Sprite Colors 2 - 角色圖顏色 2 + 角色圖顏色 2 Palette preset - 預設調色盤 + 預設調色盤 @@ -4208,7 +4208,7 @@ Download size: %3 Windows PAL (*.pal);;Adobe Color Table (*.act) - Windows PAL (*.pal);;Adobe Color Table (*.act) + Windows 調色盤 (*.pal);;Adobe 色表 (*.act) @@ -4218,62 +4218,62 @@ Download size: %3 Palette - 調色盤 + 調色盤 Background - 背景 + 背景 Objects - 物件 + 物件 Selection - 選取 + 選取 Red - + Green - + Blue - + 16-bit value - 16 位元數值 + 16 位元數值 Hex code - 十六進位碼 + 十六進位碼 Palette index - 調色盤索引值 + 調色盤索引值 Export BG - 匯出背景 + 匯出背景 Export OBJ - 匯出 OBJ + 匯出 OBJ @@ -4281,27 +4281,27 @@ Download size: %3 Adjust placement - 調整位置 + 調整位置 All - 全部 + 全部 Offset - 偏移量 + 偏移量 X - X + X Y - Y + Y @@ -4309,37 +4309,37 @@ Download size: %3 Game Boy Printer - Game Boy Printer + Game Boy 印表機 Hurry up! - 快一點! + 快一點! Tear off - 撕裂 + 撕裂 Magnification - 放大 + 縮放率 Copy - 複製 + 複製 Save Printout - + 儲存列印輸出 Portable Network Graphics (*.png) - 可攜式網路圖形 (*.png) + 可攜式網路圖形 (*.png) @@ -4366,47 +4366,47 @@ Download size: %3 ROM Info - ROM 資訊 + ROM 資訊 File information - + 文件訊息 Game name: - 遊戲名稱: + 遊戲名稱: File size: - 檔案大小: + 檔案大小: CRC32: - CRC32: + CRC32: MD5 - + MD5 Save file: - + 儲存文件: ROM header - + ROM header Internal name: - 內部名稱: + 內部名稱: @@ -4416,12 +4416,12 @@ Download size: %3 Maker Code: - + 創建者程式碼: Revision: - + 修訂: @@ -4439,37 +4439,37 @@ Download size: %3 Generate Bug Report - 產生錯誤報告 + 產生錯誤報告 <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>若要提出錯誤報告,請先產生一份報告檔,再將報告檔附加到要提出的錯誤報告中。建議您附上存檔,因為存檔通常對除錯很有幫助。錯誤報告會收集以下資料:正在執行的 {projectName} 版本、設定、電腦資訊、目前開啟的遊戲 (若有的話)。在資料收集完成後,您可以檢查所有收集的資料,並儲存成 zip 壓縮檔。錯誤報告會嘗試自動塗銷所有個人資訊,例如路徑包含的使用者名稱。以防萬一您還是可以在這之後自行編輯。生成並儲存報告之後,請點擊下方按鈕,或前往 <a href="https://mgba.io/i/"><span style=" text-decoration: underline; color:#2980b9;">mgba.io/i</span></a> 以在 GitHub 上提出報告。請確定附上產生的報告!</p></body></html> + <html><head/><body><p>若要提出錯誤報告,請先產生一份報告檔,再將報告檔附加到要提出的錯誤報告中。建議您附上存檔,因為存檔通常對除錯很有幫助。錯誤報告會收集以下資料:正在執行的 {projectName} 版本、設定、電腦資訊、目前開啟的遊戲 (若有的話)。在資料收集完成後,您可以檢查所有收集的資料,並儲存成 zip 壓縮檔。錯誤報告會嘗試自動塗銷所有個人資訊,例如路徑包含的使用者名稱。以防萬一您還是可以在這之後自行編輯。生成並儲存報告之後,請點擊下方按鈕,或前往 <a href="https://mgba.io/i/"><span style=" text-decoration: underline; color:#2980b9;">mgba.io/i</span></a> 以在 GitHub 上提出報告。請確定附上產生的報告!</p></body></html> Generate report - 產生報告 + 產生報告 Save - 儲存 + 儲存 Open issue list in browser - 在瀏覽器中打開問題清單 + 在瀏覽器中打開問題清單 Include save file - 附加存檔 + 包括保存檔案 Create and include savestate - 建立並加入即時存檔 + 建立並加入即時存檔 @@ -4532,97 +4532,97 @@ Download size: %3 %1 %2 save game - %1 %2 遊戲存檔 + %1 %2 遊戲存檔 little endian - 位元組由小到大 + 小端 big endian - 位元組由大到小 + 大端 SRAM - SRAM + SRAM %1 flash - %1 flash + %1 快閃記憶體 %1 EEPROM - %1 EEPROM + %1 EEPROM + RTC - + + RTC %1 SRAM + RTC - %1 SRAM + RTC + %1 SRAM + RTC %1 SRAM - %1 SRAM + %1 SRAM packed MBC2 - 包裝 MBC2 + 包裝 MBC2 unpacked MBC2 - 未包裝 MBC2 + 未包裝 MBC2 MBC6 flash - MBC6 flash + MBC6 快閃記憶體 MBC6 combined SRAM + flash - MBC6 合併 SRAM + flash + MBC6組合SRAM+快閃記憶體 MBC6 SRAM - MBC6 SRAM + MBC6 SRAM TAMA5 - TAMA5 + TAMA5 %1 (%2) - %1 (%2) + %1 (%2) %1 save state with embedded %2 save game - %1 即時存檔與嵌入的 %2 遊戲存檔 + %1 即時存檔與嵌入的 %2 遊戲存檔 %1 SharkPort %2 save game - %1 SharkPort %2 存檔 + %1 SharkPort %2 存檔 %1 GameShark Advance SP %2 save game - %1 GameShark Advance SP %2 存檔 + %1 GameShark Advance SP %2 存檔 @@ -4632,23 +4632,23 @@ Download size: %3 Convert/Extract Save Game - 轉換/擷取存檔 + 轉換/擷取存檔 Input file - 輸入檔案 + 輸入檔案 Browse - 瀏覽 + 瀏覽 Output file - 輸出檔案 + 輸出檔案 @@ -4656,7 +4656,7 @@ Download size: %3 Untitled buffer - + 無標題緩存 @@ -4664,57 +4664,57 @@ Download size: %3 Scripting - + 腳本 Run - + 運行 File - + 檔案 Load recent script - + 載入最近的腳本 Load script... - + 加載腳本... &Load most recent - + 載入最近的(&L) &Reset - 重新啟動 (&R) + 重新啟動 (&R) 0 - 0 + 0 Select script to load - + 選擇要載入的腳本 Lua scripts (*.lua) - + Lua 腳本 (*.lua) All files (*.*) - + 所有檔案 (*.*) @@ -4722,84 +4722,84 @@ Download size: %3 Sensors - 感測器 + 感測器 Realtime clock - 實時計時器 + 實時計時器 System time - 系統時間 + 系統時間 Fixed time - 固定時間 + 固定時間 Now - 現在 + 現在 Offset time - + 偏移時間 sec - + Start time at - 開始時間於 + 開始時間於 MM/dd/yy hh:mm:ss AP - yy/MM/dd hh:mm:ss AP + yy/MM/dd hh:mm:ss AP Light sensor - 光感測器 + 光感測器 Brightness - 亮度 + 亮度 Tilt sensor - 傾斜感測器 + 傾斜感測器 Set Y - 設定 Y + 設定 Y 軸 Set X - 設定 X + 設定 X 軸 Gyroscope - 陀螺儀 + 陀螺儀 Sensitivity - 靈敏度 + 靈敏度 @@ -4823,150 +4823,150 @@ Download size: %3 Settings - 設定 + 設定 Audio/Video - 音訊/視訊 + 音訊/視訊 Gameplay - + 遊玩設定 Interface - 介面 + 介面 Update - 更新 + 更新 Emulation - 模擬 + 模擬器 Enhancements - 增強 + 增強 BIOS - BIOS + BIOS Paths - 路徑 + 路徑 Logging - 記錄 + 日誌記錄 Game Boy - Game Boy + Game Boy Audio - 音訊 + 音訊 Audio driver: - 音訊驅動: + 音訊驅動: Audio buffer: - 音訊緩衝: + 音訊緩衝: 1536 - 1536 + 1536 512 - 512 + 512 768 - 768 + 768 1024 - 1024 + 1024 2048 - 2048 + 2048 3072 - 3072 + 3072 4096 - 4096 + 4096 samples - 取樣 + 取樣 Sample rate: - 取樣率: + 取樣率: 44100 - 44100 + 44100 22050 - 22050 + 22050 32000 - 32000 + 32000 48000 - 48000 + 48000 Hz - Hz + Hz Volume: - 音量: + 音量: @@ -4974,248 +4974,248 @@ Download size: %3 Mute - 靜音 + 靜音 Fast forward volume: - 快轉音量: + 快轉音量: Audio in multiplayer: - 多人遊戲音訊: + 多人遊戲音訊: All windows - 所有視窗 + 所有視窗 Player 1 window only - 僅玩家 1 視窗 + 僅玩家 1 視窗 Currently active player window - 現在使用中的玩家視窗 + 現在使用中的玩家視窗 Video - 視訊 + 視訊 Display driver: - 顯示驅動: + 顯示驅動: Frameskip: - 跳過畫格: + 跳過畫格: Skip every - 每隔 N 畫格跳過 + 每隔 N 畫格跳過 frames - 畫格 + 畫格 Lock aspect ratio - 鎖定長寬比 + 鎖定長寬比 Force integer scaling - 強制整數倍放大 + 強制整數倍放大 Interframe blending - 畫格間混合 + 畫格間混合 Bilinear filtering - 雙線性過濾 + 雙線性過濾 FPS target: - FPS 目標: + FPS 目標: frames per second - 每秒畫格數 (FPS) + 每秒畫格數 (FPS) Native (59.7275) - 原生 (59.7275) + 原生 (59.7275) Sync: - 同步: + 同步: On loading a game: - + 載入遊戲時: Load last state - + 載入最後的即時存檔 Load cheats - + 加載作弊 Periodically autosave state - + 定期自動保存狀態 Save entered cheats - + 儲存已輸入的作弊碼 Save state extra data: - 儲存即時存檔額外資料: + 儲存即時存檔額外資料: Screenshot - 螢幕截圖 + 螢幕截圖 Save game - 儲存遊戲 + 儲存遊戲 Cheat codes - 金手指代碼 + 金手指代碼 Load state extra data: - 讀取即時存檔額外資料: + 讀取即時存檔額外資料: Enable Discord Rich Presence - 啟用 Discord Rich Presence + 啟用 Discord Rich Presence Language - 語言 + 語言 Library: - 資料庫: + 資料庫: List view - 清單顯示 + 清單顯示 Tree view - 樹狀顯示 + 樹狀顯示 Show when no game open - 無遊戲啟動時顯示 + 無遊戲啟動時顯示 Show filename instead of ROM name in library view - + 在庫視圖中顯示檔案名稱而非 ROM 名稱 Clear cache - 清除快取 + 清除快取 Allow opposing input directions - 允許相反方向輸入 + 允許相反方向輸入 Suspend screensaver - 暫停螢幕保護程式 + 暫停螢幕保護程式 When inactive: - 閒置時: + 閒置時: Pause - 暫停 + 暫停 When minimized: - 最小化時: + 最小化時: Dynamically update window title - 動態更新視窗標題 + 動態更新視窗標題 Show FPS in title bar - 標題顯示 FPS + 標題顯示 FPS Show filename instead of ROM name in title bar - 標題顯示檔案名稱而非 ROM 名稱 + 標題顯示檔案名稱而非 ROM 名稱 Show OSD messages - 顯示 OSD 訊息 + 顯示 OSD 訊息 Show frame count in OSD - + 在 OSD 中顯示幀數 Show emulation info on reset - + 重置時顯示模擬訊息 @@ -5229,133 +5229,133 @@ Download size: %3 Browse - 瀏覽 + 瀏覽 Custom border: - + 自訂邊框: Current channel: - 目前頻道: + 目前頻道: Current version: - 現在版本: + 現在版本: Update channel: - 更新頻道: + 更新頻道: Available version: - 可用版本: + 可用版本: (Unknown) - (未知) + (未知) Last checked: - 上次檢查時間: + 上次檢查時間: Automatically check on start - 啟動時自動檢查 + 啟動時自動檢查 Check now - 現在檢查 + 現在檢查 Fast forward speed: - 快轉速率: + 快轉速率: Unbounded - 無限制 + 無限制 Fast forward (held) speed: - 快轉 (長按) 速率: + 快轉 (長按) 速率: Autofire interval: - 自動連射間隔: + 自動連射間隔: Enable rewind - 啟用倒轉 + 啟用倒轉 Rewind history: - 倒轉歷史: + 倒轉歷史: Rewind speed: - + 倒帶速度: Idle loops: - 閒置迴圈: + 閒置迴圈: Run all - 執行全部 + 執行全部 Remove known - 移除已知 + 移除已知 Detect and remove - 偵測並移除 + 偵測並移除 Preload entire ROM into memory - 預先讀取整個 ROM 至記憶體中 + 預先讀取整個 ROM 至記憶體中 Enable Game Boy Player features by default - 預設啟用 Game Boy Player 功能 + 預設啟用 Game Boy Player 功能 Enable VBA bug compatibility in ROM hacks - ROM 修改啟用 VBA 錯誤相容性 + ROM 修改啟用 VBA 錯誤相容性 Video renderer: - 渲染器: + 渲染器: Software - 軟體 + 軟體 @@ -5366,52 +5366,52 @@ Download size: %3 OpenGL enhancements - OpenGL 增強 + OpenGL 增強 High-resolution scale: - 高畫質比例: + 高畫質比例: (240×160) - (240×160) + (240×160) GB BIOS file: - GB BIOS 檔案: + GB BIOS 檔案: SGB BIOS file: - SGB BIOS 檔案: + SGB BIOS 檔案: GBC BIOS file: - GBC BIOS 檔案: + GBC BIOS 檔案: GBA BIOS file: - GBA BIOS 檔案: + GBA BIOS 檔案: Use BIOS file if found - 若存在,使用 BIOS 檔案 + 若存在,使用 BIOS 檔案 Skip BIOS intro - 跳過 BIOS 開頭畫面 + 跳過 BIOS 開頭畫面 Save games - 遊戲存檔 + 遊戲存檔 @@ -5420,92 +5420,92 @@ Download size: %3 Same directory as the ROM - 與 ROM 同目錄 + 與 ROM 同目錄 Save states - 即時存檔 + 即時存檔 Screenshots - 螢幕截圖 + 螢幕截圖 Patches - 修補檔 + 修補檔 Cheats - 金手指 + 金手指 Log to file - 記錄到檔案 + 記錄到檔案 Log to console - 記錄到控制台 + 記錄到控制台 Select Log File - 選擇記錄檔 + 選擇記錄檔 Models - 模型 + 模型 GB only: - 僅 GB: + 僅 GB: SGB compatible: - SGB 相容: + SGB 相容: GBC only: - 僅 GBC: + 僅 GBC: GBC compatible: - GBC 相容: + GBC 相容: SGB and GBC compatible: - SGB & GBC 相容: + SGB & GBC 相容: Super Game Boy borders - Super Game Boy 邊界 + Super Game Boy 邊界 Game Boy palette - Game Boy 調色盤 + Game Boy 調色盤 Preset: - 預設: + 預設: Default BG colors: - 預設 BG 顏色組: + 預設背景色: @@ -5520,37 +5520,37 @@ Download size: %3 SGB color palette if available - 若可用,使用SGB調色盤 + 若可用,使用SGB調色盤 Default color palette only - 僅使用預設調色盤 + 僅使用預設調色盤 GBC color palette if available - 若可用,使用GBC調色盤 + 若可用,使用GBC調色盤 SGB (preferred) or GBC color palette if available - 若可用,使用 SGB (優先) 或 GBC調色盤 + 若可用,使用 SGB (優先) 或 GBC調色盤 Game Boy Camera - Game Boy Camera + Game Boy Camera Driver: - 驅動: + 驅動: Source: - 來源: + 來源: @@ -5587,7 +5587,9 @@ Download size: %3 Shaders are not supported when the display driver is not OpenGL. If it is set to OpenGL and you still see this, your graphics card or drivers may be too old. - + 當顯示驅動程式不是 OpenGL 時,不支援著色器。 + +如果將其設為 OpenGL 並且您仍然看到此情況,則您的顯示卡或驅動程式可能太舊了。 @@ -5610,12 +5612,12 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Select image - 選擇圖片 + 選擇圖片 Image file (*.png *.jpg *.jpeg) - 圖檔 (*.png *.jpg *.jpeg) + 圖檔 (*.png *.jpg *.jpeg) @@ -5668,17 +5670,17 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may mGBA Shaders - + mGBA 著色器 Error loading shader - + 載入著色器時出錯 The shader "%1" could not be loaded successfully. - + 著色器“%1”無法成功載入。 @@ -5703,37 +5705,37 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Shaders - 著色器 + 著色器 Active Shader: - 使用中的著色器: + 使用中的著色器: Name - 名稱 + 名稱 Author - 作者 + 作者 Description - 描述 + 描述 Unload Shader - 卸除著色器 + 卸除著色器 Load New Shader - 讀取新著色器 + 讀取新著色器 @@ -5759,22 +5761,22 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Edit Shortcuts - 編輯快捷鍵 + 編輯快捷鍵 Keyboard - 鍵盤 + 鍵盤 Gamepad - 遊戲手把 + 遊戲手把 Clear - 清除 + 清除 @@ -5798,72 +5800,72 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Tiles - 圖塊 + 圖塊 Palette - 調色盤 + 調色盤 256 colors - 256 色 + 256 色 Magnification - 放大 + 縮放率 Tiles per row - 每行圖塊數 + 每行圖塊數 Fit to window - 貼合視窗 + 貼合視窗 Displayed tiles - + 已顯示的圖塊 Only BG tiles - + 僅 BG 圖塊 Only OBJ tiles - + 僅 OBJ 圖塊 Both - 兩者 + 兩者 Copy Selected - 複製選取 + 複製選取 Export Selected - 匯出所選 + 匯出所選 Copy All - 複製全部 + 複製全部 Export All - 匯出全部 + 匯出全部 @@ -5886,117 +5888,117 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Record Video - 錄影 + 錄影 Start - + 開始 Stop - 停止 + 停止 Select File - 選擇檔案 + 選擇檔案 Presets - 預設 + 預設 High &Quality - 高畫質 (&Q) + 高畫質 (&Q) &YouTube - YouTube (&Y) + YouTube (&Y) WebM - WebM + WebM MP4 - MP4 + MP4 &Lossless - 無損品質 (&L) + 無損品質 (&L) 4K - 4K + 4K &1080p - 1080p (&1) + 1080p (&1) &720p - 720p (&7) + 720p (&7) &480p - 480p (&4) + 480p (&4) &Native - 原始畫質 (&N) + 原始畫質 (&N) Format - 格式 + 格式 Bitrate (kbps) - 位元率 (kbps) + 位元率 (kbps) ABR - ABR + ABR VBR - VBR + VBR CRF - CRF + CRF Dimensions - 維度 + 維度 Lock aspect ratio - 鎖定長寬比 + 鎖定長寬比 Show advanced - 顯示進階選項 + 顯示進階選項 @@ -6131,12 +6133,12 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Reset needed - + 需要重啟 Some changes will not take effect until the game is reset. - + 某些改動需要重新啟動才會生效。 @@ -6343,7 +6345,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Save games - 遊戲存檔 + 遊戲存檔 @@ -6358,12 +6360,12 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Automatically determine - + 自動判斷 Use player %0 save game - + 使用玩家 %0 存檔 @@ -6448,12 +6450,12 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Increase fast forward speed - + 加快快轉速度 Decrease fast forward speed - + 降低快轉速度 @@ -6503,7 +6505,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Game Boy Printer... - Game Boy Printer... + Game Boy 印表機... @@ -6533,7 +6535,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may &Lock frame size - + 鎖定幀大小(&L) @@ -6638,12 +6640,12 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Scripting... - + 腳本... Create forwarder... - + 建立轉發器... @@ -6663,7 +6665,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Game state views - + 遊戲狀態視圖 @@ -6708,7 +6710,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Log memory &accesses... - + 記錄記憶體存取(&a)... @@ -6826,17 +6828,17 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Super (L) - Super (L) + Super (L) Super (R) - Super (R) + Super (R) Menu - 選單 + 選單 From 2e0f9268922b0e85dcfb8bd306be6f1935cc5c02 Mon Sep 17 00:00:00 2001 From: Felipe Date: Sun, 12 Jan 2025 17:05:17 +0000 Subject: [PATCH 29/31] Qt: Update translation (Portuguese (Brazil)) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/pt_BR/ --- src/platform/qt/ts/mgba-pt_BR.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/ts/mgba-pt_BR.ts b/src/platform/qt/ts/mgba-pt_BR.ts index dbe2b3b46..0d1e2c8ac 100644 --- a/src/platform/qt/ts/mgba-pt_BR.ts +++ b/src/platform/qt/ts/mgba-pt_BR.ts @@ -3409,7 +3409,7 @@ Tamanho do download: %3 Failed to open memory log file - Falhou em abrir o arquivo do registro da memória + Falhou em abrir o arquivo do registro de memória From 0d19cf1d5c7aada2d2507dd090f5a412bfd00492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=AE=A4=E0=AE=AE=E0=AE=BF=E0=AE=B4=E0=AF=8D=E0=AE=A8?= =?UTF-8?q?=E0=AF=87=E0=AE=B0=E0=AE=AE=E0=AF=8D?= Date: Sat, 18 Jan 2025 05:53:39 +0100 Subject: [PATCH 30/31] Qt: Added translation (Tamil) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/ta/ --- src/platform/qt/ts/mgba-ta.ts | 6869 +++++++++++++++++++++++++++++++++ 1 file changed, 6869 insertions(+) create mode 100644 src/platform/qt/ts/mgba-ta.ts diff --git a/src/platform/qt/ts/mgba-ta.ts b/src/platform/qt/ts/mgba-ta.ts new file mode 100644 index 000000000..33d7b64b5 --- /dev/null +++ b/src/platform/qt/ts/mgba-ta.ts @@ -0,0 +1,6869 @@ + + + + + QGBA + + + Game Boy Advance ROMs (%1) + கேம் பாய் அட்வான்ச் ரோம்ச் (%1) + + + + Game Boy ROMs (%1) + கேம் பாய் ரோம்ச் (%1) + + + + All ROMs (%1) + அனைத்து ROM களும் (%1) + + + + %1 Video Logs (*.mvl) + %1 வீடியோ பதிவுகள் (*.mvl) + + + + QGBA::AboutScreen + + + About + பற்றி + + + + <a href="http://mgba.io/">Website</a> • <a href="https://forums.mgba.io/">Forums / Support</a> • <a href="https://patreon.com/mgba">Donate</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">Source</a> + <a href = "http:/pt </a>" <a href = "https.2" >>> <a href = "https://paton.com/peration> • <a href =" httpthub.com /gitbranch} "> மூல /</a> + + + + Branch: <tt>{gitBranch}</tt><br/>Revision: <tt>{gitCommit}</tt> + கிளை: <tt> {gitBranch} </tt> <br/> திருத்தம்: <tt> {gitCommit} </tt> + + + + {projectName} would like to thank the following patrons from Patreon: + {projectName} பேட்ரியோனின் பின்வரும் புரவலர்களுக்கு நன்றி தெரிவிக்க விரும்புகிறது: + + + + © 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 - {year} செஃப்ரி பிஃபா, மொசில்லா பொது உரிமத்தின் கீழ் உரிமம் பெற்றது, பதிப்பு 2.0 + கேம் பாய் அட்வான்ச் என்பது நிண்டெண்டோ கோ, லிமிடெட் நிறுவனத்தின் பதிவு செய்யப்பட்ட வர்த்தக முத்திரை. + + + + {projectName} is an open-source Game Boy Advance emulator + {projectName} என்பது ஒரு திறந்த மூல விளையாட்டு பாய் அட்வான்ச் முன்மாதிரி + + + + QGBA::ApplicationUpdatePrompt + + + An update is available + புதுப்பிப்பு கிடைக்கிறது + + + + An update to %1 is available. + + %1 க்கான புதுப்பிப்பு கிடைக்கிறது. + + + + + +Do you want to download and install it now? You will need to restart the emulator when the download is complete. + +இப்போது அதை பதிவிறக்கம் செய்து நிறுவ விரும்புகிறீர்களா? பதிவிறக்கம் முடிந்ததும் நீங்கள் முன்மாதிரியை மறுதொடக்கம் செய்ய வேண்டும். + + + + +Auto-update is not available on this platform. If you wish to update you will need to do it manually. + +இந்த மேடையில் ஆட்டோ அப்டேட் கிடைக்கவில்லை. நீங்கள் புதுப்பிக்க விரும்பினால் அதை கைமுறையாக செய்ய வேண்டும். + + + + Current version: %1 +New version: %2 +Download size: %3 + தற்போதைய பதிப்பு: %1 + புதிய பதிப்பு: %2 + பதிவிறக்க அளவு: %3 + + + + Downloading update... + புதுப்பிப்பைப் பதிவிறக்குகிறது ... + + + + Downloading failed. Please update manually. + பதிவிறக்கம் தோல்வியுற்றது. கைமுறையாக புதுப்பிக்கவும். + + + + Downloading done. Press OK to restart %1 and install the update. + பதிவிறக்கம் முடிந்தது. %1 ஐ மறுதொடக்கம் செய்ய சரி என்பதை அழுத்தி புதுப்பிப்பை நிறுவவும். + + + + QGBA::ApplicationUpdater + + + Stable + நிலையான + + + + Development + வளர்ச்சி + + + + Unknown + தெரியவில்லை + + + + (None) + (எதுவுமில்லை) + + + + QGBA::ArchiveInspector + + + Open in archive... + காப்பகத்தில் திறந்திருக்கும் ... + + + + Loading... + ஏற்றுகிறது ... + + + + QGBA::AssetTile + + + Tile # + ஓடு # + + + + Palette # + தட்டு # + + + + Address + முகவரி + + + + Red + சிவப்பு + + + + Green + பச்சை + + + + Blue + நீலம் + + + + + + 0x%0 (%1) + 0x% 0 (% 1) + + + + QGBA::AudioDevice + + + Can't set format of context-less audio device + சூழல்-குறைவான ஆடியோ சாதனத்தின் வடிவமைப்பை அமைக்க முடியாது + + + + Audio device is missing its core + ஆடியோ சாதனம் அதன் மையத்தைக் காணவில்லை + + + + Writing data to read-only audio device + படிக்க மட்டும் ஆடியோ சாதனத்திற்கு தரவை எழுதுதல் + + + + QGBA::AudioProcessorQt + + + Can't start an audio processor without input + உள்ளீடு இல்லாமல் ஆடியோ செயலியைத் தொடங்க முடியாது + + + + QGBA::AudioProcessorSDL + + + Can't start an audio processor without input + உள்ளீடு இல்லாமல் ஆடியோ செயலியைத் தொடங்க முடியாது + + + + QGBA::BattleChipView + + + BattleChip Gate + போர்ட்லெசிப் கேட் + + + + Chip name + சில்லு பெயர் + + + + Insert + செருகவும் + + + + Save + சேமி + + + + Load + சுமை + + + + Add + கூட்டு + + + + Remove + அகற்று + + + + Gate type + நுழைவாயில் வகை + + + + Inserted + செருகப்பட்டது + + + + Chip ID + சில்லு ஐடி + + + + Update Chip data + சிப் தரவைப் புதுப்பிக்கவும் + + + + Show advanced + மேம்பட்டதைக் காட்டு + + + + BattleChip data missing + BATLECHIP தரவு இல்லை + + + + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? + BATLECHIP தரவு இல்லை. போர்ட்லெச்சிப் கேட்ச் இன்னும் வேலை செய்யும், ஆனால் சில கிராபிக்ச் காணாமல் போகும். தரவை இப்போது பதிவிறக்கம் செய்ய விரும்புகிறீர்களா? + + + + + Select deck file + டெக் கோப்பைத் தேர்ந்தெடுக்கவும் + + + + Incompatible deck + பொருந்தாத டெக் + + + + The selected deck is not compatible with this Chip Gate + தேர்ந்தெடுக்கப்பட்ட டெக் இந்த சிப் வாயிலுடன் பொருந்தாது + + + + QGBA::CheatsModel + + + (untitled) + (பெயரிடப்படாதது) + + + + Failed to open cheats file: %1 + ஏமாற்று கோப்பைத் திறக்கத் தவறிவிட்டது: %1 + + + + QGBA::CheatsView + + + Cheats + ஏமாற்றுக்காரர்கள் + + + + Add New Code + புதிய குறியீட்டைச் சேர்க்கவும் + + + + Remove + அகற்று + + + + Add Lines + கோடுகளைச் சேர்க்கவும் + + + + Code type + குறியீடு வகை + + + + Save + சேமி + + + + Load + சுமை + + + + Enter codes here... + குறியீடுகளை இங்கே உள்ளிடவும் ... + + + + + Autodetect (recommended) + ஆட்டோடெடெக்ட் (பரிந்துரைக்கப்படுகிறது) + + + + + Select cheats file + ஏமாற்று கோப்பைத் தேர்ந்தெடுக்கவும் + + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + சில ஏமாற்றுக்காரர்களால் சேர்க்க முடியவில்லை. தயவுசெய்து அவை சரியாக வடிவமைக்கப்பட்டுள்ளன என்பதை உறுதிப்படுத்தவும் மற்றும்/அல்லது பிற ஏமாற்று வகைகளை முயற்சிக்கவும். + + + + QGBA::CoreController + + + Reset r%1-%2 %3 + R%1-%2%3 ஐ மீட்டமைக்கவும் + + + + + Rewinding not currently enabled + தற்போது இயக்கப்படவில்லை + + + + Reset the game? + விளையாட்டை மீட்டமைக்கவா? + + + + Most games will require a reset to load the new save. Do you want to reset now? + புதிய சேமிப்பை ஏற்ற பெரும்பாலான விளையாட்டுகளுக்கு மீட்டமைப்பு தேவைப்படும். இப்போது மீட்டமைக்க விரும்புகிறீர்களா? + + + + Failed to open save file: %1 + சேமி கோப்பைத் திறக்கத் தவறிவிட்டது: %1 + + + + Failed to open game file: %1 + விளையாட்டு கோப்பைத் திறக்கத் தவறிவிட்டது: %1 + + + + Can't yank pack in unexpected platform! + எதிர்பாராத மேடையில் பேக் செய்ய முடியாது! + + + + Failed to open snapshot file for reading: %1 + வாசிப்புக்கு ச்னாப்சாட் கோப்பைத் திறக்கத் தவறிவிட்டது: %1 + + + + Failed to open snapshot file for writing: %1 + எழுதுவதற்கு ச்னாப்சாட் கோப்பைத் திறக்கத் தவறிவிட்டது: %1 + + + + 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; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). + சேமி கோப்பைத் திறக்கத் தவறிவிட்டது; விளையாட்டு சேமிப்புகளை புதுப்பிக்க முடியாது. கூடுதல் சலுகைகள் இல்லாமல் சேமி அடைவு எழுதக்கூடியது என்பதை உறுதிப்படுத்தவும் (எ.கா. சாளரங்களில் UAC). + + + + QGBA::DebuggerConsole + + + Debugger + பிழைத்திருத்தம் + + + + Enter command (try `help` for more info) + கட்டளையை உள்ளிடவும் (மேலும் தகவலுக்கு `உதவி` முயற்சிக்கவும்) + + + + Break + இடைவேளை + + + + QGBA::DebuggerConsoleController + + + Could not open CLI history for writing + எழுதுவதற்கு சி.எல்.ஐ வரலாற்றைத் திறக்க முடியவில்லை + + + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + ஓபன்சிஎல் 3 சூழலை உருவாக்குவதில் தோல்வி, பழைய பாணியை முயற்சிக்கிறது ... + + + + QGBA::DolphinConnector + + + Connect to Dolphin + டால்பினுடன் இணைக்கவும் + + + + Local computer + உள்ளக கணினி + + + + IP address + ஐபி முகவரி + + + + Connect + இணை + + + + Disconnect + துண்டிக்கவும் + + + + Close + மூடு + + + + Reset on connect + இணைப்பில் மீட்டமைக்கவும் + + + + Couldn't Connect + இணைக்க முடியவில்லை + + + + Could not connect to Dolphin. + டால்பினுடன் இணைக்க முடியவில்லை. + + + + QGBA::ForwarderGenerator + + + 3DS + 3DS + + + + Vita + வீட்டா + + + + QGBA::ForwarderGenerator3DS + + + Icon + படவுரு + + + + Banner + பேனர் + + + + QGBA::ForwarderGeneratorVita + + + Bubble + குமிழி + + + + Background + பின்னணி + + + + Startup + தொடங்கு + + + + QGBA::ForwarderView + + + Create forwarder + முன்னோக்கி உருவாக்கு + + + + Files + கோப்புகள் + + + + ROM file: + ரோம் கோப்பு: + + + + + + Browse + உலாவு + + + + Output filename: + வெளியீட்டு கோப்பு பெயர்: + + + + Forwarder base: + முன்னோக்கி அடிப்படை: + + + + Latest stable version + அண்மைக் கால நிலையான பதிப்பு + + + + Latest development build + அண்மைக் கால மேம்பாட்டு உருவாக்கம் + + + + Specific file + குறிப்பிட்ட கோப்பு + + + + Base file: + தள கோப்பு: + + + + System + மண்டலம் + + + + 3DS + 3DS + + + + Vita + வீட்டா + + + + Presentation + விளக்கக்காட்சி + + + + Title: + தலைப்பு: + + + + Images: + படங்கள்: + + + + Use default image + இயல்புநிலை படத்தைப் பயன்படுத்தவும் + + + + Preferred size: + விருப்பமான அளவு: + + + + Select image file + படக் கோப்பைத் தேர்ந்தெடுக்கவும் + + + + Select ROM file + ரோம் கோப்பைத் தேர்ந்தெடுக்கவும் + + + + Select output filename + வெளியீட்டு கோப்பு பெயரைத் தேர்ந்தெடுக்கவும் + + + + Select base file + அடிப்படை கோப்பைத் தேர்ந்தெடுக்கவும் + + + + Build finished + உருவாக்க முடிந்தது + + + + Forwarder finished building + முன்னோக்கி கட்டிடம் முடிந்தது + + + + Build failed + உருவாக்கம் தோல்வியடைந்தது + + + + Failed to build forwarder + முன்னோக்கி கட்டுவதில் தோல்வி + + + + %1 installable package (*.%2) + %1 நிறுவக்கூடிய தொகுப்பு (*.%2) + + + + Select an image + ஒரு படத்தைத் தேர்ந்தெடுக்கவும் + + + + Image files (*.png *.jpg *.bmp) + படக் கோப்புகள் ( *.png *.jpg *.bmp) + + + + QGBA::FrameView + + + Inspect frame + சட்டத்தை ஆய்வு செய்யுங்கள் + + + + Magnification + உருப்பெருக்கம் + + + + Freeze frame + முடக்கம் சட்டகம் + + + + Backdrop color + பின்னணி நிறம் + + + + Disable scanline effects + ச்கேன்லைன் விளைவுகளை முடக்கு + + + + Export + ஏற்றுமதி + + + + Reset + மீட்டமை + + + + Export frame + ஏற்றுமதி சட்டகம் + + + + Portable Network Graphics (*.png) + போர்ட்டபிள் பிணையம் கிராபிக்ச் (*.png) + + + + None + எதுவுமில்லை + + + + Background + பின்னணி + + + + Window + சாளரம் + + + + Objwin + ஆப்ச்வின் + + + + Sprite + ச்பிரிட் + + + + Backdrop + பின்னணி + + + + Frame + சட்டகம் + + + + %1 %2 + %1 %2 + + + + QGBA::GBAApp + + + Enable Discord Rich Presence + முரண்பாடு பணக்கார இருப்பை இயக்கவும் + + + + QGBA::GBAKeyEditor + + + Clear Button + பொத்தானை அழிக்கவும் + + + + Clear Analog + அனலாக் அழி + + + + Refresh + புதுப்பிப்பு + + + + Set all + அனைத்தையும் அமைக்கவும் + + + + QGBA::GDBWindow + + + Server settings + சேவையக அமைப்புகள் + + + + Local port + உள்ளக துறைமுகம் + + + + Bind address + முகவரியை பிணைக்கவும் + + + + Write watchpoints behavior + கண்காணிப்பு புள்ளிகள் நடத்தை எழுதுங்கள் + + + + Standard GDB + நிலையான சி.டி.பி. + + + + Internal change detection + உள் மாற்றம் கண்டறிதல் + + + + Break on all writes + அனைத்து எழுத்துக்களையும் முறித்துக் கொள்ளுங்கள் + + + + Break + இடைவேளை + + + + Stop + நிறுத்து + + + + Start + தொடங்கு + + + + Crash + செயலிழப்பு + + + + Could not start GDB server + GDB சேவையகத்தைத் தொடங்க முடியவில்லை + + + + QGBA::GIFView + + + Record GIF/WebP/APNG + Gif/webp/apng ஐ பதிவு செய்யுங்கள் + + + + Loop + லூப் + + + + Start + தொடங்கு + + + + Stop + நிறுத்து + + + + Select File + கோப்பைத் தேர்ந்தெடு + + + + APNG + தலைகீழான -பார் + + + + GIF + Gif + + + + WebP + வலை + + + + Frameskip + பிரேம்கிப் + + + + Failed to open output file: %1 + வெளியீட்டு கோப்பைத் திறக்கத் தவறிவிட்டது: %1 + + + + Select output file + வெளியீட்டு கோப்பைத் தேர்ந்தெடுக்கவும் + + + + Graphics Interchange Format (*.gif);;WebP ( *.webp);;Animated Portable Network Graphics (*.png *.apng) + கிராபிக்ச் இன்டர்சேஞ்ச் வடிவம் ( *.GIF) ;; Webp ( *.Webp) ;; அனிமேசன் செய்யப்பட்ட போர்ட்டபிள் பிணையம் கிராபிக்ச் ( *.png *.apng) + + + + QGBA::GameBoy + + + + Autodetect + ஆட்டோடெடெக்ட் + + + + Game Boy (DMG) + கேம் பாய் (டி.எம்.சி) + + + + Game Boy Pocket (MGB) + கேம் பாய் பாக்கெட் (எம்சிபி) + + + + Super Game Boy (SGB) + சூப்பர் கேம் பாய் (எச்சிபி) + + + + Super Game Boy 2 (SGB) + சூப்பர் கேம் பாய் 2 (எச்சிபி) + + + + Game Boy Color (CGB) + கேம் பாய் கலர் (சிசிபி) + + + + Game Boy Advance (AGB) + கேம் பாய் அட்வான்ச் (ஏசிபி) + + + + Super Game Boy Color (SGB + CGB) + சூப்பர் கேம் பாய் கலர் (எச்சிபி + சிசிபி) + + + + ROM Only + ரோம் மட்டும் + + + + MBC1 + MBC1 + + + + MBC2 + MBC2 + + + + MBC3 + முட்டாள் + + + + MBC3 + RTC + MBC3 + RTC + + + + MBC5 + MBC5 + + + + MBC5 + Rumble + MBC5 + ரம்பிள் + + + + MBC6 + MBC6 + + + + MBC7 (Tilt) + MBC7 (சாய்) + + + + MMM01 + MMM01 + + + + HuC-1 + இங்கே -1 + + + + HuC-3 + HECO-3 + + + + Pocket Cam + பாக்கெட் கேம் + + + + TAMA5 + சிதைவு + + + + Wisdom Tree + ஞான மரம் + + + + NT (old 1) + Nt (பழைய 1) + + + + NT (old 2) + Nt (பழைய 2) + + + + NT (new) + Nt (புதியது) + + + + Pokémon Jade/Diamond + போகிமொன் சேட்/டயமண்ட் + + + + BBD + பிபிடி + + + + Hitek + நம்பிக்கைகள் + + + + GGB-81 + சிசிபி -81 + + + + Li Cheng + எல் நான் செங் + + + + Sachen (MMC1) + விசயங்கள் (MMC1) + + + + Sachen (MMC2) + விசயங்கள் (MMC2) + + + + QGBA::IOViewer + + + I/O Viewer + I/O பார்வையாளர் + + + + 0x0000 + 0x0000 + + + + + + B + B + + + + Background mode + பின்னணி முறை + + + + Mode 0: 4 tile layers + பயன்முறை 0: 4 ஓடு அடுக்குகள் + + + + Mode 1: 2 tile layers + 1 rotated/scaled tile layer + பயன்முறை 1: 2 ஓடு அடுக்குகள் + 1 சுழற்றப்பட்ட/அளவிடப்பட்ட ஓடு அடுக்கு + + + + Mode 2: 2 rotated/scaled tile layers + பயன்முறை 2: 2 சுழற்றப்பட்ட/அளவிடப்பட்ட ஓடு அடுக்குகள் + + + + Mode 3: Full 15-bit bitmap + பயன்முறை 3: முழு 15-பிட் பிட்மேப் + + + + Mode 4: Full 8-bit bitmap + பயன்முறை 4: முழு 8-பிட் பிட்மேப் + + + + Mode 5: Small 15-bit bitmap + பயன்முறை 5: சிறிய 15-பிட் பிட்மேப் + + + + CGB Mode + சிசிபி பயன்முறை + + + + Frame select + சட்டத்தைத் தேர்ந்தெடுங்கள் + + + + Unlocked HBlank + திறக்கப்பட்ட HBLANK + + + + Linear OBJ tile mapping + நேரியல் OBJ ஓடு மேப்பிங் + + + + Force blank screen + வெற்று திரையை கட்டாயப்படுத்துங்கள் + + + + Enable background 0 + பின்னணி 0 ஐ இயக்கவும் + + + + Enable background 1 + பின்னணி 1 ஐ இயக்கவும் + + + + Enable background 2 + பின்னணி 2 ஐ இயக்கவும் + + + + Enable background 3 + பின்னணி 3 ஐ இயக்கவும் + + + + Enable OBJ + OBJ ஐ இயக்கு + + + + Enable Window 0 + சாளரம் 0 ஐ இயக்கவும் + + + + Enable Window 1 + சாளர 1 ஐ இயக்கவும் + + + + Enable OBJ Window + OBJ சாளரத்தை இயக்கவும் + + + + Swap green components + பச்சை கூறுகளை மாற்றவும் + + + + Currently in VBlank + தற்போது Vblank இல் + + + + Currently in HBlank + தற்போது HBLANK இல் + + + + Currently in VCounter + தற்போது கவுண்டரில் + + + + Enable VBlank IRQ generation + VBLANK IRQ தலைமுறையை இயக்கவும் + + + + Enable HBlank IRQ generation + HBLANK IRQ தலைமுறையை இயக்கவும் + + + + Enable VCounter IRQ generation + Vcounter IRQ தலைமுறையை இயக்கவும் + + + + VCounter scanline + Vcounter ச்கேன்லைன் + + + + Current scanline + தற்போதைய ச்கேன்லைன் + + + + + + + Priority + முன்னுரிமை + + + + + + + Tile data base (* 16kB) + ஓடு தரவு அடிப்படை (* 16KB) + + + + + + + Enable mosaic + மொசைக் இயக்கு + + + + + + + Enable 256-color + 256 வண்ணத்தை இயக்கவும் + + + + + + + Tile map base (* 2kB) + ஓடு வரைபட அடிப்படை (* 2KB) + + + + + + + Background dimensions + பின்னணி பரிமாணங்கள் + + + + + Overflow wraps + வழிதல் மறைப்புகள் + + + + + + + + + Horizontal offset + கிடைமட்ட ஆஃப்செட் + + + + + + + + + Vertical offset + செங்குத்து ஆஃப்செட் + + + + + + + + + + + + + + + Fractional part + பகுதியளவு பகுதி + + + + + + + + + + + Integer part + முழு எண் பகுதி + + + + + + + Integer part (low) + முழு எண் (குறைந்த) + + + + + + + Integer part (high) + முழு எண் (உயர்) + + + + + End x + முடிவு ஃச் + + + + + Start x + ஃச் தொடங்கு + + + + + End y + இறுதி ஒய் + + + + + Start y + ஒய் ஐத் தொடங்குங்கள் + + + + Window 0 enable BG 0 + சாளரம் 0 பி.சி 0 ஐ இயக்கவும் + + + + Window 0 enable BG 1 + சாளரம் 0 பி.சி 1 ஐ இயக்கவும் + + + + Window 0 enable BG 2 + சாளரம் 0 பி.சி 2 ஐ இயக்கவும் + + + + Window 0 enable BG 3 + சாளரம் 0 பி.சி 3 ஐ இயக்கவும் + + + + Window 0 enable OBJ + சாளரம் 0 OBJ ஐ இயக்கவும் + + + + Window 0 enable blend + சாளரம் 0 கலவையை இயக்கவும் + + + + Window 1 enable BG 0 + சாளரம் 1 பி.சி 0 ஐ இயக்கவும் + + + + Window 1 enable BG 1 + சாளரம் 1 பி.சி 1 ஐ இயக்கவும் + + + + Window 1 enable BG 2 + சாளரம் 1 பி.சி 2 ஐ இயக்கவும் + + + + Window 1 enable BG 3 + சாளரம் 1 பி.சி 3 ஐ இயக்கவும் + + + + Window 1 enable OBJ + சாளரம் 1 OBJ ஐ இயக்கவும் + + + + Window 1 enable blend + சாளரம் 1 கலவையை இயக்கவும் + + + + Outside window enable BG 0 + வெளியே சாளரம் BG 0 ஐ இயக்குகிறது + + + + Outside window enable BG 1 + வெளியே சாளரம் பி.சி 1 ஐ இயக்குகிறது + + + + Outside window enable BG 2 + வெளியே சாளரம் பி.சி 2 ஐ இயக்குகிறது + + + + Outside window enable BG 3 + வெளியே சாளரம் பி.சி 3 ஐ இயக்குகிறது + + + + Outside window enable OBJ + வெளியே சாளரம் OBJ ஐ இயக்குகிறது + + + + Outside window enable blend + வெளியே சாளரம் கலவையை இயக்கவும் + + + + OBJ window enable BG 0 + OBJ சாளரம் BG 0 ஐ இயக்குகிறது + + + + OBJ window enable BG 1 + OBJ சாளரம் BG 1 ஐ இயக்குகிறது + + + + OBJ window enable BG 2 + OBJ சாளரம் BG 2 ஐ இயக்குகிறது + + + + OBJ window enable BG 3 + OBJ சாளரம் BG 3 ஐ இயக்குகிறது + + + + OBJ window enable OBJ + OBJ சாளரம் OBJ ஐ இயக்கவும் + + + + OBJ window enable blend + OBJ சாளரம் கலவையை இயக்குகிறது + + + + Background mosaic size vertical + பின்னணி மொசைக் அளவு செங்குத்து + + + + Background mosaic size horizontal + பின்னணி மொசைக் அளவு கிடைமட்டமாக + + + + Object mosaic size vertical + பொருள் மொசைக் அளவு செங்குத்து + + + + Object mosaic size horizontal + பொருள் மொசைக் அளவு கிடைமட்டமானது + + + + BG 0 target 1 + பிசி 0 இலக்கு 1 + + + + BG 1 target 1 + பி.சி 1 இலக்கு 1 + + + + BG 2 target 1 + பி.சி 2 இலக்கு 1 + + + + BG 3 target 1 + பி.சி 3 இலக்கு 1 + + + + OBJ target 1 + OBJ இலக்கு 1 + + + + Backdrop target 1 + பின்னணி இலக்கு 1 + + + + Blend mode + கலப்பு பயன்முறை + + + + Disabled + முடக்கப்பட்டது + + + + Additive blending + சேர்க்கை கலத்தல் + + + + Brighten + பிரகாசமாக்குங்கள் + + + + Darken + தட்டவும் + + + + BG 0 target 2 + பி.சி 0 இலக்கு 2 + + + + BG 1 target 2 + பி.சி 1 இலக்கு 2 + + + + BG 2 target 2 + பி.சி 2 இலக்கு 2 + + + + BG 3 target 2 + பி.சி 3 இலக்கு 2 + + + + OBJ target 2 + OBJ இலக்கு 2 + + + + Backdrop target 2 + பின்னணி இலக்கு 2 + + + + Blend A (target 1) + A (இலக்கு 1) கலக்கவும் + + + + Blend B (target 2) + கலப்பு பி (இலக்கு 2) + + + + Blend Y + கலப்பு ஒய் + + + + + Sweep shifts + ச்வீப் மாற்றங்கள் + + + + + Sweep subtract + ச்வீப் கழித்தல் + + + + + Sweep time (in 1/128s) + ச்வீப் நேரம் (1/128 களில்) + + + + + + + + + + + Sound length + ஒலி நீளம் + + + + + + + Duty cycle + கடமை சுழற்சி + + + + + + + + + Envelope step time + உறை படி நேரம் + + + + + + + + + Envelope increase + உறை அதிகரிப்பு + + + + + + + + + Initial volume + தொடக்க தொகுதி + + + + + + Sound frequency + ஒலி அதிர்வெண் + + + + + + + + + + + Timed + நேரம் + + + + + + + + + + + Reset + மீட்டமை + + + + Double-size wave table + இரட்டை அளவு அலை அட்டவணை + + + + Active wave table + செயலில் அலை அட்டவணை + + + + + Enable channel 3 + சேனல் 3 ஐ இயக்கவும் + + + + + Volume + தொகுதி + + + + + 0% + 0% + + + + + + 100% + 100% + + + + + + 50% + 50% + + + + + + 25% + 25% + + + + + + + 75% + 75% + + + + + Clock divider + கடிகார வகுப்பி + + + + + Register stages + பதிவு நிலைகள் + + + + + 15 + 15 + + + + + 7 + 7 + + + + + Shifter frequency + சிஃப்ட்டர் அதிர்வெண் + + + + PSG volume right + PSG தொகுதி சரி + + + + PSG volume left + PSG தொகுதி இடது + + + + + Enable channel 1 right + சேனல் 1 வலதுபுறம் இயக்கவும் + + + + + Enable channel 2 right + சேனல் 2 ஐ வலதுபுறமாக இயக்கவும் + + + + + Enable channel 3 right + சேனல் 3 வலதுபுறமாக இயக்கவும் + + + + + Enable channel 4 right + சேனல் 4 ஐ இயக்கவும் + + + + + Enable channel 1 left + சேனல் 1 இடது + + + + + Enable channel 2 left + சேனல் 2 இடது + + + + + Enable channel 3 left + சேனல் 3 இடது + + + + + Enable channel 4 left + சேனல் 4 இடது + + + + PSG master volume + PSG முதன்மை தொகுதி + + + + Loud channel A + உரத்த சேனல் அ + + + + Loud channel B + உரத்த சேனல் ஆ + + + + Enable channel A right + சேனலை ஒரு உரிமையை இயக்கவும் + + + + Enable channel A left + சேனலை ஒரு இடதுபுறமாக இயக்கவும் + + + + Channel A timer + சேனல் ஒரு நேரங்குறிகருவி + + + + + 0 + 0 + + + + + + + + + + + + 1 + 1 + + + + Channel A reset + சேனல் ஒரு மீட்டமைப்பு + + + + Enable channel B right + சேனல் பி வலதுபுறமாக இயக்கவும் + + + + Enable channel B left + சேனல் பி இடது + + + + Channel B timer + சேனல் பி நேரங்குறிகருவி + + + + Channel B reset + சேனல் பி மீட்டமை + + + + + Active channel 1 + செயலில் சேனல் 1 + + + + + Active channel 2 + செயலில் சேனல் 2 + + + + + Active channel 3 + செயலில் சேனல் 3 + + + + + Active channel 4 + செயலில் சேனல் 4 + + + + + Enable audio + ஆடியோவை இயக்கவும் + + + + Bias + சார்பு + + + + Resolution + பகுத்தல் + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sample + மாதிரி + + + + + + + + + + + Address (low) + முகவரி (குறைந்த) + + + + + + + + + + + Address (high) + முகவரி (உயர்) + + + + + + Sound frequency (low) + ஒலி அதிர்வெண் (குறைந்த) + + + + + + Sound frequency (high) + ஒலி அதிர்வெண் (உயர்) + + + + Source (high) + மூல (உயர்) + + + + Source (low) + மூல (குறைந்த) + + + + Destination (high) + இலக்கு (உயர்) + + + + Destination (low) + இலக்கு (குறைந்த) + + + + + Green (low) + பச்சை (குறைந்த) + + + + + Green (high) + பச்சை (உயர்) + + + + + + + Word count + சொல் எண்ணிக்கை + + + + + + + Destination offset + இலக்கு ஆஃப்செட் + + + + + + + + + + + Increment + அதிகரிப்பு + + + + + + + + + + + Decrement + குறைவு + + + + + + + + + + + Fixed + சரி + + + + + + + Increment and reload + அதிகரிப்பு மற்றும் மீண்டும் ஏற்றவும் + + + + + + + Source offset + மூல ஆஃப்செட் + + + + + + + Repeat + மீண்டும் + + + + + + + 32-bit + 32-பிட் + + + + + + + Start timing + நேரத்தைத் தொடங்கவும் + + + + + + + + Immediate + உடனடியாக + + + + + + + + + + + VBlank + Vblank + + + + + + + + + + HBlank + Hblank + + + + + + + + + + + + IRQ + Irq + + + + + + + + + + + + + + Enable + இயக்கு + + + + + + Audio FIFO + ஃபிஃபோ ஆடியோ + + + + Video Capture + வீடியோ பிடிப்பு + + + + DRQ + Drq + + + + + + + + + + + Value + மதிப்பு + + + + + + + Scale + அளவு + + + + + + + + 1/64 + 1/64 + + + + + + + + 1/256 + 1/256 + + + + + + + + 1/1024 + 1/1024 + + + + + + Cascade + ஓடையிணைப்பு + + + + + A + A + + + + + Select + தேர்ந்தெடு + + + + + Start + தொடங்கு + + + + + Right + வலது + + + + + Left + இடது + + + + + Up + மேலே + + + + + Down + கீழே + + + + + R + R + + + + + L + எல் + + + + Condition + நிபந்தனை + + + + SC + எச்சி + + + + SD + எச்.டி. + + + + SI + மற்றும் + + + + SO + எனவே + + + + + VCounter + கவுண்டர் + + + + + Timer 0 + நேரங்குறிகருவி 0 + + + + + Timer 1 + நேரங்குறிகருவி 1 + + + + + Timer 2 + நேரங்குறிகருவி 2 + + + + + Timer 3 + நேரங்குறிகருவி 3 + + + + + SIO + சியோ + + + + + DMA 0 + டி.எம்.ஏ 0 + + + + + DMA 1 + டி.எம்.ஏ 1 + + + + + DMA 2 + டி.எம்.ஏ 2 + + + + + DMA 3 + டி.எம்.ஏ 3 + + + + + Keypad + கீபேட் + + + + + Gamepak + கேம்பக் + + + + SRAM wait + SRAM காத்திருங்கள் + + + + + + + + 4 + 4 + + + + + + + 3 + 3 + + + + + + + + 2 + 2 + + + + + + + + 8 + 8 + + + + Cart 0 non-sequential + CART 0 அல்லாத அடுத்தடுத்த + + + + Cart 0 sequential + வண்டி 0 தொடர்ச்சியான + + + + Cart 1 non-sequential + வண்டி 1 அல்லாத + + + + Cart 1 sequential + வண்டி 1 தொடர்ச்சியான + + + + Cart 2 non-sequential + வண்டி 2 அல்லாத + + + + Cart 2 sequential + வண்டி 2 தொடர்ச்சியானது + + + + PHI terminal + ஃபை முனையம் + + + + + Disable + முடக்கு + + + + 4.19MHz + 4.19 மெகா எர்ட்ச் + + + + 8.38MHz + 8.38 மெகா எர்ட்ச் + + + + 16.78MHz + 16.78 மெகா எர்ட்ச் + + + + Gamepak prefetch + கேம்பாக் முன்னுரிமை + + + + Enable IRQs + IRQ களை இயக்கவும் + + + + Right/A + வலது/அ + + + + Left/B + இடது/பி + + + + Up/Select + மேலே/தேர்ந்தெடுக்கவும் + + + + Down/Start + டவுன்/ச்டார்ட் + + + + Active D-pad + செயலில் டி-பேட் + + + + Active face buttons + செயலில் உள்ள முக பொத்தான்கள் + + + + Internal clock + உள் கடிகாரம் + + + + 32× clocking (CGB only) + 32 × கடிகாரம் (சிசிபி மட்டும்) + + + + Transfer active + செயலில் பரிமாற்றம் + + + + Divider + பிரிப்பான் + + + + 1/16 + 1/16 + + + + + LCD STAT + எல்சிடி ச்டேட் + + + + + Timer + நேரங்குறிகருவி + + + + + Serial + தொடர் + + + + + Joypad + சாய்பாட் + + + + Volume right + தொகுதி சரியானது + + + + Output right + வெளியீடு உரிமை + + + + Volume left + தொகுதி இடது + + + + Output left + வெளியீடு இடது + + + + Background enable/priority + பின்னணி இயக்க/முன்னுரிமை + + + + Enable sprites + உருவங்களை இயக்கவும் + + + + Double-height sprites + இரட்டை உயர உருவங்கள் + + + + Background tile map + பின்னணி ஓடு வரைபடம் + + + + + 0x9800 – 0x9BFF + 0x9800 - 0x9bff + + + + + 0x9C00 – 0x9FFF + 0x9c00 - 0x9fff + + + + Background tile data + பின்னணி ஓடு தரவு + + + + 0x8800 – 0x87FF + 0x8800 - 0x87ff + + + + 0x8000 – 0x8FFF + 0x8000 - 0x8fff + + + + Enable window + சாளரத்தை இயக்கவும் + + + + Window tile map + சாளர ஓடு வரைபடம் + + + + Enable LCD + எல்சிடியை இயக்கு + + + + Mode + பயன்முறை + + + + 0: HBlank + 0: Hblank + + + + 1: VBlank + 1: vblank + + + + 2: OAM scan + 2: ஓம் ச்கேன் + + + + 3: HDraw + 3: hdraw + + + + In LYC + LYC இல் + + + + Enable HBlank (mode 0) IRQ + HBLANK (பயன்முறை 0) IRQ ஐ இயக்கவும் + + + + Enable VBlank (mode 1) IRQ + VBLANK ஐ இயக்கு (பயன்முறை 1) IRQ + + + + Enable OAM (mode 2) IRQ + OAM (பயன்முறை 2) IRQ ஐ இயக்கு + + + + Enable LYC IRQ + LIC IRQ ஐ இயக்கு + + + + Current Y coordinate + தற்போதைய ஒய் ஒருங்கிணைப்பு + + + + Comparison Y coordinate + ஒப்பீடு ஒய் ஒருங்கிணைப்பு + + + + Start upper byte + மேல் பைட்டைத் தொடங்குங்கள் + + + + + + Color 0 shade + நிறம் 0 நிழல் + + + + + + Color 1 shade + நிறம் 1 நிழல் + + + + + + Color 2 shade + நிறம் 2 நிழல் + + + + + + Color 3 shade + வண்ணம் 3 நிழல் + + + + Prepare to switch speed + வேகத்தை மாற்ற தயாராகுங்கள் + + + + Double speed + இரட்டை விரைவு + + + + VRAM bank + VRAM வங்கி + + + + Length + நீளம் + + + + Timing + நேரவிவரம் + + + + Write bit + பிட் எழுதுங்கள் + + + + Read bit + பிட் படித்தார் + + + + + Unknown + தெரியவில்லை + + + + + Current index + தற்போதைய அட்டவணை + + + + + Auto-increment + ஆட்டோ-அதிகரிப்பு + + + + + Red + சிவப்பு + + + + + Blue + நீலம் + + + + Sprite ordering + ச்பிரிட் ஆர்டர் + + + + OAM order + ஓம் ஆர்டர் + + + + x coordinate sorting + ஃச் ஒருங்கிணைப்பு வரிசையாக்கம் + + + + WRAM bank + ராம் வங்கி + + + + QGBA::KeyEditor + + + + --- + --- + + + + QGBA::LibraryTree + + + Name + பெயர் + + + + Location + இடம் + + + + Platform + இயங்குதளம் + + + + Size + அளவு + + + + CRC32 + CRC32 + + + + QGBA::LoadSaveState + + + + %1 State + %1 மாநிலம் + + + + + + + + + + + + No Save + சேமிப்பு இல்லை + + + + 5 + 5 + + + + 6 + 6 + + + + 8 + 8 + + + + 4 + 4 + + + + 1 + 1 + + + + 3 + 3 + + + + 7 + 7 + + + + 9 + 9 + + + + 2 + 2 + + + + Cancel + ரத்துசெய் + + + + Load State + சுமை நிலை + + + + Save State + மாநிலத்தை சேமிக்கவும் + + + + Empty + காலி + + + + Corrupted + சிதைந்த + + + + Slot %1 + ச்லாட் %1 + + + + QGBA::LogConfigModel + + + + Default + இயல்புநிலை + + + + Fatal + அபாயகரமான + + + + Error + பிழை + + + + Warning + எச்சரிக்கை + + + + Info + தகவல் + + + + Debug + பிழைத்திருத்தம் + + + + Stub + முளை + + + + Game Error + விளையாட்டு பிழை + + + + QGBA::LogController + + + [%1] %2: %3 + [ %1] %2: %3 + + + + An error occurred + பிழை ஏற்பட்டது + + + + DEBUG + பிழைத்திருத்தம் + + + + STUB + முளை + + + + INFO + தகவல் + + + + WARN + எச்சரிக்கை + + + + ERROR + பிழை + + + + FATAL + அபாயகரமான + + + + GAME ERROR + விளையாட்டு பிழை + + + + QGBA::LogView + + + Logs + பதிவுகள் + + + + Enabled Levels + இயக்கப்பட்ட நிலைகள் + + + + Debug + பிழைத்திருத்தம் + + + + Stub + முளை + + + + Info + தகவல் + + + + Warning + எச்சரிக்கை + + + + Error + பிழை + + + + Fatal + அபாயகரமான + + + + Game Error + விளையாட்டு பிழை + + + + Advanced settings + மேம்பட்ட அமைப்புகள் + + + + Clear + தெளிவான + + + + Max Lines + அதிகபட்ச கோடுகள் + + + + QGBA::MapView + + + Maps + வரைபடங்கள் + + + + Magnification + உருப்பெருக்கம் + + + + Export + ஏற்றுமதி + + + + Copy + நகலெடு + + + + Priority + முன்னுரிமை + + + + + Map base + வரைபட அடிப்படை + + + + + Tile base + ஓடு அடிப்படை + + + + Size + அளவு + + + + + Offset + ஈடுசெய்யும் + + + + Xform + எக்ச்ஃபார்ம் + + + + Map Addr. + வரைபட முகவரி. + + + + Mirror + கண்ணாடி + + + + None + எதுவுமில்லை + + + + Both + இரண்டும் + + + + Horizontal + கிடைமட்டமாக + + + + Vertical + செங்குத்து + + + + + + N/A + இதற்கில்லை + + + + Export map + ஏற்றுமதி வரைபடம் + + + + Portable Network Graphics (*.png) + போர்ட்டபிள் பிணையம் கிராபிக்ச் (*.png) + + + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + நினைவக பதிவு கோப்பைத் திறக்கத் தவறிவிட்டது + + + + QGBA::MemoryAccessLogView + + + Memory access logging + நினைவக அணுகல் பதிவு + + + + Log file + பதிவு கோப்பு + + + + Browse + உலாவு + + + + Log additional information (uses 3× space) + கூடுதல் தகவல்களை பதிவு செய்யுங்கள் (3 × இடத்தைப் பயன்படுத்துகிறது) + + + + Load existing file if present + இருந்தால் இருக்கும் கோப்பை ஏற்றவும் + + + + Regions + பகுதிகள் + + + + Export ROM snapshot + ஏற்றுமதி ரோம் ச்னாப்சாட் + + + + Start + தொடங்கு + + + + Stop + நிறுத்து + + + + + Select access log file + அணுகல் பதிவு கோப்பைத் தேர்ந்தெடுக்கவும் + + + + Memory access logs (*.mal) + நினைவக அணுகல் பதிவுகள் (*.மால்) + + + + QGBA::MemoryDump + + + Save Memory Range + நினைவக வரம்பைச் சேமிக்கவும் + + + + Start Address: + முகவரியைத் தொடங்கு: + + + + Byte Count: + பைட் எண்ணிக்கை: + + + + Dump across banks + வங்கிகள் முழுவதும் கொட்டவும் + + + + Save memory region + நினைவக பகுதியைச் சேமிக்கவும் + + + + Failed to open output file: %1 + வெளியீட்டு கோப்பைத் திறக்கத் தவறிவிட்டது: %1 + + + + 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 + ஐஎச்ஓ -8859-1 + + + + QGBA::MemorySearch + + + Memory Search + நினைவக தேடல் + + + + Address + முகவரி + + + + Current Value + தற்போதைய மதிப்பு + + + + + Type + வகை + + + + Value + மதிப்பு + + + + Numeric + எண் வரிசை + + + + Text + உரை + + + + Width + அகலம் + + + + + Guess + யூகிக்க + + + + 1 Byte (8-bit) + 1 பைட் (8-பிட்) + + + + 2 Bytes (16-bit) + 2 பைட்டுகள் (16-பிட்) + + + + 4 Bytes (32-bit) + 4 பைட்டுகள் (32-பிட்) + + + + Number type + எண் வகை + + + + Decimal + தசம + + + + Hexadecimal + எக்சாடெசிமல் + + + + Search type + தேடல் வகை + + + + Equal to value + மதிப்புக்கு சமம் + + + + Greater than value + மதிப்பை விட பெரியது + + + + Less than value + மதிப்பை விட குறைவாக + + + + Unknown/changed + தெரியாத/மாற்றப்பட்டது + + + + Changed by value + மதிப்பால் மாற்றப்பட்டது + + + + Unchanged + மாறாமல் + + + + Increased + அதிகரித்தது + + + + Decreased + குறைந்தது + + + + Search ROM + தேடுங்கள் + + + + New Search + புதிய தேடல் + + + + Search Within + உள்ளே தேடுங்கள் + + + + Open in Memory Viewer + நினைவக பார்வையாளரில் திறந்திருக்கும் + + + + Refresh + புதுப்பிப்பு + + + + (%0/%1×) + (%0/%1 ×) + + + + (⅟%0×) + (⅟%0 ×) + + + + (%0×) + (%0 ×) + + + + %1 byte%2 + %1 பைட்%2 + + + + QGBA::MemoryView + + + Memory + நினைவகம் + + + + Inspect Address: + முகவரியை ஆய்வு செய்யுங்கள்: + + + + Set Alignment: + சீரமைப்பை அமைக்கவும்: + + + + &1 Byte + & 1 பைட் + + + + &2 Bytes + & 2 பைட்டுகள் + + + + &4 Bytes + & 4 பைட்டுகள் + + + + Unsigned Integer: + கையொப்பமிடாத முழு எண்: + + + + Signed Integer: + கையொப்பமிடப்பட்ட முழு எண்: + + + + String: + சரம்: + + + + Load TBL + TBL ஐ ஏற்றவும் + + + + Copy Selection + தேர்வு நகல் + + + + Paste + ஒட்டு + + + + Save Selection + தேர்வைச் சேமிக்கவும் + + + + Save Range + வரம்பைச் சேமிக்கவும் + + + + Load + சுமை + + + + QGBA::MessagePainter + + + Frame %1 + பிரேம் %1 + + + + QGBA::MultiplayerController + + + Trying to detach a multiplayer player that's not attached + இணைக்கப்படாத மல்டிபிளேயர் பிளேயரை பிரிக்க முயற்சிக்கிறது + + + + Clearing invalid save ID + தவறான சேமிப்பு ஐடியை அழித்தல் + + + + Clearing invalid preferred ID + தவறான விருப்பமான ஐடியை அழித்தல் + + + + Trying to get player ID for a multiplayer player that's not attached + இணைக்கப்படாத மல்டிபிளேயர் பிளேயருக்கு பிளேயர் ஐடியைப் பெற முயற்சிக்கிறது + + + + Trying to get save ID for a multiplayer player that's not attached + இணைக்கப்படாத மல்டிபிளேயர் பிளேயருக்கான ஐடியை சேமிக்க முயற்சிக்கிறது + + + + QGBA::ObjView + + + Sprites + உருவங்கள் + + + + Address + முகவரி + + + + Copy + நகலெடு + + + + Magnification + உருப்பெருக்கம் + + + + Geometry + வடிவியல் + + + + Position + நிலை + + + + Dimensions + பரிமாணங்கள் + + + + Matrix + அணி + + + + Export + ஏற்றுமதி + + + + Attributes + பண்புக்கூறுகள் + + + + Transform + உருமாற்று, உருமாற்றம் + + + + + Off + அணை + + + + Palette + தட்டு + + + + Double Size + இரட்டை அளவு + + + + + + Return, Ctrl+R + திரும்ப, ctrl+r + + + + Flipped + புரட்டப்பட்டது + + + + H + Short for horizontal + + + + + V + Short for vertical + V + + + + Mode + பயன்முறை + + + + + Normal + சாதாரண + + + + Mosaic + மொசைக் + + + + Enabled + இயக்கப்பட்டது + + + + Priority + முன்னுரிமை + + + + Tile + ஓடு + + + + + 0x%0 + 0x% 0 + + + + + + + + + + + --- + --- + + + + Trans + எதிர்ப்பக்க + + + + OBJWIN + ஆப்ச்வின் + + + + Invalid + செல்லுபடியாகாத + + + + + N/A + இதற்கில்லை + + + + Export sprite + ஏற்றுமதி ச்பிரிட் + + + + Portable Network Graphics (*.png) + போர்ட்டபிள் பிணையம் கிராபிக்ச் (*.png) + + + + QGBA::OverrideView + + + Game Overrides + விளையாட்டு மேலெழுகிறது + + + + Game Boy Advance + கேம் பாய் அட்வான்ச் + + + + + + + Autodetect + ஆட்டோடெடெக்ட் + + + + Realtime clock + நிகழ்நேர கடிகாரம் + + + + Gyroscope + கைரோச்கோப் + + + + Tilt + சாய் + + + + Light sensor + ஒளி சென்சார் + + + + Rumble + ரம்பிள் + + + + Save type + வகை சேமிக்கவும் + + + + None + எதுவுமில்லை + + + + SRAM + ச்ராம் + + + + Flash 512kb + ஃபிளாச் 512KB + + + + Flash 1Mb + ஃபிளாச் 1MB + + + + EEPROM 8kB + EEPROM 8KB + + + + EEPROM 512 bytes + EEPROM 512 பைட்டுகள் + + + + SRAM 64kB (bootlegs only) + SRAM 64KB (பூட்லெக்ச் மட்டும்) + + + + Idle loop + செயலற்ற வளையம் + + + + Game Boy Player features + கேம் பாய் பிளேயர் நற்பொருத்தங்கள் + + + + VBA bug compatibility mode + VBA பிழை பொருந்தக்கூடிய பயன்முறை + + + + Game Boy + கேம் பாய் + + + + Game Boy model + கேம் பாய் மாதிரி + + + + Memory bank controller + நினைவக வங்கி கட்டுப்பாட்டாளர் + + + + Background Colors + பின்னணி வண்ணங்கள் + + + + Sprite Colors 1 + ச்பிரிட் வண்ணங்கள் 1 + + + + Sprite Colors 2 + ச்ப்ரைட் வண்ணங்கள் 2 + + + + Palette preset + தட்டு முன்னமைவு + + + + Official MBCs + அதிகாரப்பூர்வ MBCS + + + + Licensed MBCs + உரிமம் பெற்ற MBC கள் + + + + Unlicensed MBCs + உரிமம் பெறாத MBC கள் + + + + QGBA::PaletteView + + + Palette + தட்டு + + + + Background + பின்னணி + + + + Objects + பொருள்கள் + + + + Selection + தேர்வு + + + + Red + சிவப்பு + + + + Green + பச்சை + + + + Blue + நீலம் + + + + 16-bit value + 16-பிட் மதிப்பு + + + + Hex code + ஃச் குறியீடு + + + + Palette index + தட்டு அட்டவணை + + + + Export BG + ஏற்றுமதி பி.சி. + + + + Export OBJ + ஏற்றுமதி OBJ + + + + #%0 + #%0 + + + + 0x%0 + 0x% 0 + + + + + + + 0x%0 (%1) + 0x% 0 (% 1) + + + + Export palette + ஏற்றுமதி தட்டு + + + + Windows PAL (*.pal);;Adobe Color Table (*.act) + சாளரங்கள் பால் (*.பால்) ;; அடோப் வண்ண அட்டவணை (*.ஆக்ட்) + + + + Failed to open output palette file: %1 + வெளியீட்டு தட்டு கோப்பைத் திறக்கத் தவறிவிட்டது: %1 + + + + QGBA::PlacementControl + + + Adjust placement + வேலைவாய்ப்பை சரிசெய்யவும் + + + + All + அனைத்தும் + + + + Offset + ஈடுசெய்யும் + + + + X + ஃச் + + + + Y + ஒய் + + + + QGBA::PrinterView + + + Game Boy Printer + கேம் பாய் பிரிண்டர் + + + + Hurry up! + சீக்கிரம்! + + + + Tear off + கிழிக்கவும் + + + + Magnification + உருப்பெருக்கம் + + + + Copy + நகலெடு + + + + Save Printout + அச்சுப்பொறியை சேமிக்கவும் + + + + Portable Network Graphics (*.png) + போர்ட்டபிள் பிணையம் கிராபிக்ச் (*.png) + + + + QGBA::ROMInfo + + + + + + + (unknown) + (தெரியவில்லை) + + + + bytes + பைட்டுகள் + + + + (no database present) + (தரவுத்தளம் இல்லை) + + + + ROM Info + ரோம் செய்தி + + + + File information + கோப்பு செய்தி + + + + Game name: + விளையாட்டு பெயர்: + + + + MD5 + MD5 + + + + ROM header + ரோம் தலைப்பு + + + + Internal name: + உள் பெயர்: + + + + Game ID: + விளையாட்டு ஐடி: + + + + Maker Code: + தயாரிப்பாளர் குறியீடு: + + + + Revision: + திருத்தம்: + + + + File size: + கோப்பு அளவு: + + + + CRC32: + CRC32: + + + + Save file: + கோப்பைச் சேமி: + + + + QGBA::ReportView + + + Bug report archive + பிழை அறிக்கை காப்பகம் + + + + ZIP archive (*.zip) + சிப் காப்பகம் (*.zip) + + + + Generate Bug Report + பிழை அறிக்கையை உருவாக்குங்கள் + + + + <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> பிழை அறிக்கையை தாக்கல் செய்ய, முதலில் நீங்கள் தாக்கல் செய்யவிருக்கும் பிழை அறிக்கையுடன் இணைக்க ஒரு அறிக்கை கோப்பை உருவாக்கவும். சேமி கோப்புகளை நீங்கள் சேர்க்க பரிந்துரைக்கப்படுகிறது, ஏனெனில் இவை பெரும்பாலும் பிழைத்திருத்த சிக்கல்களுக்கு உதவுகின்றன. நீங்கள் இயங்கும் {projectName} இன் பதிப்பு, உங்கள் உள்ளமைவு, உங்கள் கணினி மற்றும் நீங்கள் தற்போது திறந்த விளையாட்டு (ஏதேனும் இருந்தால்) பற்றிய சில தகவல்களை இது சேகரிக்கும். இந்த சேகரிப்பு முடிந்ததும் கீழே சேகரிக்கப்பட்ட அனைத்து தகவல்களையும் மதிப்பாய்வு செய்து அதை ஒரு சிப் கோப்பில் சேமிக்கலாம். சேகரிக்கப்பட்ட எந்தவொரு பாதையிலும் இருந்தால், உங்கள் பயனர்பெயர் போன்ற எந்தவொரு தனிப்பட்ட தகவல்களையும் மாற்றியமைக்க சேகரிப்பு தானாகவே முயற்சிக்கும், ஆனால் நீங்கள் அதைத் திருத்தினால். நீங்கள் அதை உருவாக்கி சேமித்த பிறகு, தயவுசெய்து கீழேயுள்ள பொத்தானைக் சொடுக்கு செய்க அல்லது <a href = "https://mgba.io/i/"> <ச்பான் பாணி = "உரை-தேடு: அடிக்கோடிட்டு; வண்ணம்: வண்ணம்:#2980 பி 9;" > mgba.io/i </span> </a> கிட்அப்பில் பிழை அறிக்கையை தாக்கல் செய்ய. நீங்கள் உருவாக்கிய அறிக்கையை இணைப்பதை உறுதிப்படுத்திக் கொள்ளுங்கள்! </P> </body> </html> + + + + Generate report + அறிக்கையை உருவாக்குங்கள் + + + + Save + சேமி + + + + Open issue list in browser + உலாவியில் திறந்த வெளியீட்டு பட்டியல் + + + + Include save file + சேமி கோப்பைச் சேர்க்கவும் + + + + Create and include savestate + Cavestate ஐ உருவாக்கி சேர்க்கவும் + + + + QGBA::SaveConverter + + + Save games and save states (%1) + விளையாட்டுகளைச் சேமித்து மாநிலங்களைச் சேமிக்கவும் (%1) + + + + Select save game or save state + விளையாட்டைச் சேமிக்கவும் அல்லது மாநிலத்தை சேமிக்கவும் என்பதைத் தேர்ந்தெடுக்கவும் + + + + Save games (%1) + விளையாட்டுகளைச் சேமிக்கவும் (%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 + தளங்களுக்கு இடையில் சேமி விளையாட்டுகளை மாற்ற முடியாது + + + + Convert/Extract Save Game + சேமி விளையாட்டை மாற்றவும்/பிரித்தெடுக்கவும் + + + + Input file + உள்ளீட்டு கோப்பு + + + + + Browse + உலாவு + + + + Output file + வெளியீட்டு கோப்பு + + + + %1 %2 save game + %1 %2 விளையாட்டைச் சேமிக்கவும் + + + + little endian + லிட்டில் எண்டியன் + + + + big endian + பெரிய எண்டியன் + + + + SRAM + ச்ராம் + + + + %1 flash + %1 ஃபிளாச் + + + + %1 EEPROM + %1 eeprom + + + + + RTC + + RTC + + + + %1 SRAM + RTC + %1 SRAM + RTC + + + + %1 SRAM + %1 SRAM + + + + packed MBC2 + நிரம்பிய MBC2 + + + + unpacked MBC2 + தொகுக்கப்படாத MBC2 + + + + MBC6 flash + MBC6 ஃபிளாச் + + + + MBC6 combined SRAM + flash + MBC6 ஒருங்கிணைந்த SRAM + Flash + + + + MBC6 SRAM + எளிமையான + + + + TAMA5 + சிதைவு + + + + %1 (%2) + %1 (%2) + + + + %1 save state with embedded %2 save game + %1 உட்பொதிக்கப்பட்ட %2 சேமிப்பு விளையாட்டுடன் மாநிலத்தை சேமிக்கவும் + + + + %1 SharkPort %2 save game + %1 சார்க்போர்ட் %2 விளையாட்டு சேமிப்பு + + + + %1 GameShark Advance SP %2 save game + %1 கேம்சார்க் அட்வான்ச் எச்பி %2 சேமி விளையாட்டு + + + + QGBA::ScriptingTextBuffer + + + Untitled buffer + பெயரிடப்படாத இடையக + + + + QGBA::ScriptingView + + + Scripting + ச்கிரிப்டிங் + + + + Run + ஓடு + + + + File + கோப்பு + + + + Load recent script + அண்மைக் கால ச்கிரிப்டை ஏற்றவும் + + + + Load script... + ச்கிரிப்டை ஏற்றவும் ... + + + + &Load most recent + & மிக அண்மைக் கால சுமை + + + + &Reset + & மீட்டமை + + + + 0 + 0 + + + + Select script to load + ஏற்ற ச்கிரிப்டைத் தேர்ந்தெடுக்கவும் + + + + Lua scripts (*.lua) + ச்கிரிப்ட்களை எடுத்துக் கொள்ளுங்கள் (*.லுவா) + + + + All files (*.*) + எல்லா கோப்புகளும் (*.*) + + + + QGBA::SensorView + + + Sensors + சென்சார்கள் + + + + Realtime clock + நிகழ்நேர கடிகாரம் + + + + Fixed time + நிலையான நேரம் + + + + System time + கணினி நேரம் + + + + Start time at + தொடக்க நேரம் + + + + Now + இப்போது + + + + Offset time + நேரம் ஈடுசெய்யும் நேரம் + + + + sec + நொடி + + + + MM/dd/yy hh:mm:ss AP + MM/DD/YY HH: MM: SS AP + + + + Light sensor + ஒளி சென்சார் + + + + Brightness + ஒளி + + + + Tilt sensor + சாய் சென்சார் + + + + + Set Y + ஒய் ஐ அமைக்கவும் + + + + + Set X + ஃச் அமைக்கவும் + + + + Gyroscope + கைரோச்கோப் + + + + Sensitivity + உணர்திறன் + + + + QGBA::SettingsView + + + + Qt Multimedia + கியுடி மல்டிமீடியா + + + + SDL + எச்.டி.எல் + + + + Software (Qt) + மென்பொருள் (QT) + + + + + OpenGL + Opengl + + + + OpenGL (force version 1.x) + Opengl (படை பதிப்பு 1.x) + + + + None + எதுவுமில்லை + + + + None (Still Image) + எதுவுமில்லை (இன்னும் படம்) + + + + Keyboard + விசைப்பலகை + + + + Controllers + கட்டுப்படுத்திகள் + + + + Shortcuts + குறுக்குவழிகள் + + + + Shaders are not supported when the display driver is not OpenGL. + +If it is set to OpenGL and you still see this, your graphics card or drivers may be too old. + காட்சி இயக்கி ஓபன்சிஎல் இல்லாதபோது சேடர்கள் ஆதரிக்கப்படுவதில்லை. + + இது ஓபன்சிஎல் என அமைக்கப்பட்டால், இதை நீங்கள் இன்னும் பார்த்தால், உங்கள் கிராபிக்ச் அட்டை அல்லது இயக்கிகள் மிகவும் பழையதாக இருக்கலாம். + + + + + + + Shaders + சேடர்ச் + + + + Select BIOS + பயாசைத் தேர்ந்தெடுக்கவும் + + + + Select directory + கோப்பகத்தைத் தேர்ந்தெடு + + + + Select image + படத்தைத் தேர்ந்தெடுக்கவும் + + + + Image file (*.png *.jpg *.jpeg) + பட கோப்பு ( *.png *.jpg *.jpeg) + + + + (%1×%2) + (%1 ×%2) + + + + Never + ஒருபோதும் + + + + Just now + இப்போது + + + + Less than an hour ago + ஒரு மணி நேரத்திற்கு முன்பு + + + + %n hour(s) ago + + %n மணி நேரத்திற்கு முன்பு + %n மணி நேரத்திற்கு முன்பு + + + + + %n day(s) ago + + %n நாள் முன்பு + %n நாட்களுக்கு முன்பு + + + + + Settings + அமைப்புகள் + + + + Audio/Video + ஆடியோ/வீடியோ + + + + Gameplay + விளையாட்டு + + + + Interface + இடைமுகம் + + + + Update + புதுப்பிப்பு + + + + Emulation + போன்மம் + + + + Enhancements + மேம்பாடுகள் + + + + BIOS + பயாச் + + + + Paths + பாதைகள் + + + + Logging + பதிவு + + + + Game Boy + கேம் பாய் + + + + Audio driver: + ஆடியோ டிரைவர்: + + + + Audio buffer: + ஆடியோ இடையக: + + + + + 1536 + 1536 + + + + 512 + 512 + + + + 768 + 768 + + + + 1024 + 1024 + + + + 2048 + 2048 + + + + 3072 + 3072 + + + + 4096 + 4096 + + + + samples + மாதிரிகள் + + + + Sample rate: + மாதிரி வீதம்: + + + + + 44100 + 44100 + + + + 22050 + 22050 + + + + 32000 + 32000 + + + + 48000 + 48000 + + + + Hz + Hz + + + + Volume: + தொகுதி: + + + + + + + Mute + முடக்கு + + + + Fast forward volume: + வேகமாக முன்னோக்கி தொகுதி: + + + + Audio in multiplayer: + மல்டிபிளேயரில் ஆடியோ: + + + + All windows + அனைத்து சாளரங்கள் + + + + Player 1 window only + பிளேயர் 1 சாளரம் மட்டுமே + + + + Currently active player window + தற்போது செயலில் உள்ள பிளேயர் சாளரம் + + + + Display driver: + காட்சி இயக்கி: + + + + Frameskip: + Framessk: + + + + Skip every + ஒவ்வொன்றையும் தவிர்க்கவும் + + + + + frames + சட்டங்கள் + + + + FPS target: + FPS இலக்கு: + + + + frames per second + நொடிக்கு பிரேம்கள் + + + + Sync: + ஒத்திசைவு: + + + + + Video + ஒளிதோற்றம் + + + + + Audio + ஆடியோ + + + + Lock aspect ratio + பூட்டு விகித விகிதம் + + + + Force integer scaling + முழு எண் அளவிடுதல் + + + + Bilinear filtering + பிலினியர் வடிகட்டுதல் + + + + Show filename instead of ROM name in library view + நூலகக் காட்சியில் ரோம் பெயருக்கு பதிலாக கோப்பு பெயரைக் காட்டு + + + + + Pause + இடைநிறுத்தம் + + + + When inactive: + செயலற்ற போது: + + + + On loading a game: + ஒரு விளையாட்டை ஏற்றும்போது: + + + + Load last state + கடைசி நிலையை ஏற்றவும் + + + + Load cheats + ஏமாற்றுகளை ஏற்றவும் + + + + Save entered cheats + நுழைந்த ஏமாற்றுகளை சேமிக்கவும் + + + + When minimized: + குறைக்கும்போது: + + + + Current channel: + தற்போதைய சேனல்: + + + + Current version: + தற்போதைய பதிப்பு: + + + + Update channel: + சேனலைப் புதுப்பிக்கவும்: + + + + Available version: + கிடைக்கும் பதிப்பு: + + + + (Unknown) + (தெரியவில்லை) + + + + Last checked: + கடைசியாக சரிபார்க்கப்பட்டது: + + + + Automatically check on start + தொடக்கத்தில் தானாக சரிபார்க்கவும் + + + + Check now + இப்போது சரிபார்க்க + + + + Default color palette only + இயல்புநிலை வண்ண தட்டு மட்டுமே + + + + SGB color palette if available + கிடைத்தால் எச்சிபி வண்ணத் தட்டு + + + + GBC color palette if available + கிடைத்தால் சிபிசி வண்ணத் தட்டு + + + + SGB (preferred) or GBC color palette if available + கிடைத்தால் எச்சிபி (விருப்பமான) அல்லது சிபிசி வண்ணத் தட்டு + + + + Game Boy Camera + கேம் பாய் கேமரா + + + + Driver: + இயக்கி: + + + + Source: + ஆதாரம்: + + + + Native (59.7275) + சொந்த (59.7275) + + + + Interframe blending + இடைக்கால கலப்பு + + + + Language + மொழி + + + + Library: + நூலகம்: + + + + List view + பட்டியல் பார்வை + + + + Tree view + மரக் காட்சி + + + + Show when no game open + விளையாட்டு திறக்கப்படாதபோது காட்டு + + + + Clear cache + தெளிவான தற்காலிக சேமிப்பு + + + + Allow opposing input directions + எதிரெதிர் உள்ளீட்டு திசைகளை அனுமதிக்கவும் + + + + Suspend screensaver + ச்கிரீன்சேவரை இடைநீக்கம் + + + + Dynamically update window title + சாளர தலைப்பை மாறும் புதுப்பிக்கவும் + + + + Show filename instead of ROM name in title bar + தலைப்பு பட்டியில் ரோம் பெயருக்கு பதிலாக கோப்பு பெயரை காட்டு + + + + Show OSD messages + OSD செய்திகளைக் காட்டு + + + + Enable Discord Rich Presence + முரண்பாடு பணக்கார இருப்பை இயக்கவும் + + + + Periodically autosave state + அவ்வப்போது ஆட்டோசேவ் நிலை + + + + Show FPS in title bar + தலைப்பு பட்டியில் FPS ஐக் காட்டு + + + + Show frame count in OSD + OSD இல் பிரேம் எண்ணிக்கையைக் காட்டு + + + + Show emulation info on reset + மீட்டமைப்பு குறித்த எமுலேசன் தகவலைக் காட்டு + + + + Custom border: + தனிப்பயன் எல்லை: + + + + Fast forward speed: + வேகமாக முன்னோக்கி வேகம்: + + + + + Unbounded + எல்லையற்ற + + + + Fast forward (held) speed: + வேகமாக முன்னோக்கி (வைத்திருக்கும்) வேகம்: + + + + Autofire interval: + தன்னியக்க இடைவெளி: + + + + Enable rewind + ரிவைண்டை இயக்கவும் + + + + Rewind history: + வரலாற்றை முன்னாடி: + + + + Rewind speed: + வேகத்தை முன்னாடி: + + + + Idle loops: + செயலற்ற சுழல்கள்: + + + + Run all + அனைத்தையும் இயக்கவும் + + + + Remove known + அறியப்பட்டதை அகற்று + + + + Detect and remove + கண்டறிந்து அகற்றவும் + + + + Preload entire ROM into memory + முழு ROM ஐ நினைவகமாக ஏற்றவும் + + + + Save state extra data: + மாநில கூடுதல் தரவைச் சேமிக்கவும்: + + + + + Save game + விளையாட்டைச் சேமிக்கவும் + + + + Load state extra data: + மாநில கூடுதல் தரவை ஏற்றவும்: + + + + Models + மாதிரிகள் + + + + GB only: + சிபி மட்டும்: + + + + SGB compatible: + எச்சிபி இணக்கமானது: + + + + GBC only: + சிபிசி மட்டும்: + + + + GBC compatible: + சிபிசி இணக்கமானது: + + + + SGB and GBC compatible: + எச்சிபி மற்றும் சிபிசி இணக்கமானது: + + + + Game Boy palette + கேம் பாய் தட்டு + + + + Preset: + முன்னமைவு: + + + + + Screenshot + திரைக்காட்சி + + + + + Cheat codes + ஏமாற்று குறியீடுகள் + + + + Enable Game Boy Player features by default + இயல்புநிலையாக கேம் பாய் பிளேயர் அம்சங்களை இயக்கவும் + + + + Enable VBA bug compatibility in ROM hacks + ரோம் ஏக்குகளில் VBA பிழை பொருந்தக்கூடிய தன்மையை இயக்கவும் + + + + Video renderer: + வீடியோ ரெண்டரிங்: + + + + Software + மென்பொருள் + + + + OpenGL enhancements + Opengl மேம்பாடுகள் + + + + High-resolution scale: + உயர்-தெளிவுத்திறன் அளவுகோல்: + + + + (240×160) + (240 × 160) + + + + GB BIOS file: + சிபி பயாச் கோப்பு: + + + + + + + + + + + + + Browse + உலாவு + + + + Use BIOS file if found + கிடைத்தால் பயாச் கோப்பைப் பயன்படுத்தவும் + + + + Skip BIOS intro + பயாச் அறிமுகத்தைத் தவிர்க்கவும் + + + + GBA BIOS file: + பயாச் கோப்பைப் பதிவிறக்கவும்: + + + + GBC BIOS file: + சிபிசி பயாச் கோப்பு: + + + + SGB BIOS file: + எச்சிபி பயாச் கோப்பு: + + + + Save games + விளையாட்டுகளைச் சேமிக்கவும் + + + + + + + + Same directory as the ROM + ரோம் போன்ற அதே அடைவு + + + + Save states + மாநிலங்களை சேமிக்கவும் + + + + Screenshots + திரைக்காட்சிகள் + + + + Patches + திட்டுகள் + + + + Cheats + ஏமாற்றுக்காரர்கள் + + + + Log to file + தாக்கல் செய்ய பதிவு + + + + Log to console + கன்சோலுக்கு பதிவு செய்யுங்கள் + + + + Select Log File + பதிவு கோப்பைத் தேர்ந்தெடுக்கவும் + + + + Default BG colors: + இயல்புநிலை பிசி வண்ணங்கள்: + + + + Default sprite colors 1: + இயல்புநிலை ச்ப்ரைட் வண்ணங்கள் 1: + + + + Default sprite colors 2: + இயல்புநிலை ச்ப்ரைட் வண்ணங்கள் 2: + + + + Super Game Boy borders + சூப்பர் கேம் பாய் எல்லைகள் + + + + QGBA::ShaderSelector + + + No shader active + சேடர் செயலில் இல்லை + + + + + Load shader + சேடரை ஏற்றவும் + + + + mGBA Shaders + சேடர்சின் போராட்டம் + + + + Error loading shader + சேடரை ஏற்றுவதில் பிழை + + + + The shader "%1" could not be loaded successfully. + சேடர் "%1" ஐ வெற்றிகரமாக ஏற்ற முடியவில்லை. + + + + No shader loaded + சேடர் ஏற்றப்படவில்லை + + + + by %1 + மூலம் %1 + + + + Preprocessing + முன் செயலாக்கம் + + + + Pass %1 + பாச் %1 + + + + Shaders + சேடர்ச் + + + + Active Shader: + செயலில் சேடர்: + + + + Name + பெயர் + + + + Author + நூலாசிரியர் + + + + Description + விவரம் + + + + Unload Shader + சேடரை இறக்கவும் + + + + Load New Shader + புதிய சேடரை ஏற்றவும் + + + + QGBA::ShortcutModel + + + Action + செயல் + + + + Keyboard + விசைப்பலகை + + + + Gamepad + கேம்பேட் + + + + QGBA::ShortcutView + + + Edit Shortcuts + குறுக்குவழிகளைத் திருத்தவும் + + + + Keyboard + விசைப்பலகை + + + + Gamepad + கேம்பேட் + + + + Clear + தெளிவான + + + + QGBA::TileView + + + Export tiles + ஓடுகளை ஏற்றுமதி செய்யுங்கள் + + + + + Portable Network Graphics (*.png) + போர்ட்டபிள் பிணையம் கிராபிக்ச் (*.png) + + + + Export tile + ஏற்றுமதி ஓடு + + + + Tiles + ஓடுகள் + + + + Export Selected + தேர்ந்தெடுக்கப்பட்ட ஏற்றுமதி + + + + Export All + அனைத்தையும் ஏற்றுமதி செய்யுங்கள் + + + + 256 colors + 256 வண்ணங்கள் + + + + Palette + தட்டு + + + + Magnification + உருப்பெருக்கம் + + + + Tiles per row + ஒரு வரிசையில் ஓடுகள் + + + + Fit to window + சாளரத்திற்கு பொருந்தும் + + + + Displayed tiles + காட்டப்பட்ட ஓடுகள் + + + + Only BG tiles + பி.சி ஓடுகள் மட்டுமே + + + + Only OBJ tiles + OBJ ஓடுகள் மட்டுமே + + + + Both + இரண்டும் + + + + Copy Selected + தேர்ந்தெடுக்கப்பட்ட நகல் + + + + Copy All + அனைத்தையும் நகலெடுக்கவும் + + + + QGBA::VideoView + + + Failed to open output video file: %1 + வெளியீட்டு வீடியோ கோப்பைத் திறக்கத் தவறிவிட்டது: %1 + + + + Native (%0x%1) + சொந்த (%0x%1) + + + + Select output file + வெளியீட்டு கோப்பைத் தேர்ந்தெடுக்கவும் + + + + Record Video + வீடியோ பதிவு + + + + Start + தொடங்கு + + + + Stop + நிறுத்து + + + + Select File + கோப்பைத் தேர்ந்தெடு + + + + Presets + முன்னமைவுகள் + + + + High &Quality + உயர் தகுதி + + + + &YouTube + YouTube + + + + WebM + வெப்எம் + + + + MP4 + எம்.பி.பி. + + + + &Lossless + & இழப்பற்றது + + + + 4K + எச்.சி. + + + + &1080p + & 1080 ப + + + + &720p + & 720 ஆ + + + + &480p + & 480 ப + + + + &Native + & பழமை + + + + Format + வடிவம் + + + + Bitrate (kbps) + பிட்ரேட் (கே.பி.பி.எச்) + + + + ABR + அப் + + + + VBR + விப்ரா + + + + CRF + சி.ஆர்.எஃப் + + + + Dimensions + பரிமாணங்கள் + + + + Lock aspect ratio + பூட்டு விகித விகிதம் + + + + Show advanced + மேம்பட்டதைக் காட்டு + + + + QGBA::Window + + + Archives (%1) + காப்பகங்கள் (%1) + + + + + + Select ROM + ராம் தேர்ந்தெடுக்கவும் + + + + Select folder + கோப்புறையைத் தேர்ந்தெடு + + + + + Select save + சேமி என்பதைத் தேர்ந்தெடுக்கவும் + + + + Select patch + ஒட்டு தேர்ந்தெடுக்கவும் + + + + Patches (*.ips *.ups *.bps) + திட்டுகள் ( *.ips *.ups *.bps) + + + + Select e-Reader dotcode + மின்-ரீடர் டாட் கோட் என்பதைத் தேர்ந்தெடுக்கவும் + + + + e-Reader card (*.raw *.bin *.bmp) + மின்-வாசகர் அட்டை ( *.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 + பின்வரும் பிழையுடன் விளையாட்டு செயலிழந்தது: + + %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 + - %2 இல் %1 + + + + %1 - %2 + %1 - %2 + + + + %1 - %2 - %3 + %1 - %2 - %3 + + + + %1 - %2 (%3 fps) - %4 + %1 - %2 ( %3 FPS) - %4 + + + + &File + கோப்பு (&f) + + + + Load &ROM... + சுமை & ரோம் ... + + + + Load ROM in archive... + காப்பகத்தில் ரோம் ஏற்றவும் ... + + + + Add folder to library... + நூலகத்தில் கோப்புறையைச் சேர்க்கவும் ... + + + + Save games (%1) + விளையாட்டுகளைச் சேமிக்கவும் (%1) + + + + Select save game + சேமி விளையாட்டைத் தேர்ந்தெடுக்கவும் + + + + mGBA save state files (%1) + மாநில கோப்புகளை சேமிக்கவும் (% 1) + + + + + Select save state + சேமி நிலையைத் தேர்ந்தெடுக்கவும் + + + + Select e-Reader card images + ஈ-ரீடர் அட்டை படங்களைத் தேர்ந்தெடுக்கவும் + + + + Image file (*.png *.jpg *.jpeg) + பட கோப்பு ( *.png *.jpg *.jpeg) + + + + Conversion finished + மாற்றம் முடிந்தது + + + + %1 of %2 e-Reader cards converted successfully. + %2 இ-ரீடர் கார்டுகளில் 1 வெற்றிகரமாக மாற்றப்பட்டது. + + + + Load alternate save game... + மாற்று சேமி விளையாட்டை ஏற்றவும் ... + + + + Load temporary save game... + தற்காலிக சேமிப்பு விளையாட்டை ஏற்றவும் ... + + + + Load &patch... + சுமை & இணைப்பு ... + + + + Boot BIOS + துவக்க பயாச் + + + + Replace ROM... + ரோம் மாற்றவும் ... + + + + Scan e-Reader dotcodes... + ஈ-ரீடர் டாட்கோட்களை ச்கேன் செய்யுங்கள் ... + + + + Convert e-Reader card image to raw... + மின்-ரீடர் அட்டை படத்தை மூலமாக மாற்றவும் ... + + + + 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 + மாநிலம் &%1 + + + + Load camera image... + கேமரா படத்தை ஏற்றவும் ... + + + + Convert save game... + சேமி விளையாட்டை மாற்றவும் ... + + + + GameShark saves (*.gsv *.sps *.xps) + கேம்சார்க் சேமிக்கிறது ( *.gsv *.sps *.xps) + + + + Reset needed + மீட்டமை தேவை + + + + Some changes will not take effect until the game is reset. + விளையாட்டு மீட்டமைக்கப்படும் வரை சில மாற்றங்கள் நடைமுறைக்கு வராது. + + + + Save games + விளையாட்டுகளைச் சேமிக்கவும் + + + + Import GameShark Save... + இறக்குமதி கேம்சார்க் சேமி ... + + + + Export GameShark Save... + ஏற்றுமதி கேம்சார்க் சேமி ... + + + + Automatically determine + தானாக தீர்மானிக்கவும் + + + + Use player %0 save game + பிளேயரைப் பயன்படுத்தவும் %0 சேமி விளையாட்டைச் சேமிக்கவும் + + + + New multiplayer window + புதிய மல்டிபிளேயர் சாளரம் + + + + Connect to Dolphin... + டால்பினுடன் இணைக்கவும் ... + + + + Report bug... + பிழையைப் புகாரளிக்கவும் ... + + + + About... + பற்றி ... + + + + E&xit + வெளியேறு (&x) + + + + &Emulation + & போன்மம் + + + + &Reset + & மீட்டமை + + + + Sh&utdown + Sh & Utdown + + + + Yank game pak + யாங்க் கேம் பாக் + + + + &Pause + & இடைநிறுத்தம் + + + + &Next frame + & அடுத்த சட்டகம் + + + + Fast forward (held) + வேகமாக முன்னோக்கி (நடைபெற்றது) + + + + &Fast forward + & வேகமாக முன்னோக்கி + + + + Fast forward speed + வேகமாக முன்னோக்கி விரைவு + + + + Unbounded + எல்லையற்ற + + + + %0x + % 0x + + + + Increase fast forward speed + வேகமாக முன்னோக்கி வேகத்தை அதிகரிக்கவும் + + + + Decrease fast forward speed + வேகமாக முன்னோக்கி வேகத்தைக் குறைக்கவும் + + + + Rewind (held) + முன்னாடி (நடைபெற்றது) + + + + Re&wind + மறு & காற்று + + + + Step backwards + பின்னோக்கி செல்லுங்கள் + + + + Solar sensor + சூரிய சென்சார் + + + + Increase solar level + சூரிய அளவை அதிகரிக்கவும் + + + + Decrease solar level + சூரிய அளவைக் குறைக்கவும் + + + + Brightest solar level + பிரகாசமான சூரிய நிலை + + + + Darkest solar level + இருண்ட சூரிய நிலை + + + + Brightness %1 + ஒளி %1 + + + + Game Boy Printer... + கேம் பாய் பிரிண்டர் ... + + + + BattleChip Gate... + BATLECHIP வாயில் ... + + + + Audio/&Video + ஆடியோ/& வீடியோ + + + + Frame size + சட்ட அளவு + + + + %1× + %1 × + + + + Toggle fullscreen + மாற்று முழுத்திரை + + + + &Lock frame size + & லாக் பிரேம் அளவு + + + + Lock aspect ratio + பூட்டு விகித விகிதம் + + + + Force integer scaling + முழு எண் அளவிடுதல் + + + + Interframe blending + இடைக்கால கலப்பு + + + + Bilinear filtering + பிலினியர் வடிகட்டுதல் + + + + Frame&skip + சட்டகம் & தவிர்க்கவும் + + + + Mute + முடக்கு + + + + FPS target + FPS இலக்கு + + + + Native (59.7275) + சொந்த (59.7275) + + + + Take &screenshot + திரைக்காட்சி எடுத்துக் கொள்ளுங்கள் + + + + F12 + எஃப் 12 + + + + Record A/V... + பதிவு a/v ... + + + + Record GIF/WebP/APNG... + Gif/webp/apng ஐ பதிவு செய்யுங்கள் ... + + + + Video layers + வீடியோ அடுக்குகள் + + + + Audio channels + ஆடியோ சேனல்கள் + + + + Adjust layer placement... + அடுக்கு வேலைவாய்ப்பை சரிசெய்யவும் ... + + + + &Tools + கருவிகள் (&t) + + + + View &logs... + பார்வை & பதிவுகள் ... + + + + Game &overrides... + விளையாட்டு & மேலெழுதும் ... + + + + Game Pak sensors... + கேம் பாக் சென்சார்கள் ... + + + + &Cheats... + & ஏமாற்றுக்காரர்கள் ... + + + + Create forwarder... + முன்னோக்கி உருவாக்கு ... + + + + Settings... + அமைப்புகள் ... + + + + Open debugger console... + திறந்த பிழைத்திருத்த கன்சோல் ... + + + + Start &GDB server... + தொடக்க & GDB சேவையகம் ... + + + + Scripting... + ச்கிரிப்டிங் ... + + + + Game state views + விளையாட்டு நிலை காட்சிகள் + + + + View &palette... + பார்வை & தட்டு ... + + + + View &sprites... + பார்வை & உருவங்கள் ... + + + + View &tiles... + பார்வை & ஓடுகள் ... + + + + View &map... + பார்வை & வரைபடம் ... + + + + &Frame inspector... + & பிரேம் இன்ச்பெக்டர் ... + + + + View memory... + நினைவகத்தைக் காண்க ... + + + + Search memory... + தேடல் நினைவகம் ... + + + + View &I/O registers... + காண்க & i/o பதிவேடுகள் ... + + + + Log memory &accesses... + பதிவு நினைவகம் & அணுகல்கள் ... + + + + Record debug video log... + பிழைத்திருத்த வீடியோ பதிவைப் பதிவுசெய்க ... + + + + Stop debug video log + பிழைத்திருத்த வீடியோ பதிவை நிறுத்துங்கள் + + + + Exit fullscreen + முழுத்திரை வெளியேறவும் + + + + GameShark Button (held) + கேம்சார்க் பொத்தான் (நடைபெற்றது) + + + + Autofire + ஆட்டோஃபயர் + + + + Autofire A + ஆட்டோஃபயர் a + + + + Autofire B + ஆட்டோஃபயர் ஆ + + + + Autofire L + ஆட்டோஃபைர் எல் + + + + Autofire R + தன்னியக்க ஆர் + + + + Autofire Start + தன்னியக்க தொடக்க + + + + Autofire Select + ஆட்டோஃபயர் தேர்ந்தெடுக்கவும் + + + + Autofire Up + ஆட்டோஃபைர் அப் + + + + Autofire Right + தன்னியக்க சரியானது + + + + Autofire Down + ஆட்டோஃபயர் கீழே + + + + Autofire Left + ஆட்டோஃபயர் இடது + + + + Clear + தெளிவான + + + + QObject + + + %1 byte + %1 பைட் + + + + %1 kiB + % 1 பார்வை + + + + %1 MiB + %1 MIB + + + + GBA + பெறுங்கள் + + + + GB + சிபி + + + + ? + ? + + + + Super (L) + சூப்பர் (எல்) + + + + Super (R) + சூப்பர் (ஆர்) + + + + Menu + பட்டியல் + + + + QShortcut + + + Shift + உயர்த்து + + + + Control + கட்டுப்பாடு + + + + Alt + மாற்று + + + + Meta + மெட்டா + + + From 9c9614e16d568a4894145fb8b14dbe4c59a3dcab Mon Sep 17 00:00:00 2001 From: reimu105 Date: Sat, 18 Jan 2025 13:34:21 +0000 Subject: [PATCH 31/31] Qt: Update translation (Chinese (Simplified Han script)) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/zh_Hans/ --- src/platform/qt/ts/mgba-zh_CN.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/qt/ts/mgba-zh_CN.ts b/src/platform/qt/ts/mgba-zh_CN.ts index 0518b256b..1b5bf201f 100644 --- a/src/platform/qt/ts/mgba-zh_CN.ts +++ b/src/platform/qt/ts/mgba-zh_CN.ts @@ -3409,7 +3409,7 @@ Download size: %3 Failed to open memory log file - 打开内存日志文件失败 + 打开内存日志文件失败 @@ -4371,7 +4371,7 @@ Download size: %3 File information - + 文件信息 @@ -4381,7 +4381,7 @@ Download size: %3 MD5 - + MD5