From c80cc1e307397b0eacc97c40009be58aaa56a4ec Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Nov 2020 17:43:35 -0800 Subject: [PATCH 01/20] Core: Replace GBA_COLOR_WHITE with M_COLOR_WHITE --- include/mgba/core/interface.h | 3 +++ include/mgba/internal/gba/renderers/video-software.h | 9 --------- src/gba/extra/proxy.c | 2 +- src/gba/renderers/video-software.c | 6 +++--- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index a4f2d1598..d5bcaf690 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -41,16 +41,19 @@ typedef uint32_t color_t; #define M_COLOR_GREEN 0x0000FF00 #define M_COLOR_BLUE 0x00FF0000 #define M_COLOR_ALPHA 0xFF000000 +#define M_COLOR_WHITE 0x00FFFFFF #elif defined(COLOR_5_6_5) #define M_COLOR_RED 0x001F #define M_COLOR_GREEN 0x07E0 #define M_COLOR_BLUE 0xF800 #define M_COLOR_ALPHA 0x0000 +#define M_COLOR_WHITE 0xFFDF #else #define M_COLOR_RED 0x001F #define M_COLOR_GREEN 0x03E0 #define M_COLOR_BLUE 0x7C00 #define M_COLOR_ALPHA 0x1000 +#define M_COLOR_WHITE 0x7FFF #endif #ifndef PYCPARSE diff --git a/include/mgba/internal/gba/renderers/video-software.h b/include/mgba/internal/gba/renderers/video-software.h index fac4098f7..9c603905b 100644 --- a/include/mgba/internal/gba/renderers/video-software.h +++ b/include/mgba/internal/gba/renderers/video-software.h @@ -46,15 +46,6 @@ struct GBAVideoSoftwareBackground { }; enum { -#ifdef COLOR_16_BIT -#ifdef COLOR_5_6_5 - GBA_COLOR_WHITE = 0xFFDF, -#else - GBA_COLOR_WHITE = 0x7FFF, -#endif -#else - GBA_COLOR_WHITE = 0x00FFFFFF, -#endif OFFSET_PRIORITY = 30, OFFSET_INDEX = 28, }; diff --git a/src/gba/extra/proxy.c b/src/gba/extra/proxy.c index f96cca31e..be961c619 100644 --- a/src/gba/extra/proxy.c +++ b/src/gba/extra/proxy.c @@ -55,7 +55,7 @@ void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct for (i = 0; i < 128; ++i) { renderer->d.highlightOBJ[i] = false; } - renderer->d.highlightColor = 0xFFFFFF; + renderer->d.highlightColor = M_COLOR_WHITE; renderer->d.highlightAmount = 0; renderer->logger->context = renderer; diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index 8eca425ff..db8749cd5 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -73,7 +73,7 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) { for (i = 0; i < 128; ++i) { renderer->d.highlightOBJ[i] = false; } - renderer->d.highlightColor = GBA_COLOR_WHITE; + renderer->d.highlightColor = M_COLOR_WHITE; renderer->d.highlightAmount = 0; renderer->temporaryBuffer = 0; @@ -89,7 +89,7 @@ static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer) { color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y]; int x; for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; ++x) { - row[x] = GBA_COLOR_WHITE; + row[x] = M_COLOR_WHITE; } } } @@ -558,7 +558,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render if (GBARegisterDISPCNTIsForcedBlank(softwareRenderer->dispcnt)) { int x; for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; ++x) { - row[x] = GBA_COLOR_WHITE; + row[x] = M_COLOR_WHITE; } return; } From 7d77aac68fec49a947c71bb67d03c7f08a8c84eb Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Nov 2020 17:48:30 -0800 Subject: [PATCH 02/20] GBA Video: Clean up redundant code --- src/gba/extra/proxy.c | 46 +++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/src/gba/extra/proxy.c b/src/gba/extra/proxy.c index be961c619..a497cd7ee 100644 --- a/src/gba/extra/proxy.c +++ b/src/gba/extra/proxy.c @@ -88,6 +88,24 @@ static void _reset(struct GBAVideoProxyRenderer* proxyRenderer) { mVideoLoggerRendererReset(proxyRenderer->logger); } +static void _copyExtraState(struct GBAVideoProxyRenderer* proxyRenderer) { + proxyRenderer->backend->disableBG[0] = proxyRenderer->d.disableBG[0]; + proxyRenderer->backend->disableBG[1] = proxyRenderer->d.disableBG[1]; + proxyRenderer->backend->disableBG[2] = proxyRenderer->d.disableBG[2]; + proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3]; + proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ; + proxyRenderer->backend->disableWIN[0] = proxyRenderer->d.disableWIN[0]; + proxyRenderer->backend->disableWIN[1] = proxyRenderer->d.disableWIN[1]; + proxyRenderer->backend->disableOBJWIN = proxyRenderer->d.disableOBJWIN; + proxyRenderer->backend->highlightBG[0] = proxyRenderer->d.highlightBG[0]; + proxyRenderer->backend->highlightBG[1] = proxyRenderer->d.highlightBG[1]; + proxyRenderer->backend->highlightBG[2] = proxyRenderer->d.highlightBG[2]; + proxyRenderer->backend->highlightBG[3] = proxyRenderer->d.highlightBG[3]; + memcpy(proxyRenderer->backend->highlightOBJ, proxyRenderer->d.highlightOBJ, sizeof(proxyRenderer->backend->highlightOBJ)); + proxyRenderer->backend->highlightAmount = proxyRenderer->d.highlightAmount; + proxyRenderer->backend->highlightColor = proxyRenderer->d.highlightColor; +} + void GBAVideoProxyRendererShim(struct GBAVideo* video, struct GBAVideoProxyRenderer* renderer) { if ((renderer->backend && video->renderer != renderer->backend) || video->renderer == &renderer->d) { return; @@ -200,20 +218,7 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD } break; case DIRTY_SCANLINE: - proxyRenderer->backend->disableBG[0] = proxyRenderer->d.disableBG[0]; - proxyRenderer->backend->disableBG[1] = proxyRenderer->d.disableBG[1]; - proxyRenderer->backend->disableBG[2] = proxyRenderer->d.disableBG[2]; - proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3]; - proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ; - proxyRenderer->backend->disableWIN[0] = proxyRenderer->d.disableWIN[0]; - proxyRenderer->backend->disableWIN[1] = proxyRenderer->d.disableWIN[1]; - proxyRenderer->backend->disableOBJWIN = proxyRenderer->d.disableOBJWIN; - proxyRenderer->backend->highlightBG[0] = proxyRenderer->d.highlightBG[0]; - proxyRenderer->backend->highlightBG[1] = proxyRenderer->d.highlightBG[1]; - proxyRenderer->backend->highlightBG[2] = proxyRenderer->d.highlightBG[2]; - proxyRenderer->backend->highlightBG[3] = proxyRenderer->d.highlightBG[3]; - memcpy(proxyRenderer->backend->highlightOBJ, proxyRenderer->d.highlightOBJ, sizeof(proxyRenderer->backend->highlightOBJ)); - proxyRenderer->backend->highlightAmount = proxyRenderer->d.highlightAmount; + _copyExtraState(proxyRenderer); if (item->address < GBA_VIDEO_VERTICAL_PIXELS) { proxyRenderer->backend->drawScanline(proxyRenderer->backend, item->address); } @@ -303,18 +308,7 @@ void GBAVideoProxyRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t o void GBAVideoProxyRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) { struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; if (!proxyRenderer->logger->block) { - proxyRenderer->backend->disableBG[0] = proxyRenderer->d.disableBG[0]; - proxyRenderer->backend->disableBG[1] = proxyRenderer->d.disableBG[1]; - proxyRenderer->backend->disableBG[2] = proxyRenderer->d.disableBG[2]; - proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3]; - proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ; - proxyRenderer->backend->disableWIN[0] = proxyRenderer->d.disableWIN[0]; - proxyRenderer->backend->disableWIN[1] = proxyRenderer->d.disableWIN[1]; - proxyRenderer->backend->disableOBJWIN = proxyRenderer->d.disableOBJWIN; - proxyRenderer->backend->highlightBG[0] = proxyRenderer->d.highlightBG[0]; - proxyRenderer->backend->highlightBG[1] = proxyRenderer->d.highlightBG[1]; - proxyRenderer->backend->highlightBG[2] = proxyRenderer->d.highlightBG[2]; - proxyRenderer->backend->highlightBG[3] = proxyRenderer->d.highlightBG[3]; + _copyExtraState(proxyRenderer); proxyRenderer->backend->drawScanline(proxyRenderer->backend, y); } mVideoLoggerRendererDrawScanline(proxyRenderer->logger, y); From ce97e265a3e26f7b1b25de872700fe3ef16fb450 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Nov 2020 18:10:55 -0800 Subject: [PATCH 03/20] GB Video: Add constants for OBJ maxima --- include/mgba/gb/interface.h | 2 ++ include/mgba/internal/gb/video.h | 7 +++++-- src/gb/extra/proxy.c | 4 ++-- src/gb/renderers/software.c | 2 +- src/gb/video.c | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/mgba/gb/interface.h b/include/mgba/gb/interface.h index e963bd563..20eccd38e 100644 --- a/include/mgba/gb/interface.h +++ b/include/mgba/gb/interface.h @@ -10,6 +10,8 @@ CXX_GUARD_START +#include + enum GBModel { GB_MODEL_AUTODETECT = 0xFF, GB_MODEL_DMG = 0x00, diff --git a/include/mgba/internal/gb/video.h b/include/mgba/internal/gb/video.h index cd5a1e8d1..35f1b8fb2 100644 --- a/include/mgba/internal/gb/video.h +++ b/include/mgba/internal/gb/video.h @@ -31,6 +31,9 @@ enum { GB_VIDEO_TOTAL_LENGTH = 70224, + GB_VIDEO_MAX_OBJ = 40, + GB_VIDEO_MAX_LINE_OBJ = 10, + GB_BASE_MAP = 0x1800, GB_SIZE_MAP = 0x0400, @@ -63,8 +66,8 @@ struct GBObj { }; union GBOAM { - struct GBObj obj[40]; - uint8_t raw[160]; + struct GBObj obj[GB_VIDEO_MAX_OBJ]; + uint8_t raw[GB_VIDEO_MAX_OBJ * 4]; }; struct mCacheSet; diff --git a/src/gb/extra/proxy.c b/src/gb/extra/proxy.c index fd5d8d6cf..266bb634a 100644 --- a/src/gb/extra/proxy.c +++ b/src/gb/extra/proxy.c @@ -119,7 +119,7 @@ void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer) { static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) { struct GBVideoProxyRenderer* proxyRenderer = logger->context; uint8_t sgbPacket[16]; - struct GBObj legacyBuffer[40]; + struct GBObj legacyBuffer[GB_VIDEO_MAX_OBJ]; switch (item->type) { case DIRTY_REGISTER: proxyRenderer->backend->writeVideoRegister(proxyRenderer->backend, item->address, item->value); @@ -160,7 +160,7 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD case DIRTY_BUFFER: switch (item->address) { case BUFFER_OAM: - if (item->value2 / sizeof(struct GBObj) > 40) { + if (item->value2 / sizeof(struct GBObj) > GB_VIDEO_MAX_OBJ) { return false; } logger->readData(logger, legacyBuffer, item->value2, true); diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index f0436ee85..7426d4a5c 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -508,7 +508,7 @@ static void _cleanOAM(struct GBVideoSoftwareRenderer* renderer, int y) { } int o = 0; int i; - for (i = 0; i < 40 && o < 10; ++i) { + for (i = 0; i < GB_VIDEO_MAX_OBJ && o < GB_VIDEO_MAX_LINE_OBJ; ++i) { uint8_t oy = renderer->d.oam->obj[i].y; if (y < oy - 16 || y >= oy - 16 + spriteHeight) { continue; diff --git a/src/gb/video.c b/src/gb/video.c index 072e9db98..9826b601f 100644 --- a/src/gb/video.c +++ b/src/gb/video.c @@ -409,7 +409,7 @@ static void _cleanOAM(struct GBVideo* video, int y) { } int o = 0; int i; - for (i = 0; i < 40 && o < 10; ++i) { + for (i = 0; i < GB_VIDEO_MAX_OBJ && o < GB_VIDEO_MAX_LINE_OBJ; ++i) { uint8_t oy = video->oam.obj[i].y; if (y < oy - 16 || y >= oy - 16 + spriteHeight) { continue; From 0b0a70d9b725c294034f2f2d9fdbaa4a3a6b5729 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Nov 2020 19:28:36 -0800 Subject: [PATCH 04/20] Core: Make _mix public --- include/mgba/core/interface.h | 62 +++++++++++++++++++++++++ src/gba/renderers/software-private.h | 68 +--------------------------- src/gba/renderers/video-software.c | 6 +-- 3 files changed, 67 insertions(+), 69 deletions(-) diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index d5bcaf690..4109038d4 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -73,6 +73,68 @@ static inline color_t mColorFrom555(uint16_t value) { #endif return color; } + +ATTRIBUTE_UNUSED static unsigned mColorMix5Bit(int weightA, unsigned colorA, int weightB, unsigned colorB) { + unsigned c = 0; + unsigned a, b; +#ifdef COLOR_16_BIT +#ifdef COLOR_5_6_5 + a = colorA & 0xF81F; + b = colorB & 0xF81F; + a |= (colorA & 0x7C0) << 16; + b |= (colorB & 0x7C0) << 16; + c = ((a * weightA + b * weightB) / 16); + if (c & 0x08000000) { + c = (c & ~0x0FC00000) | 0x07C00000; + } + if (c & 0x0020) { + c = (c & ~0x003F) | 0x001F; + } + if (c & 0x10000) { + c = (c & ~0x1F800) | 0xF800; + } + c = (c & 0xF81F) | ((c >> 16) & 0x07C0); +#else + a = colorA & 0x7C1F; + b = colorB & 0x7C1F; + a |= (colorA & 0x3E0) << 16; + b |= (colorB & 0x3E0) << 16; + c = ((a * weightA + b * weightB) / 16); + if (c & 0x04000000) { + c = (c & ~0x07E00000) | 0x03E00000; + } + if (c & 0x0020) { + c = (c & ~0x003F) | 0x001F; + } + if (c & 0x8000) { + c = (c & ~0xF800) | 0x7C00; + } + c = (c & 0x7C1F) | ((c >> 16) & 0x03E0); +#endif +#else + a = colorA & 0xFF; + b = colorB & 0xFF; + c |= ((a * weightA + b * weightB) / 16) & 0x1FF; + if (c & 0x00000100) { + c = 0x000000FF; + } + + a = colorA & 0xFF00; + b = colorB & 0xFF00; + c |= ((a * weightA + b * weightB) / 16) & 0x1FF00; + if (c & 0x00010000) { + c = (c & 0x000000FF) | 0x0000FF00; + } + + a = colorA & 0xFF0000; + b = colorB & 0xFF0000; + c |= ((a * weightA + b * weightB) / 16) & 0x1FF0000; + if (c & 0x01000000) { + c = (c & 0x0000FFFF) | 0x00FF0000; + } +#endif + return c; +} #endif struct blip_t; diff --git a/src/gba/renderers/software-private.h b/src/gba/renderers/software-private.h index 8ac181800..a527f901d 100644 --- a/src/gba/renderers/software-private.h +++ b/src/gba/renderers/software-private.h @@ -31,8 +31,6 @@ void GBAVideoSoftwareRendererPostprocessSprite(struct GBAVideoSoftwareRenderer* static inline unsigned _brighten(unsigned color, int y); static inline unsigned _darken(unsigned color, int y); -static unsigned _mix(int weightA, unsigned colorA, int weightB, unsigned colorB); - // We stash the priority on the top bits so we can do a one-operator comparison // The lower the number, the higher the priority, and sprites take precedence over backgrounds @@ -41,7 +39,7 @@ static unsigned _mix(int weightA, unsigned colorA, int weightB, unsigned colorB) static inline void _compositeBlendObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) { if (color >= current) { if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) { - color = _mix(renderer->blda, current, renderer->bldb, color); + color = mColorMix5Bit(renderer->blda, current, renderer->bldb, color); } else { color = current & (0x00FFFFFF | FLAG_REBLEND | FLAG_OBJWIN); } @@ -54,7 +52,7 @@ static inline void _compositeBlendObjwin(struct GBAVideoSoftwareRenderer* render static inline void _compositeBlendNoObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) { if (color >= current) { if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) { - color = _mix(renderer->blda, current, renderer->bldb, color); + color = mColorMix5Bit(renderer->blda, current, renderer->bldb, color); } else { color = current & (0x00FFFFFF | FLAG_REBLEND | FLAG_OBJWIN); } @@ -234,66 +232,4 @@ static inline unsigned _darken(unsigned color, int y) { return c; } -static unsigned _mix(int weightA, unsigned colorA, int weightB, unsigned colorB) { - unsigned c = 0; - unsigned a, b; -#ifdef COLOR_16_BIT -#ifdef COLOR_5_6_5 - a = colorA & 0xF81F; - b = colorB & 0xF81F; - a |= (colorA & 0x7C0) << 16; - b |= (colorB & 0x7C0) << 16; - c = ((a * weightA + b * weightB) / 16); - if (c & 0x08000000) { - c = (c & ~0x0FC00000) | 0x07C00000; - } - if (c & 0x0020) { - c = (c & ~0x003F) | 0x001F; - } - if (c & 0x10000) { - c = (c & ~0x1F800) | 0xF800; - } - c = (c & 0xF81F) | ((c >> 16) & 0x07C0); -#else - a = colorA & 0x7C1F; - b = colorB & 0x7C1F; - a |= (colorA & 0x3E0) << 16; - b |= (colorB & 0x3E0) << 16; - c = ((a * weightA + b * weightB) / 16); - if (c & 0x04000000) { - c = (c & ~0x07E00000) | 0x03E00000; - } - if (c & 0x0020) { - c = (c & ~0x003F) | 0x001F; - } - if (c & 0x8000) { - c = (c & ~0xF800) | 0x7C00; - } - c = (c & 0x7C1F) | ((c >> 16) & 0x03E0); -#endif -#else - a = colorA & 0xFF; - b = colorB & 0xFF; - c |= ((a * weightA + b * weightB) / 16) & 0x1FF; - if (c & 0x00000100) { - c = 0x000000FF; - } - - a = colorA & 0xFF00; - b = colorB & 0xFF00; - c |= ((a * weightA + b * weightB) / 16) & 0x1FF00; - if (c & 0x00010000) { - c = (c & 0x000000FF) | 0x0000FF00; - } - - a = colorA & 0xFF0000; - b = colorB & 0xFF0000; - c |= ((a * weightA + b * weightB) / 16) & 0x1FF0000; - if (c & 0x01000000) { - c = (c & 0x0000FFFF) | 0x00FF0000; - } -#endif - return c; -} - #endif diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index db8749cd5..0c6f31dd9 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -640,7 +640,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render for (; x < end; ++x) { uint32_t color = softwareRenderer->row[x]; if (color & FLAG_TARGET_1) { - softwareRenderer->row[x] = _mix(softwareRenderer->bldb, backdrop, softwareRenderer->blda, color); + softwareRenderer->row[x] = mColorMix5Bit(softwareRenderer->bldb, backdrop, softwareRenderer->blda, color); } } } @@ -975,8 +975,8 @@ static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer) { if (highlightAmount) { for (i = 0; i < 512; ++i) { - renderer->highlightPalette[i] = _mix(0x10 - highlightAmount, renderer->normalPalette[i], highlightAmount, renderer->d.highlightColor); - renderer->highlightVariantPalette[i] = _mix(0x10 - highlightAmount, renderer->variantPalette[i], highlightAmount, renderer->d.highlightColor); + renderer->highlightPalette[i] = mColorMix5Bit(0x10 - highlightAmount, renderer->normalPalette[i], highlightAmount, renderer->d.highlightColor); + renderer->highlightVariantPalette[i] = mColorMix5Bit(0x10 - highlightAmount, renderer->variantPalette[i], highlightAmount, renderer->d.highlightColor); } } } From 6174858d0d6a8de2e153dd39ae323bfce8c0c921 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Nov 2020 20:17:11 -0800 Subject: [PATCH 05/20] Core: Add RGB8 to native color function --- include/mgba/core/interface.h | 6 ++++++ src/platform/qt/FrameView.cpp | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index 4109038d4..ca42bca7b 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -42,18 +42,24 @@ typedef uint32_t color_t; #define M_COLOR_BLUE 0x00FF0000 #define M_COLOR_ALPHA 0xFF000000 #define M_COLOR_WHITE 0x00FFFFFF + +#define M_RGB8_TO_NATIVE(X) (((X) & 0x00FF00) | (((X) & 0x0000FF) << 16) | (((X) & 0xFF0000) >> 16)) #elif defined(COLOR_5_6_5) #define M_COLOR_RED 0x001F #define M_COLOR_GREEN 0x07E0 #define M_COLOR_BLUE 0xF800 #define M_COLOR_ALPHA 0x0000 #define M_COLOR_WHITE 0xFFDF + +#define M_RGB8_TO_NATIVE(X) ((((X) & 0xF8) << 8) | (((X) & 0xFC00) >> 5) | (((X) & 0xF80000) >> 19)) #else #define M_COLOR_RED 0x001F #define M_COLOR_GREEN 0x03E0 #define M_COLOR_BLUE 0x7C00 #define M_COLOR_ALPHA 0x1000 #define M_COLOR_WHITE 0x7FFF + +#define M_RGB8_TO_NATIVE(X) M_RGB8_TO_BGR5(X) #endif #ifndef PYCPARSE diff --git a/src/platform/qt/FrameView.cpp b/src/platform/qt/FrameView.cpp index 42091a494..f15c7ff37 100644 --- a/src/platform/qt/FrameView.cpp +++ b/src/platform/qt/FrameView.cpp @@ -275,7 +275,7 @@ void FrameView::injectGBA() { gba->video.renderer->highlightOBJ[i] = false; } QPalette palette; - gba->video.renderer->highlightColor = palette.color(QPalette::HighlightedText).rgb(); + gba->video.renderer->highlightColor = M_RGB8_TO_NATIVE(palette.color(QPalette::Highlight).rgb()); gba->video.renderer->highlightAmount = sin(m_glowFrame * M_PI / 30) * 48 + 64; if (!m_overrideBackdrop.isValid()) { QRgb backdrop = M_RGB5_TO_RGB8(gba->video.palette[0]) | 0xFF000000; From 4baa8b3d9b5ecf411d65d5f53d5ec705b926d6dc Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Nov 2020 20:27:30 -0800 Subject: [PATCH 06/20] GB Video: Add highlighting --- include/mgba/internal/gb/renderers/software.h | 16 +- include/mgba/internal/gb/video.h | 6 + src/gb/extra/proxy.c | 28 ++- src/gb/renderers/software.c | 192 +++++++++++------- src/platform/qt/FrameView.cpp | 18 ++ 5 files changed, 178 insertions(+), 82 deletions(-) diff --git a/include/mgba/internal/gb/renderers/software.h b/include/mgba/internal/gb/renderers/software.h index 11e107f6d..57942a7dc 100644 --- a/include/mgba/internal/gb/renderers/software.h +++ b/include/mgba/internal/gb/renderers/software.h @@ -14,16 +14,22 @@ CXX_GUARD_START #include #include +struct GBVideoRendererSprite { + struct GBObj obj; + int8_t index; +}; + struct GBVideoSoftwareRenderer { struct GBVideoRenderer d; color_t* outputBuffer; int outputBufferStride; - uint8_t row[GB_VIDEO_HORIZONTAL_PIXELS + 8]; + // TODO: Implement the pixel FIFO + uint16_t row[GB_VIDEO_HORIZONTAL_PIXELS + 8]; - color_t palette[128]; - uint8_t lookup[64]; + color_t palette[192]; + uint8_t lookup[192]; uint32_t* temporaryBuffer; @@ -40,7 +46,7 @@ struct GBVideoSoftwareRenderer { GBRegisterLCDC lcdc; enum GBModel model; - struct GBObj obj[10]; + struct GBVideoRendererSprite obj[GB_VIDEO_MAX_LINE_OBJ]; int objMax; int16_t objOffsetX; @@ -54,6 +60,8 @@ struct GBVideoSoftwareRenderer { uint8_t sgbPacket[128]; uint8_t sgbCommandHeader; bool sgbBorders; + + uint8_t lastHighlightAmount; }; void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer*); diff --git a/include/mgba/internal/gb/video.h b/include/mgba/internal/gb/video.h index 35f1b8fb2..da83ebc2a 100644 --- a/include/mgba/internal/gb/video.h +++ b/include/mgba/internal/gb/video.h @@ -102,6 +102,12 @@ struct GBVideoRenderer { bool disableBG; bool disableOBJ; bool disableWIN; + + bool highlightBG; + bool highlightOBJ[GB_VIDEO_MAX_OBJ]; + bool highlightWIN; + color_t highlightColor; + uint8_t highlightAmount; }; DECL_BITFIELD(GBRegisterLCDC, uint8_t); diff --git a/src/gb/extra/proxy.c b/src/gb/extra/proxy.c index 266bb634a..29be8af49 100644 --- a/src/gb/extra/proxy.c +++ b/src/gb/extra/proxy.c @@ -48,6 +48,15 @@ void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GB renderer->d.disableWIN = false; renderer->d.disableOBJ = false; + renderer->d.highlightBG = false; + renderer->d.highlightWIN = false; + int i; + for (i = 0; i < GB_VIDEO_MAX_OBJ; ++i) { + renderer->d.highlightOBJ[i] = false; + } + renderer->d.highlightColor = M_COLOR_WHITE; + renderer->d.highlightAmount = 0; + renderer->logger->context = renderer; renderer->logger->parsePacket = _parsePacket; renderer->logger->vramBlock = _vramBlock; @@ -75,6 +84,17 @@ static void _reset(struct GBVideoProxyRenderer* proxyRenderer) { mVideoLoggerRendererReset(proxyRenderer->logger); } +static void _copyExtraState(struct GBVideoProxyRenderer* proxyRenderer) { + proxyRenderer->backend->disableBG = proxyRenderer->d.disableBG; + proxyRenderer->backend->disableWIN = proxyRenderer->d.disableWIN; + proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ; + proxyRenderer->backend->highlightBG = proxyRenderer->d.highlightBG; + proxyRenderer->backend->highlightWIN = proxyRenderer->d.highlightWIN; + memcpy(proxyRenderer->backend->highlightOBJ, proxyRenderer->d.highlightOBJ, sizeof(proxyRenderer->backend->highlightOBJ)); + proxyRenderer->backend->highlightAmount = proxyRenderer->d.highlightAmount; + proxyRenderer->backend->highlightColor = proxyRenderer->d.highlightColor; +} + void GBVideoProxyRendererShim(struct GBVideo* video, struct GBVideoProxyRenderer* renderer) { if ((renderer->backend && video->renderer != renderer->backend) || video->renderer == &renderer->d) { return; @@ -142,9 +162,7 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD } break; case DIRTY_SCANLINE: - proxyRenderer->backend->disableBG = proxyRenderer->d.disableBG; - proxyRenderer->backend->disableWIN = proxyRenderer->d.disableWIN; - proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ; + _copyExtraState(proxyRenderer); if (item->address < GB_VIDEO_VERTICAL_PIXELS) { proxyRenderer->backend->finishScanline(proxyRenderer->backend, item->address); } @@ -235,9 +253,7 @@ void GBVideoProxyRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y) { struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer; if (!proxyRenderer->logger->block) { - proxyRenderer->backend->disableBG = proxyRenderer->d.disableBG; - proxyRenderer->backend->disableWIN = proxyRenderer->d.disableWIN; - proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ; + _copyExtraState(proxyRenderer); proxyRenderer->backend->drawRange(proxyRenderer->backend, startX, endX, y); } mVideoLoggerRendererDrawRange(proxyRenderer->logger, startX, endX, y); diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index 7426d4a5c..6f3610eee 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -11,6 +11,15 @@ #include #include +#define PAL_BG 0 +#define PAL_OBJ 0x20 +#define PAL_HIGHLIGHT 0x80 +#define PAL_HIGHLIGHT_BG (PAL_HIGHLIGHT | PAL_BG) +#define PAL_HIGHLIGHT_OBJ (PAL_HIGHLIGHT | PAL_OBJ) +#define PAL_SGB_BORDER 0x40 +#define OBJ_PRIORITY 0x100 +#define OBJ_PRIO_MASK 0x0FF + static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders); static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer); static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value); @@ -25,8 +34,8 @@ static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* rende static void GBVideoSoftwareRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels); static void GBVideoSoftwareRendererPutPixels(struct GBVideoRenderer* renderer, size_t stride, const void* pixels); -static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int sx, int sy); -static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y); +static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int sx, int sy, bool highlight); +static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBVideoRendererSprite* obj, int startX, int endX, int y); static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) { size_t sgbOffset = 0; @@ -51,7 +60,7 @@ static void _regenerateSGBBorder(struct GBVideoSoftwareRenderer* renderer) { for (i = 0; i < 0x40; ++i) { uint16_t color; LOAD_16LE(color, 0x800 + i * 2, renderer->d.sgbMapRam); - renderer->d.writePalette(&renderer->d, i + 0x40, color); + renderer->d.writePalette(&renderer->d, i + PAL_SGB_BORDER, color); } int x, y; for (y = 0; y < 224; ++y) { @@ -180,6 +189,15 @@ void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer* renderer) { renderer->d.disableOBJ = false; renderer->d.disableWIN = false; + renderer->d.highlightBG = false; + renderer->d.highlightWIN = false; + int i; + for (i = 0; i < GB_VIDEO_MAX_OBJ; ++i) { + renderer->d.highlightOBJ[i] = false; + } + renderer->d.highlightColor = M_COLOR_WHITE; + renderer->d.highlightAmount = 0; + renderer->temporaryBuffer = 0; } @@ -206,8 +224,8 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G softwareRenderer->offsetWx = 0; softwareRenderer->offsetWy = 0; - int i; - for (i = 0; i < 64; ++i) { + size_t i; + for (i = 0; i < (sizeof(softwareRenderer->lookup) / sizeof(*softwareRenderer->lookup)); ++i) { softwareRenderer->lookup[i] = i; softwareRenderer->lookup[i] = i; softwareRenderer->lookup[i] = i; @@ -215,6 +233,8 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G } memset(softwareRenderer->palette, 0, sizeof(softwareRenderer->palette)); + + softwareRenderer->lastHighlightAmount = 0; } static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer) { @@ -280,18 +300,30 @@ static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* softwareRenderer->lookup[1] = (value >> 2) & 3; softwareRenderer->lookup[2] = (value >> 4) & 3; softwareRenderer->lookup[3] = (value >> 6) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 0] = value & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 1] = (value >> 2) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 2] = (value >> 4) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 3] = (value >> 6) & 3; break; case GB_REG_OBP0: - softwareRenderer->lookup[0x20 + 0] = value & 3; - softwareRenderer->lookup[0x20 + 1] = (value >> 2) & 3; - softwareRenderer->lookup[0x20 + 2] = (value >> 4) & 3; - softwareRenderer->lookup[0x20 + 3] = (value >> 6) & 3; + softwareRenderer->lookup[PAL_OBJ + 0] = value & 3; + softwareRenderer->lookup[PAL_OBJ + 1] = (value >> 2) & 3; + softwareRenderer->lookup[PAL_OBJ + 2] = (value >> 4) & 3; + softwareRenderer->lookup[PAL_OBJ + 3] = (value >> 6) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 0] = value & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 1] = (value >> 2) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 2] = (value >> 4) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 3] = (value >> 6) & 3; break; case GB_REG_OBP1: - softwareRenderer->lookup[0x24 + 0] = value & 3; - softwareRenderer->lookup[0x24 + 1] = (value >> 2) & 3; - softwareRenderer->lookup[0x24 + 2] = (value >> 4) & 3; - softwareRenderer->lookup[0x24 + 3] = (value >> 6) & 3; + softwareRenderer->lookup[PAL_OBJ + 4] = value & 3; + softwareRenderer->lookup[PAL_OBJ + 5] = (value >> 2) & 3; + softwareRenderer->lookup[PAL_OBJ + 6] = (value >> 4) & 3; + softwareRenderer->lookup[PAL_OBJ + 7] = (value >> 6) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 4] = value & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 5] = (value >> 2) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 6] = (value >> 4) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 7] = (value >> 6) & 3; break; } return value; @@ -442,8 +474,10 @@ static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer if (softwareRenderer->model & GB_MODEL_SGB) { if (index < 0x10 && index && !(index & 3)) { color = softwareRenderer->palette[0]; - } else if (index >= 0x40 && !(index & 0xF)) { + } else if (index >= PAL_SGB_BORDER && !(index & 0xF)) { color = softwareRenderer->palette[0]; + } else if (index > PAL_HIGHLIGHT && index < PAL_HIGHLIGHT_OBJ && !(index & 3)) { + color = softwareRenderer->palette[PAL_HIGHLIGHT_BG]; } } if (renderer->cache) { @@ -472,6 +506,9 @@ static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer #endif } softwareRenderer->palette[index] = color; + if (index < PAL_SGB_BORDER && (index < PAL_OBJ || (index & 3))) { + softwareRenderer->palette[index + PAL_HIGHLIGHT] = mColorMix5Bit(0x10 - softwareRenderer->lastHighlightAmount, color, softwareRenderer->lastHighlightAmount, renderer->highlightColor); + } if (softwareRenderer->model & GB_MODEL_SGB && !index && GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) { renderer->writePalette(renderer, 0x04, value); @@ -514,7 +551,8 @@ static void _cleanOAM(struct GBVideoSoftwareRenderer* renderer, int y) { continue; } // TODO: Sort - renderer->obj[o] = renderer->d.oam->obj[i]; + renderer->obj[o].obj = renderer->d.oam->obj[i]; + renderer->obj[o].index = i; ++o; if (o == 10) { break; @@ -542,16 +580,16 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i } if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && softwareRenderer->hasWindow && wx <= endX && !softwareRenderer->d.disableWIN) { if (wx > 0 && !softwareRenderer->d.disableBG) { - GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, wx, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy); + GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, wx, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy, renderer->highlightBG); } maps = &softwareRenderer->d.vram[GB_BASE_MAP]; if (GBRegisterLCDCIsWindowTileMap(softwareRenderer->lcdc)) { maps += GB_SIZE_MAP; } - GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, wx, endX, -wx - softwareRenderer->offsetWx, y - wy - softwareRenderer->offsetWy); + GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, wx, endX, -wx - softwareRenderer->offsetWx, y - wy - softwareRenderer->offsetWy, renderer->highlightWIN); } else if (!softwareRenderer->d.disableBG) { - GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy); + GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy, renderer->highlightBG); } } else if (!softwareRenderer->d.disableBG) { memset(&softwareRenderer->row[startX], 0, endX - startX); @@ -567,6 +605,18 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i } } + unsigned highlightAmount = (renderer->highlightAmount + 6) >> 4; + if (softwareRenderer->lastHighlightAmount != highlightAmount) { + softwareRenderer->lastHighlightAmount = highlightAmount; + int i; + for (i = 0; i < PAL_SGB_BORDER; ++i) { + if (i >= PAL_OBJ && (i & 3) == 0) { + continue; + } + softwareRenderer->palette[i + PAL_HIGHLIGHT] = mColorMix5Bit(0x10 - highlightAmount, softwareRenderer->palette[i], highlightAmount, renderer->highlightColor); + } + } + size_t sgbOffset = 0; if (softwareRenderer->model & GB_MODEL_SGB && softwareRenderer->sgbBorders) { sgbOffset = softwareRenderer->outputBufferStride * 40 + 48; @@ -583,7 +633,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i p <<= 2; } for (; x < ((startX + 7) & ~7) && x < endX; ++x) { - row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & 0x7F]]; + row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & OBJ_PRIO_MASK]]; } for (; x + 7 < (endX & ~7); x += 8) { if (softwareRenderer->model & GB_MODEL_SGB) { @@ -592,14 +642,14 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i p &= 3; p <<= 2; } - row[x + 0] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & 0x7F]]; - row[x + 1] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 1] & 0x7F]]; - row[x + 2] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 2] & 0x7F]]; - row[x + 3] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 3] & 0x7F]]; - row[x + 4] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 4] & 0x7F]]; - row[x + 5] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 5] & 0x7F]]; - row[x + 6] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 6] & 0x7F]]; - row[x + 7] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 7] & 0x7F]]; + row[x + 0] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & OBJ_PRIO_MASK]]; + row[x + 1] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 1] & OBJ_PRIO_MASK]]; + row[x + 2] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 2] & OBJ_PRIO_MASK]]; + row[x + 3] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 3] & OBJ_PRIO_MASK]]; + row[x + 4] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 4] & OBJ_PRIO_MASK]]; + row[x + 5] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 5] & OBJ_PRIO_MASK]]; + row[x + 6] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 6] & OBJ_PRIO_MASK]]; + row[x + 7] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 7] & OBJ_PRIO_MASK]]; } if (softwareRenderer->model & GB_MODEL_SGB) { p = softwareRenderer->d.sgbAttributes[(x >> 5) + 5 * (y >> 3)]; @@ -608,7 +658,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i p <<= 2; } for (; x < endX; ++x) { - row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & 0x7F]]; + row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & OBJ_PRIO_MASK]]; } break; case 1: @@ -769,7 +819,7 @@ static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* rende } } -static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int sx, int sy) { +static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int sx, int sy, bool highlight) { uint8_t* data = renderer->d.vram; uint8_t* attr = &maps[GB_SIZE_VRAM_BANK0]; if (!GBRegisterLCDCIsTileData(renderer->lcdc)) { @@ -794,12 +844,12 @@ static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer } else { bgTile = ((int8_t*) maps)[topX + topY]; } - int p = 0; + int p = highlight ? PAL_HIGHLIGHT_BG : PAL_BG; if (renderer->model >= GB_MODEL_CGB) { GBObjAttributes attrs = attr[topX + topY]; - p = GBObjAttributesGetCGBPalette(attrs) * 4; + p |= GBObjAttributesGetCGBPalette(attrs) * 4; if (GBObjAttributesIsPriority(attrs) && GBRegisterLCDCIsBgEnable(renderer->lcdc)) { - p |= 0x80; + p |= OBJ_PRIORITY; } if (GBObjAttributesIsBank(attrs)) { localData += GB_SIZE_VRAM_BANK0; @@ -829,12 +879,12 @@ static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer } else { bgTile = ((int8_t*) maps)[topX + topY]; } - int p = 0; + int p = highlight ? PAL_HIGHLIGHT_BG : PAL_BG; if (renderer->model >= GB_MODEL_CGB) { GBObjAttributes attrs = attr[topX + topY]; - p = GBObjAttributesGetCGBPalette(attrs) * 4; + p |= GBObjAttributesGetCGBPalette(attrs) * 4; if (GBObjAttributesIsPriority(attrs) && GBRegisterLCDCIsBgEnable(renderer->lcdc)) { - p |= 0x80; + p |= OBJ_PRIORITY; } if (GBObjAttributesIsBank(attrs)) { localData += GB_SIZE_VRAM_BANK0; @@ -869,8 +919,8 @@ static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer } } -static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y) { - int objX = obj->x + renderer->objOffsetX; +static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBVideoRendererSprite* obj, int startX, int endX, int y) { + int objX = obj->obj.x + renderer->objOffsetX; int ix = objX - 8; if (endX < ix || startX >= ix + 8) { return; @@ -887,8 +937,8 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende uint8_t* data = renderer->d.vram; int tileOffset = 0; int bottomY; - int objY = obj->y + renderer->objOffsetY; - if (GBObjAttributesIsYFlip(obj->attr)) { + int objY = obj->obj.y + renderer->objOffsetY; + if (GBObjAttributesIsYFlip(obj->obj.attr)) { bottomY = 7 - ((y - objY - 16) & 7); if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - objY < -8) { ++tileOffset; @@ -899,115 +949,113 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende ++tileOffset; } } - if (GBRegisterLCDCIsObjSize(renderer->lcdc) && obj->tile & 1) { + if (GBRegisterLCDCIsObjSize(renderer->lcdc) && obj->obj.tile & 1) { --tileOffset; } - uint8_t mask = GBObjAttributesIsPriority(obj->attr) ? 0x63 : 0x60; - uint8_t mask2 = GBObjAttributesIsPriority(obj->attr) ? 0 : 0x83; - int p; + unsigned mask = GBObjAttributesIsPriority(obj->obj.attr) ? 0x63 : 0x60; + unsigned mask2 = GBObjAttributesIsPriority(obj->obj.attr) ? 0 : (OBJ_PRIORITY | 3); + int p = renderer->d.highlightOBJ[obj->index] ? PAL_HIGHLIGHT_OBJ : PAL_OBJ; if (renderer->model >= GB_MODEL_CGB) { - p = (GBObjAttributesGetCGBPalette(obj->attr) + 8) * 4; - if (GBObjAttributesIsBank(obj->attr)) { + p |= GBObjAttributesGetCGBPalette(obj->obj.attr) * 4; + if (GBObjAttributesIsBank(obj->obj.attr)) { data += GB_SIZE_VRAM_BANK0; } if (!GBRegisterLCDCIsBgEnable(renderer->lcdc)) { mask = 0x60; - mask2 = 0x83; + mask2 = OBJ_PRIORITY | 3; } } else { - p = (GBObjAttributesGetPalette(obj->attr) + 8) * 4; + p |= (GBObjAttributesGetPalette(obj->obj.attr) + 8) * 4; } int bottomX; int x = startX; + int objTile = obj->obj.tile + tileOffset; if ((x - objX) & 7) { for (; x < endX; ++x) { - if (GBObjAttributesIsXFlip(obj->attr)) { + if (GBObjAttributesIsXFlip(obj->obj.attr)) { bottomX = (x - objX) & 7; } else { bottomX = 7 - ((x - objX) & 7); } - int objTile = obj->tile + tileOffset; uint8_t tileDataLower = data[(objTile * 8 + bottomY) * 2]; uint8_t tileDataUpper = data[(objTile * 8 + bottomY) * 2 + 1]; tileDataUpper >>= bottomX; tileDataLower >>= bottomX; - color_t current = renderer->row[x]; - if (((tileDataUpper | tileDataLower) & 1) && !(current & mask) && (current & mask2) <= 0x80) { + unsigned current = renderer->row[x]; + if (((tileDataUpper | tileDataLower) & 1) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x] = p | ((tileDataUpper & 1) << 1) | (tileDataLower & 1); } } - } else if (GBObjAttributesIsXFlip(obj->attr)) { - int objTile = obj->tile + tileOffset; + } else if (GBObjAttributesIsXFlip(obj->obj.attr)) { uint8_t tileDataLower = data[(objTile * 8 + bottomY) * 2]; uint8_t tileDataUpper = data[(objTile * 8 + bottomY) * 2 + 1]; - color_t current; + unsigned current; current = renderer->row[x]; - if (((tileDataUpper | tileDataLower) & 1) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 1) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x] = p | ((tileDataUpper & 1) << 1) | (tileDataLower & 1); } current = renderer->row[x + 1]; - if (((tileDataUpper | tileDataLower) & 2) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 2) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 1] = p | (tileDataUpper & 2) | ((tileDataLower & 2) >> 1); } current = renderer->row[x + 2]; - if (((tileDataUpper | tileDataLower) & 4) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 4) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 2] = p | ((tileDataUpper & 4) >> 1) | ((tileDataLower & 4) >> 2); } current = renderer->row[x + 3]; - if (((tileDataUpper | tileDataLower) & 8) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 8) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 3] = p | ((tileDataUpper & 8) >> 2) | ((tileDataLower & 8) >> 3); } current = renderer->row[x + 4]; - if (((tileDataUpper | tileDataLower) & 16) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 16) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 4] = p | ((tileDataUpper & 16) >> 3) | ((tileDataLower & 16) >> 4); } current = renderer->row[x + 5]; - if (((tileDataUpper | tileDataLower) & 32) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 32) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 5] = p | ((tileDataUpper & 32) >> 4) | ((tileDataLower & 32) >> 5); } current = renderer->row[x + 6]; - if (((tileDataUpper | tileDataLower) & 64) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 64) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 6] = p | ((tileDataUpper & 64) >> 5) | ((tileDataLower & 64) >> 6); } current = renderer->row[x + 7]; - if (((tileDataUpper | tileDataLower) & 128) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 128) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 7] = p | ((tileDataUpper & 128) >> 6) | ((tileDataLower & 128) >> 7); } } else { - int objTile = obj->tile + tileOffset; uint8_t tileDataLower = data[(objTile * 8 + bottomY) * 2]; uint8_t tileDataUpper = data[(objTile * 8 + bottomY) * 2 + 1]; - color_t current; + unsigned current; current = renderer->row[x + 7]; - if (((tileDataUpper | tileDataLower) & 1) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 1) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 7] = p | ((tileDataUpper & 1) << 1) | (tileDataLower & 1); } current = renderer->row[x + 6]; - if (((tileDataUpper | tileDataLower) & 2) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 2) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 6] = p | (tileDataUpper & 2) | ((tileDataLower & 2) >> 1); } current = renderer->row[x + 5]; - if (((tileDataUpper | tileDataLower) & 4) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 4) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 5] = p | ((tileDataUpper & 4) >> 1) | ((tileDataLower & 4) >> 2); } current = renderer->row[x + 4]; - if (((tileDataUpper | tileDataLower) & 8) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 8) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 4] = p | ((tileDataUpper & 8) >> 2) | ((tileDataLower & 8) >> 3); } current = renderer->row[x + 3]; - if (((tileDataUpper | tileDataLower) & 16) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 16) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 3] = p | ((tileDataUpper & 16) >> 3) | ((tileDataLower & 16) >> 4); } current = renderer->row[x + 2]; - if (((tileDataUpper | tileDataLower) & 32) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 32) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 2] = p | ((tileDataUpper & 32) >> 4) | ((tileDataLower & 32) >> 5); } current = renderer->row[x + 1]; - if (((tileDataUpper | tileDataLower) & 64) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 64) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x + 1] = p | ((tileDataUpper & 64) >> 5) | ((tileDataLower & 64) >> 6); } current = renderer->row[x]; - if (((tileDataUpper | tileDataLower) & 128) && !(current & mask) && (current & mask2) <= 0x80) { + if (((tileDataUpper | tileDataLower) & 128) && !(current & mask) && (current & mask2) <= OBJ_PRIORITY) { renderer->row[x] = p | ((tileDataUpper & 128) >> 6) | ((tileDataLower & 128) >> 7); } } diff --git a/src/platform/qt/FrameView.cpp b/src/platform/qt/FrameView.cpp index f15c7ff37..05fbffbdb 100644 --- a/src/platform/qt/FrameView.cpp +++ b/src/platform/qt/FrameView.cpp @@ -370,6 +370,15 @@ void FrameView::updateTilesGB(bool) { void FrameView::injectGB() { mVideoLogger* logger = m_vl->videoLogger; + GB* gb = static_cast(m_vl->board); + gb->video.renderer->highlightBG = false; + gb->video.renderer->highlightWIN = false; + for (int i = 0; i < 40; ++i) { + gb->video.renderer->highlightOBJ[i] = false; + } + QPalette palette; + gb->video.renderer->highlightColor = M_RGB8_TO_NATIVE(palette.color(QPalette::Highlight).rgb()); + gb->video.renderer->highlightAmount = sin(m_glowFrame * M_PI / 30) * 48 + 64; m_vl->reset(m_vl); for (const Layer& layer : m_queue) { @@ -378,12 +387,21 @@ void FrameView::injectGB() { if (!layer.enabled) { mVideoLoggerInjectOAM(logger, layer.id.index << 2, 0); } + if (layer.id == m_active) { + gb->video.renderer->highlightOBJ[layer.id.index] = true; + } break; case LayerId::BACKGROUND: m_vl->enableVideoLayer(m_vl, GB_LAYER_BACKGROUND, layer.enabled); + if (layer.id == m_active) { + gb->video.renderer->highlightBG = true; + } break; case LayerId::WINDOW: m_vl->enableVideoLayer(m_vl, GB_LAYER_WINDOW, layer.enabled); + if (layer.id == m_active) { + gb->video.renderer->highlightWIN = true; + } break; } } From 1e76ae31d62931c2c2d1aaa07741dda926d27b46 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Nov 2020 23:42:00 -0800 Subject: [PATCH 07/20] CHANGES: Update --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 39907c7f5..5d1a88f04 100644 --- a/CHANGES +++ b/CHANGES @@ -37,6 +37,7 @@ Emulation fixes: - GBA Memory: Stall on VRAM access in mode 2 (fixes mgba.io/i/190) - GBA Memory: Improve robustness of Matrix memory support - GBA Memory: Mark Famicom Mini games 22 through 28 as non-mirroring + - GBA Memory: Return correct byte for odd ROM open bus addresses - GBA SIO: Fix copying Normal mode transfer values - GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800) - GBA SIO: Fix deseralizing SIO registers From 9902e2eeeed324eecf813b4dd93ceafc03fc6ae7 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Nov 2020 00:46:55 -0800 Subject: [PATCH 08/20] GBA Video: Fix OBJWIN erratic rendering in OpenGL renderer --- CHANGES | 1 + src/gba/renderers/gl.c | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 5d1a88f04..87c409fed 100644 --- a/CHANGES +++ b/CHANGES @@ -45,6 +45,7 @@ Emulation fixes: - GBA Video: Fix Hblank timing - GBA Video: Implement green swap (fixes mgba.io/i/1609) - GBA Video: Emulate sprite cycle limits in OpenGL renderer (fixes mgba.io/i/1635) + - GBA Video: Fix OBJWIN erratic rendering in OpenGL renderer - SM83: Emulate HALT bug Other fixes: - 3DS: Fix thread cleanup diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index 31c16f5cd..07b034680 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -426,7 +426,7 @@ static const char* const _renderObj = "uniform ivec4 inflags;\n" "uniform mat2x2 transform;\n" "uniform ivec4 dims;\n" - "uniform ivec4 objwin;\n" + "uniform ivec3 objwin;\n" "uniform ivec4 mosaic;\n" "uniform int cyclesRemaining[160];\n" "OUT(0) out vec4 color;\n" @@ -459,7 +459,7 @@ static const char* const _renderObj = " color = pix;\n" " flags = inflags;\n" " gl_FragDepth = float(flags.x) / 16.;\n" - " window = ivec4(objwin.yzw, 0);\n" + " window = ivec4(objwin, 0);\n" "}"; static const struct GBAVideoGLUniform _uniformsObjPriority[] = { @@ -1428,7 +1428,6 @@ void _drawScanlines(struct GBAVideoGLRenderer* glRenderer, int y) { GBAVideoGLRendererDrawWindow(glRenderer, y); if (GBARegisterDISPCNTIsObjEnable(glRenderer->dispcnt) && !glRenderer->d.disableOBJ) { glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glEnable(GL_STENCIL_TEST); glDepthFunc(GL_LESS); for (i = 0; i < glRenderer->oamMax; ++i) { struct GBAVideoRendererSprite* sprite = &glRenderer->sprites[i]; @@ -1716,20 +1715,21 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB glUniformMatrix2fv(uniforms[GBA_GL_OBJ_TRANSFORM], 1, GL_FALSE, (GLfloat[]) { flipX, 0, 0, flipY }); } glUniform4i(uniforms[GBA_GL_OBJ_DIMS], width, height, totalWidth, totalHeight); + glDisable(GL_STENCIL_TEST); if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN) { // OBJWIN writes do not affect pixel priority glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glStencilMask(GL_FALSE); int window = renderer->objwin & 0x3F; - glUniform4i(uniforms[GBA_GL_OBJ_OBJWIN], 1, window, renderer->bldb, renderer->bldy); + glUniform3i(uniforms[GBA_GL_OBJ_OBJWIN], window, renderer->bldb, renderer->bldy); glDrawBuffers(3, (GLenum[]) { GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2 }); } else { glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glStencilMask(GL_TRUE); glStencilFunc(GL_ALWAYS, 1, 1); - glUniform4i(uniforms[GBA_GL_OBJ_OBJWIN], 0, 0, 0, 0); + glUniform3i(uniforms[GBA_GL_OBJ_OBJWIN], 0, 0, 0); glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }); } if (GBAObjAttributesAIsMosaic(sprite->a) && GBAObjAttributesAGetMode(sprite->a) != OBJ_MODE_OBJWIN) { @@ -1749,6 +1749,7 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB // Update the pixel priority for already-written pixels shader = &renderer->objShader[2]; uniforms = shader->uniforms; + glEnable(GL_STENCIL_TEST); glStencilFunc(GL_EQUAL, 1, 1); glUseProgram(shader->program); glDrawBuffers(2, (GLenum[]) { GL_NONE, GL_COLOR_ATTACHMENT1 }); From 2f5fb2265992581712525dad2b47fcad0a5c0372 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Nov 2020 01:03:10 -0800 Subject: [PATCH 09/20] GBA: Remove Pokemon Pinball R/S override --- src/gba/overrides.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/gba/overrides.c b/src/gba/overrides.c index 551b189b5..bfb52e093 100644 --- a/src/gba/overrides.c +++ b/src/gba/overrides.c @@ -87,12 +87,6 @@ static const struct GBACartridgeOverride _overrides[] = { // Metal Slug Advance { "BSME", SAVEDATA_EEPROM, HW_NONE, 0x8000290, false }, - // Pokemon Pinball: Ruby & Sapphire - { "BPPJ", SAVEDATA_SRAM, HW_GB_PLAYER_DETECTION, IDLE_LOOP_NONE, false }, - { "BPPE", SAVEDATA_SRAM, HW_GB_PLAYER_DETECTION, IDLE_LOOP_NONE, false }, - { "BPPP", SAVEDATA_SRAM, HW_GB_PLAYER_DETECTION, IDLE_LOOP_NONE, false }, - { "BPPU", SAVEDATA_SRAM, HW_GB_PLAYER_DETECTION, IDLE_LOOP_NONE, false }, - // Pokemon Ruby { "AXVJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, { "AXVE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, From 1093849ad5f6103d8eb1817e9b913255a3218eb9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Nov 2020 01:11:24 -0800 Subject: [PATCH 10/20] Qt: Add option to toggle forceGbp mode --- CHANGES | 1 + src/platform/qt/SettingsView.cpp | 2 ++ src/platform/qt/SettingsView.ui | 27 +++++++++++++++++---------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 87c409fed..d322f1aca 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ Features: - e-Reader card scanning - WebP and APNG recording - Separate overrides for GBC games that can also run on SGB or regular GB + - Game Boy Player features can be enabled by default for all compatible games - Mute option in homebrew ports - Status indicators for fast-forward and mute in homebrew ports - Read-only support for MBC6 flash memory diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 3f1e57010..01123a3c0 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -418,6 +418,7 @@ void SettingsView::updateConfig() { saveSetting("gba.audioHle", m_ui.audioHle); saveSetting("dynamicTitle", m_ui.dynamicTitle); saveSetting("videoScale", m_ui.videoScale); + saveSetting("gba.forceGbp", m_ui.forceGbp); if (m_ui.audioBufferSize->currentText().toInt() > 8192) { m_ui.audioBufferSize->setCurrentText("8192"); @@ -607,6 +608,7 @@ void SettingsView::reloadConfig() { loadSetting("useDiscordPresence", m_ui.useDiscordPresence); loadSetting("gba.audioHle", m_ui.audioHle); loadSetting("dynamicTitle", m_ui.dynamicTitle); + loadSetting("gba.forceGbp", m_ui.forceGbp); m_ui.libraryStyle->setCurrentIndex(loadSetting("libraryStyle").toInt()); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 46ab4861e..fba6a4bb2 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -873,21 +873,21 @@ - + Qt::Horizontal - + Savestate extra data: - + Screenshot @@ -897,7 +897,7 @@ - + Save data @@ -907,7 +907,7 @@ - + Cheat codes @@ -917,21 +917,21 @@ - + Qt::Horizontal - + Load extra data: - + Screenshot @@ -941,20 +941,27 @@ - + Save data - + Cheat codes + + + + Enable Game Boy Player features by default + + + From 513c97d6cdd67de22ebe60876b4e43b55e796521 Mon Sep 17 00:00:00 2001 From: Lothar Serra Mari Date: Sun, 22 Nov 2020 11:06:07 +0100 Subject: [PATCH 11/20] Qt: Update German GUI translation --- src/platform/qt/ts/mgba-de.ts | 182 ++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 88 deletions(-) diff --git a/src/platform/qt/ts/mgba-de.ts b/src/platform/qt/ts/mgba-de.ts index 9dd4defa7..ccdab6c83 100644 --- a/src/platform/qt/ts/mgba-de.ts +++ b/src/platform/qt/ts/mgba-de.ts @@ -306,8 +306,8 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.GIFView - Record GIF/APNG - GIF/APNG aufzeichnen + Record GIF/WebP/APNG + GIF/WebP/APNG aufzeichnen @@ -1392,22 +1392,22 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::CoreController - + Failed to open save file: %1 Fehler beim Öffnen der Speicherdatei: %1 - + Failed to open game file: %1 Fehler beim Öffnen der Spieldatei: %1 - + Failed to open snapshot file for reading: %1 Konnte Snapshot-Datei %1 nicht zum Lesen öffnen - + Failed to open snapshot file for writing: %1 Konnte Snapshot-Datei %1 nicht zum Schreiben öffnen @@ -1433,52 +1433,52 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::FrameView - + Export frame Bild exportieren - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Keine - + Background Hintergrund - + Window Fenster - + Objwin Objwin - + Sprite Sprite - + Backdrop Hintergrund - + Frame Frame - + %1 %2 %1 %2 @@ -1494,22 +1494,22 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::GBAKeyEditor - + Clear Button Button löschen - + Clear Analog Analog löschen - + Refresh Aktualisieren - + Set all Alle belegen @@ -3236,12 +3236,12 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.Fehler beim Laden der Eingabedatei: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3249,22 +3249,22 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::MemorySearch - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 byte%2 @@ -3655,12 +3655,12 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.Video-Logs (*.mvl) - + Crash Absturz - + The game has crashed with the following error: %1 @@ -3669,52 +3669,52 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. - + Unimplemented BIOS call Nicht implementierter BIOS-Aufruf - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Dieses Spiel verwendet einen BIOS-Aufruf, der nicht implementiert ist. Bitte verwenden Sie für die beste Spielerfahrung das offizielle BIOS. - + Really make portable? Portablen Modus wirklich aktivieren? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Diese Einstellung wird den Emulator so konfigurieren, dass er seine Konfiguration aus dem gleichen Verzeichnis wie die Programmdatei lädt. Möchten Sie fortfahren? - + Restart needed Neustart benötigt - + Some changes will not take effect until the emulator is restarted. Einige Änderungen werden erst übernommen, wenn der Emulator neu gestartet wurde. - + - Player %1 of %2 - Spieler %1 von %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 Bilder/Sekunde) - %4 @@ -4090,12 +4090,12 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.e-Reader-Karte (*.raw *.bin *.bmp) - + Couldn't Start Konnte nicht gestartet werden - + Could not start game. Spiel konnte nicht gestartet werden. @@ -4682,7 +4682,13 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.Bildwiederholrate in der Titelleiste anzeigen - + + Enable Game Boy Player features by default + Game Boy Player-Features +standardmäßig aktivieren + + + Super Game Boy/Game Boy Color model: Super Game Boy/Game Boy Color-Modell: @@ -4733,107 +4739,107 @@ Titelleiste anzeigen Vorlauf-Geschwindigkeit (halten): - + Video renderer: Video-Renderer: - + Software Software - + OpenGL OpenGL - + OpenGL enhancements OpenGL-Verbesserungen - + High-resolution scale: Hochauflösende Skalierung: - + XQ GBA audio (experimental) XQ GBA-Audio (experimentell) - + Cheats Cheats - + Log to file In Datei protokollieren - + Log to console Auf die Konsole protokollieren - + Select Log File Protokoll-Datei auswählen - + Game Boy-only model: Game Boy-Modell: - + Game Boy Color-only model: Game Boy Color-Modell: - + Game Boy/Game Boy Color model: Game Boy/Game Boy Color-Modell: - + Camera: Kamera: - + Default BG colors: Standard-Hintergrundfarben: - + Default sprite colors 1: Standard-Sprite-Farben 1: - + Default sprite colors 2: Standard-Sprite-Farben 2: - + Use GBC colors in GB games Verwende GBC-Farben in GB-Spielen - + Super Game Boy borders Super Game Boy-Rahmen - + Super Game Boy model: Super Game Boy-Modell: - + Camera driver: Kamera-Treiber: @@ -4864,33 +4870,33 @@ Titelleiste anzeigen in Arbeitsspeicher vorladen - - - - - - - - - + + + + + + + + + Browse Durchsuchen - + Use BIOS file if found BIOS-Datei verwenden, wenn vorhanden - + Skip BIOS intro BIOS-Intro überspringen - + × × @@ -4989,56 +4995,56 @@ wenn vorhanden Autofeuer-Intervall: - + (240×160) (240×160) - + GB BIOS file: Datei mit GB-BIOS: - + GBA BIOS file: Datei mit GBA-BIOS: - + GBC BIOS file: Datei mit GBC-BIOS: - + SGB BIOS file: Datei mit SGB-BIOS: - + Save games Spielstände - - - - - + + + + + Same directory as the ROM Verzeichnis der ROM-Datei - + Save states Savestates - + Screenshots Screenshots - + Patches Patches From 19e73dae1c173be2d19b54552d49d8032caf5e96 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Nov 2020 03:16:34 -0800 Subject: [PATCH 12/20] GBA Video: Minor cleanup --- src/gba/renderers/gl.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index 07b034680..cdcd4feb7 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -677,7 +677,7 @@ void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer) { for (i = 0; i < 128; ++i) { renderer->d.highlightOBJ[i] = false; } - renderer->d.highlightColor = 0xFFFFFF; + renderer->d.highlightColor = M_COLOR_WHITE; renderer->d.highlightAmount = 0; renderer->scale = 1; @@ -735,7 +735,7 @@ static void _initFramebufferTextureEx(GLuint tex, GLenum internalFormat, GLenum glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, scale > 0 ? GBA_VIDEO_HORIZONTAL_PIXELS * scale : 8, GBA_VIDEO_VERTICAL_PIXELS * (scale > 0 ? scale : 1), 0, format, type, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0); } static void _initFramebufferTexture(GLuint tex, GLenum format, GLenum attachment, int scale) { @@ -754,7 +754,7 @@ static void _initFramebuffers(struct GBAVideoGLRenderer* glRenderer) { _initFramebufferTextureEx(glRenderer->layers[GBA_GL_TEX_BACKDROP_FLAGS], GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, GL_COLOR_ATTACHMENT1, 0); glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_WINDOW]); - _initFramebufferTextureEx(glRenderer->layers[GBA_GL_TEX_WINDOW], GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, GL_COLOR_ATTACHMENT0, glRenderer->scale); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glRenderer->layers[GBA_GL_TEX_WINDOW], 0); glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_OUTPUT]); _initFramebufferTexture(glRenderer->outputTex, GL_RGB, GL_COLOR_ATTACHMENT0, glRenderer->scale); @@ -1416,13 +1416,12 @@ void _drawScanlines(struct GBAVideoGLRenderer* glRenderer, int y) { glDrawBuffers(2, (GLenum[]) { GL_NONE, GL_COLOR_ATTACHMENT1 }); int i; for (i = 0; i < 4; ++i) { - glScissor(i + 1, glRenderer->firstY, i + 2, y - glRenderer->firstY + 1); + glScissor(i + 1, glRenderer->firstY, 1, y - glRenderer->firstY + 1); glClearBufferiv(GL_COLOR, 1, (GLint[]) { glRenderer->bg[i].priority, glRenderer->bg[i].target1 | (glRenderer->bg[i].target2 << 1) | (glRenderer->blendEffect << 2), glRenderer->blda, 0 }); } - glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 }); GBAVideoGLRendererDrawWindow(glRenderer, y); @@ -1720,14 +1719,14 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB // OBJWIN writes do not affect pixel priority glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - glStencilMask(GL_FALSE); + glStencilMask(0); int window = renderer->objwin & 0x3F; glUniform3i(uniforms[GBA_GL_OBJ_OBJWIN], window, renderer->bldb, renderer->bldy); glDrawBuffers(3, (GLenum[]) { GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2 }); } else { glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); - glStencilMask(GL_TRUE); + glStencilMask(1); glStencilFunc(GL_ALWAYS, 1, 1); glUniform3i(uniforms[GBA_GL_OBJ_OBJWIN], 0, 0, 0); glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }); From 13c36a54f1c1bffc9903dc9087f535eb184d1827 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Nov 2020 03:58:12 -0800 Subject: [PATCH 13/20] GBA Video: Only use shader for setting window params if a clear is insufficient --- src/gba/renderers/gl.c | 53 ++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index cdcd4feb7..8d2742eb8 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -533,20 +533,15 @@ static const char* const _renderWindow = "}\n" "void main() {\n" - " int dispflags = (dispcnt & 0x1F) | 0x20;\n" - " if ((dispcnt & 0xE0) == 0) {\n" - " window = ivec4(dispflags, blend, 0);\n" - " } else {\n" - " ivec4 windowFlags = ivec4(flags.z, blend, 0);\n" - " int top = int(texCoord.y);\n" - " int bottom = max(top - 1, 0);\n" - " if ((dispcnt & 0x20) != 0 && crop(interpolate(vec4(win0[top]), vec4(win0[bottom])))) { \n" - " windowFlags.x = flags.x;\n" - " } else if ((dispcnt & 0x40) != 0 && crop(interpolate(vec4(win1[top]), vec4(win1[bottom])))) {\n" - " windowFlags.x = flags.y;\n" - " }\n" - " window = windowFlags;\n" + " ivec4 windowFlags = ivec4(flags.z, blend, 0);\n" + " int top = int(texCoord.y);\n" + " int bottom = max(top - 1, 0);\n" + " if ((dispcnt & 0x20) != 0 && crop(interpolate(vec4(win0[top]), vec4(win0[bottom])))) { \n" + " windowFlags.x = flags.x;\n" + " } else if ((dispcnt & 0x40) != 0 && crop(interpolate(vec4(win1[top]), vec4(win1[bottom])))) {\n" + " windowFlags.x = flags.y;\n" " }\n" + " window = windowFlags;\n" "}\n"; static const struct GBAVideoGLUniform _uniformsFinalize[] = { @@ -1868,17 +1863,29 @@ void GBAVideoGLRendererDrawWindow(struct GBAVideoGLRenderer* renderer, int y) { glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_WINDOW]); glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale); glScissor(0, renderer->firstY * renderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, renderer->scale * (y - renderer->firstY + 1)); - glUseProgram(shader->program); - glBindVertexArray(shader->vao); - glUniform2i(uniforms[GBA_GL_VS_LOC], y - renderer->firstY + 1, renderer->firstY); - glUniform2i(uniforms[GBA_GL_VS_MAXPOS], GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS); - glUniform1i(uniforms[GBA_GL_WIN_DISPCNT], renderer->dispcnt >> 8); - glUniform2i(uniforms[GBA_GL_WIN_BLEND], renderer->bldb, renderer->bldy); - glUniform3i(uniforms[GBA_GL_WIN_FLAGS], renderer->winN[0].control, renderer->winN[1].control, renderer->winout); - glUniform4iv(uniforms[GBA_GL_WIN_WIN0], GBA_VIDEO_VERTICAL_PIXELS, renderer->winNHistory[0]); - glUniform4iv(uniforms[GBA_GL_WIN_WIN1], GBA_VIDEO_VERTICAL_PIXELS, renderer->winNHistory[1]); glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 }); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + switch (renderer->dispcnt & 0xE000) { + case 0x0000: + // No windows are enabled + glClearBufferiv(GL_COLOR, 0, (GLint[]) { ((renderer->dispcnt >> 8) & 0x1F) | 0x20, renderer->bldb, renderer->bldy, 0 }); + break; + case 0x8000: + // Only OBJWIN is enabled + glClearBufferiv(GL_COLOR, 0, (GLint[]) { renderer->winout, renderer->bldb, renderer->bldy, 0 }); + break; + default: + glUseProgram(shader->program); + glBindVertexArray(shader->vao); + glUniform2i(uniforms[GBA_GL_VS_LOC], y - renderer->firstY + 1, renderer->firstY); + glUniform2i(uniforms[GBA_GL_VS_MAXPOS], GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS); + glUniform1i(uniforms[GBA_GL_WIN_DISPCNT], renderer->dispcnt >> 8); + glUniform2i(uniforms[GBA_GL_WIN_BLEND], renderer->bldb, renderer->bldy); + glUniform3i(uniforms[GBA_GL_WIN_FLAGS], renderer->winN[0].control, renderer->winN[1].control, renderer->winout); + glUniform4iv(uniforms[GBA_GL_WIN_WIN0], GBA_VIDEO_VERTICAL_PIXELS, renderer->winNHistory[0]); + glUniform4iv(uniforms[GBA_GL_WIN_WIN1], GBA_VIDEO_VERTICAL_PIXELS, renderer->winNHistory[1]); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + break; + } } void GBAVideoGLRendererSetScale(struct GBAVideoGLRenderer* renderer, int scale) { From 7918b5af453872dd1d7ea04ece0248bf787904ec Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Nov 2020 15:08:45 -0800 Subject: [PATCH 14/20] GB Video: Fix SGB video logs --- CHANGES | 1 + include/mgba/internal/gb/serialize.h | 3 +++ src/gb/core.c | 3 +++ src/gb/extra/proxy.c | 6 ++++++ src/gb/serialize.c | 3 --- 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index d322f1aca..e1764c314 100644 --- a/CHANGES +++ b/CHANGES @@ -58,6 +58,7 @@ Other fixes: - Debugger: Close trace log when done tracing - FFmpeg: Fix some small memory leaks - FFmpeg: Fix encoding of time base + - GB Video: Fix SGB video logs - mGUI: Don't attempt to preload files larger than can fit in RAM - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Fix static compilation in MinGW (fixes mgba.io/i/1769) diff --git a/include/mgba/internal/gb/serialize.h b/include/mgba/internal/gb/serialize.h index c7d1532be..b3cde1661 100644 --- a/include/mgba/internal/gb/serialize.h +++ b/include/mgba/internal/gb/serialize.h @@ -437,6 +437,9 @@ struct GBSerializedState { bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state); void GBSerialize(struct GB* gb, struct GBSerializedState* state); +void GBSGBSerialize(struct GB* gb, struct GBSerializedState* state); +void GBSGBDeserialize(struct GB* gb, const struct GBSerializedState* state); + CXX_GUARD_END #endif diff --git a/src/gb/core.c b/src/gb/core.c index cddd3104f..f0dbac0ba 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -1163,6 +1163,9 @@ static bool _GBVLPLoadState(struct mCore* core, const void* buffer) { GBVideoDeserialize(&gb->video, state); GBIODeserialize(gb, state); GBAudioReset(&gb->audio); + if (gb->model & GB_MODEL_SGB) { + GBSGBDeserialize(gb, state); + } // Make sure CPU loop never spins gb->memory.ie = 0; diff --git a/src/gb/extra/proxy.c b/src/gb/extra/proxy.c index 29be8af49..cea273692 100644 --- a/src/gb/extra/proxy.c +++ b/src/gb/extra/proxy.c @@ -102,6 +102,12 @@ void GBVideoProxyRendererShim(struct GBVideo* video, struct GBVideoProxyRenderer renderer->backend = video->renderer; video->renderer = &renderer->d; renderer->d.cache = renderer->backend->cache; + renderer->d.sgbRenderMode = renderer->backend->sgbRenderMode; + renderer->d.sgbCharRam = renderer->backend->sgbCharRam; + renderer->d.sgbMapRam = renderer->backend->sgbMapRam; + renderer->d.sgbPalRam = renderer->backend->sgbPalRam; + renderer->d.sgbAttributeFiles = renderer->backend->sgbAttributeFiles; + renderer->d.sgbAttributes = renderer->backend->sgbAttributes; renderer->d.vram = video->vram; renderer->d.oam = &video->oam; _init(renderer); diff --git a/src/gb/serialize.c b/src/gb/serialize.c index 04060d641..056d1fd77 100644 --- a/src/gb/serialize.c +++ b/src/gb/serialize.c @@ -16,9 +16,6 @@ mLOG_DEFINE_CATEGORY(GB_STATE, "GB Savestate", "gb.serialize"); const uint32_t GB_SAVESTATE_MAGIC = 0x00400000; const uint32_t GB_SAVESTATE_VERSION = 0x00000002; -static void GBSGBSerialize(struct GB* gb, struct GBSerializedState* state); -static void GBSGBDeserialize(struct GB* gb, const struct GBSerializedState* state); - void GBSerialize(struct GB* gb, struct GBSerializedState* state) { STORE_32LE(GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION, 0, &state->versionMagic); STORE_32LE(gb->romCrc32, 0, &state->romCrc32); From 45e0ce8e27994ed66e696ea7a67628c4aeb40a98 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Nov 2020 15:36:21 -0800 Subject: [PATCH 15/20] GB Video: Fix highlighting after modifying GB palettes --- src/gb/renderers/software.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index 6f3610eee..f90d8d674 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -300,30 +300,30 @@ static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* softwareRenderer->lookup[1] = (value >> 2) & 3; softwareRenderer->lookup[2] = (value >> 4) & 3; softwareRenderer->lookup[3] = (value >> 6) & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 0] = value & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 1] = (value >> 2) & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 2] = (value >> 4) & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 3] = (value >> 6) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 0] = PAL_HIGHLIGHT + (value & 3); + softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 1] = PAL_HIGHLIGHT + ((value >> 2) & 3); + softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 2] = PAL_HIGHLIGHT + ((value >> 4) & 3); + softwareRenderer->lookup[PAL_HIGHLIGHT_BG + 3] = PAL_HIGHLIGHT + ((value >> 6) & 3); break; case GB_REG_OBP0: softwareRenderer->lookup[PAL_OBJ + 0] = value & 3; softwareRenderer->lookup[PAL_OBJ + 1] = (value >> 2) & 3; softwareRenderer->lookup[PAL_OBJ + 2] = (value >> 4) & 3; softwareRenderer->lookup[PAL_OBJ + 3] = (value >> 6) & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 0] = value & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 1] = (value >> 2) & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 2] = (value >> 4) & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 3] = (value >> 6) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 0] = PAL_HIGHLIGHT + (value & 3); + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 1] = PAL_HIGHLIGHT + ((value >> 2) & 3); + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 2] = PAL_HIGHLIGHT + ((value >> 4) & 3); + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 3] = PAL_HIGHLIGHT + ((value >> 6) & 3); break; case GB_REG_OBP1: softwareRenderer->lookup[PAL_OBJ + 4] = value & 3; softwareRenderer->lookup[PAL_OBJ + 5] = (value >> 2) & 3; softwareRenderer->lookup[PAL_OBJ + 6] = (value >> 4) & 3; softwareRenderer->lookup[PAL_OBJ + 7] = (value >> 6) & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 4] = value & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 5] = (value >> 2) & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 6] = (value >> 4) & 3; - softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 7] = (value >> 6) & 3; + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 4] = PAL_HIGHLIGHT + (value & 3); + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 5] = PAL_HIGHLIGHT + ((value >> 2) & 3); + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 6] = PAL_HIGHLIGHT + ((value >> 4) & 3); + softwareRenderer->lookup[PAL_HIGHLIGHT_OBJ + 7] = PAL_HIGHLIGHT + ((value >> 6) & 3); break; } return value; From e9ed09e9beeee9e8b35f50b568b0c6bdab45b636 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Nov 2020 15:47:56 -0800 Subject: [PATCH 16/20] Qt: Allow frame viewer on Game Boy --- CHANGES | 3 ++- src/platform/qt/Window.cpp | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index e1764c314..57a9b957b 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ Features: - WebP and APNG recording - Separate overrides for GBC games that can also run on SGB or regular GB - Game Boy Player features can be enabled by default for all compatible games + - Frame viewer support for Game Boy - Mute option in homebrew ports - Status indicators for fast-forward and mute in homebrew ports - Read-only support for MBC6 flash memory @@ -12,7 +13,7 @@ Features: - Command scripts for CLI debugger (by ahigerd) - ARM disassembler now resolves addresses to symbol names - Add Game Boy Player feature support to ports - - Individual window types can now be toggled in GBA debugging views + - Individual window types can now be toggled in debugging views Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index efa7df30e..78688b4a5 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1504,7 +1504,6 @@ void Window::setupMenu(QMenuBar* menubar) { addGameAction(tr("View &tiles..."), "tileWindow", openControllerTView(), "tools"); addGameAction(tr("View &map..."), "mapWindow", openControllerTView(), "tools"); -#ifdef M_CORE_GBA Action* frameWindow = addGameAction(tr("&Frame inspector..."), "frameWindow", [this]() { if (!m_frameView) { m_frameView = new FrameView(m_controller); @@ -1520,8 +1519,6 @@ void Window::setupMenu(QMenuBar* menubar) { } m_frameView->show(); }, "tools"); - m_platformActions.insert(PLATFORM_GBA, frameWindow); -#endif addGameAction(tr("View memory..."), "memoryView", openControllerTView(), "tools"); addGameAction(tr("Search memory..."), "memorySearch", openControllerTView(), "tools"); From 447750dc2e53fa4986a26e5ddcca90f5861be49a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Nov 2020 15:43:20 -0800 Subject: [PATCH 17/20] Qt: Take SGB border into account in frame viewer --- src/platform/qt/FrameView.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/platform/qt/FrameView.cpp b/src/platform/qt/FrameView.cpp index 05fbffbdb..6fbcbc584 100644 --- a/src/platform/qt/FrameView.cpp +++ b/src/platform/qt/FrameView.cpp @@ -318,7 +318,12 @@ void FrameView::updateTilesGB(bool) { m_queue.clear(); { CoreController::Interrupter interrupter(m_controller); - uint8_t* io = static_cast(m_controller->thread()->core->board)->memory.io; + QPointF origin; + GB* gb = static_cast(m_controller->thread()->core->board); + if (gb->video.sgbBorders && (gb->model & GB_MODEL_SGB)) { + origin = QPointF(48, 40); + } + uint8_t* io = gb->memory.io; GBRegisterLCDC lcdc = io[GB_REG_LCDC]; for (int sprite = 0; sprite < 40; ++sprite) { @@ -338,7 +343,7 @@ void FrameView::updateTilesGB(bool) { { LayerId::SPRITE, sprite }, !m_disabled.contains({ LayerId::SPRITE, sprite }), QPixmap::fromImage(obj), - {}, offset, false, false + {}, offset + origin, false, false }); if (m_queue.back().image.hasAlpha()) { m_queue.back().mask = QRegion(m_queue.back().image.mask()); @@ -352,7 +357,7 @@ void FrameView::updateTilesGB(bool) { { LayerId::WINDOW }, !m_disabled.contains({ LayerId::WINDOW }), {}, - {}, {0, 0}, false, false + {}, origin, false, false }); } @@ -360,7 +365,7 @@ void FrameView::updateTilesGB(bool) { { LayerId::BACKGROUND }, !m_disabled.contains({ LayerId::BACKGROUND }), {}, - {}, {0, 0}, false, false + {}, origin, false, false }); updateRendered(); @@ -528,6 +533,12 @@ void FrameView::newVl() { m_vl->loadROM(m_vl, m_currentFrame); m_currentFrame = nullptr; mCoreInitConfig(m_vl, nullptr); +#ifdef M_CORE_GB + if (m_controller->platform() == PLATFORM_GB) { + mCoreConfigSetIntValue(&m_vl->config, "sgb.borders", static_cast(m_controller->thread()->core->board)->video.sgbBorders); + m_vl->reloadConfigOption(m_vl, "sgb.borders", nullptr); + } +#endif unsigned width, height; m_vl->desiredVideoDimensions(m_vl, &width, &height); m_framebuffer = QImage(width, height, QImage::Format_RGBX8888); From ecc7522cf66db6c5f9464d2e85f671a9fad6fd7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81tila=20Camur=C3=A7a=20Alves?= Date: Mon, 23 Nov 2020 17:43:37 -0300 Subject: [PATCH 18/20] Brazilian portuguese translation (#1917) * Brazilian portuguese translation * Review and fixed some typos * Suggested revisions implemented * Not translating the word Shader It's not a common word in Portuguese, so it's easy to understand in English. * Review of suggested changes --- src/platform/qt/ts/mgba-pt_BR.ts | 5445 ++++++++++++++++++++++++++++++ 1 file changed, 5445 insertions(+) create mode 100644 src/platform/qt/ts/mgba-pt_BR.ts diff --git a/src/platform/qt/ts/mgba-pt_BR.ts b/src/platform/qt/ts/mgba-pt_BR.ts new file mode 100644 index 000000000..b5d3cf545 --- /dev/null +++ b/src/platform/qt/ts/mgba-pt_BR.ts @@ -0,0 +1,5445 @@ + + + + + AboutScreen + + + About + Sobre + + + + <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/">Site</a> • <a href="https://forums.mgba.io/">Fóruns / Suporte</a> • <a href="https://patreon.com/mgba">Doar</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">Fonte</a> + + + + Branch: <tt>{gitBranch}</tt><br/>Revision: <tt>{gitCommit}</tt> + Branch: <tt>{gitBranch}</tt><br/>Revisão: <tt>{gitCommit}</tt> + + + + {projectName} + {projectName} + + + + {projectName} would like to thank the following patrons from Patreon: + {projectName} gostaria de agradecer aos seguintes patrões do Patreon: + + + + © 2013 – 2020 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 +Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + © 2013 – 2020 Jeffrey Pfau, licenciado sob a Licença Pública Mozilla, versão 2.0 +Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. + + + + {projectVersion} + {projectVersion} + + + + {logo} + {logo} + + + + {projectName} is an open-source Game Boy Advance emulator + {projectName} é um emulador de Game Boy Advance de Código Aberto + + + + {patrons} + {patrons} + + + + ArchiveInspector + + + Open in archive... + Abrir no arquivo... + + + + Loading... + Carregando... + + + + AssetTile + + + AssetTile + Conjunto de Blocos + + + + Tile # + Bloco # + + + + + 0 + 0 + + + + Palette # + Paleta # + + + + Address + Endereço + + + + 0x06000000 + 0x06000000 + + + + Red + Vermelho + + + + Green + Verde + + + + Blue + Azul + + + + + + 0x00 (00) + 0x00 (00) + + + + BattleChipView + + + BattleChip Gate + BattleChip Gate + + + + Chip name + Nome do chip + + + + Insert + Inserir + + + + Save + Salvar + + + + Load + Carregar + + + + Add + Adicionar + + + + Remove + Excluir + + + + Gate type + Gate type + + + + Ba&ttleChip Gate + Ba&ttleChip Gate + + + + Progress &Gate + Progress &Gate + + + + Beast &Link Gate + Beast &Link Gate + + + + Inserted + Inserido + + + + Chip ID + ID do Chip + + + + Update Chip data + Atualizar dados do Chip + + + + Show advanced + Mostrar opções avançadas + + + + CheatsView + + + Cheats + Cheats + + + + Remove + Excluir + + + + Save + Salvar + + + + Load + Carregar + + + + Add New Set + Adicionar Novo Conjunto + + + + Add + Adicionar + + + + Enter codes here... + Insira os códigos aqui... + + + + DebuggerConsole + + + Debugger + Depurador + + + + Enter command (try `help` for more info) + Digite o comando (ou `help` para mais informações) + + + + Break + Pausar + + + + FrameView + + + Inspect frame + Inspecionar quadro + + + + × + × + + + + Magnification + Ampliação + + + + Freeze frame + Congelar quadro + + + + Backdrop color + Cor de fundo + + + + Disable scanline effects + Desativar efeitos scanline + + + + Export + Exportar + + + + Reset + Resetar + + + + GIFView + + + Record GIF/APNG + Gravar GIF/APNG + + + + Loop + Repetir + + + + Start + Iniciar + + + + Stop + Parar + + + + Select File + Selecionar arquivo + + + + APNG + APNG + + + + GIF + GIF + + + + WebP + WebP + + + + Frameskip + Frameskip + + + + IOViewer + + + I/O Viewer + Visualizador de E/S + + + + 0x0000 + 0x0000 + + + + 2 + 2 + + + + 5 + 5 + + + + 4 + 4 + + + + 7 + 7 + + + + 0 + 0 + + + + 9 + 9 + + + + 1 + 1 + + + + 3 + 3 + + + + 8 + 8 + + + + C + C + + + + E + E + + + + 6 + 6 + + + + D + D + + + + F + F + + + + A + A + + + + B + B + + + + LibraryTree + + + Name + Nome + + + + Location + Localização + + + + Platform + Plataforma + + + + Size + Tamanho + + + + CRC32 + CRC32 + + + + LoadSaveState + + + + %1 State + Estado %1 + + + + + + + + + + + + No Save + Não salvar + + + + 1 + 1 + + + + 2 + 2 + + + + Cancel + Cancelar + + + + 3 + 3 + + + + 4 + 4 + + + + 5 + 5 + + + + 6 + 6 + + + + 7 + 7 + + + + 8 + 8 + + + + 9 + 9 + + + + LogView + + + Logs + Registros + + + + Enabled Levels + Níveis Habilitados + + + + Debug + Depurar + + + + Stub + Stub + + + + Info + Info + + + + Warning + Warning + + + + Error + Error + + + + Fatal + Fatal + + + + Game Error + Erro do Jogo + + + + Clear + Limpar + + + + Max Lines + Máximo de Linhas + + + + MapView + + + Maps + Mapas + + + + × + × + + + + Magnification + Ampliação + + + + Export + Exportar + + + + Copy + Copiar + + + + MemoryDump + + + Save Memory Range + Salvar Faixa de Memória + + + + Start Address: + Endereço Inicial: + + + + : + : + + + + + 0x + 0x + + + + Byte Count: + Número de bytes: + + + + Dump across banks + Salvar múltiplos bancos + + + + MemorySearch + + + Memory Search + Pesquisa de Memória + + + + Address + Endereço + + + + Current Value + Valor Atual + + + + + Type + Tipo + + + + Value + Valor + + + + Numeric + Numérico + + + + Text + Texto + + + + Width + Tamanho + + + + 1 Byte (8-bit) + 1 Byte (8-bit) + + + + 2 Bytes (16-bit) + 2 Bytes (16-bit) + + + + 4 Bytes (32-bit) + 4 Bytes (32-bit) + + + + Number type + Tipo de número + + + + Hexadecimal + Hexadecimal + + + + Search type + Tipo de pesquisa + + + + Equal to value + Igual ao valor + + + + Greater than value + Maior que o valor + + + + Less than value + Menor que o valor + + + + Unknown/changed + Desconhecido/alterado + + + + Changed by value + Alterado por valor + + + + Unchanged + Inalterado + + + + Increased + Aumentado + + + + Decreased + Diminuído + + + + Search ROM + Pesquisar ROM + + + + New Search + Nova Pesquisa + + + + Decimal + Decimal + + + + + Guess + Adivinhar + + + + Search Within + Buscar nos Resultados + + + + Open in Memory Viewer + Abrir no Visualizador de Memória + + + + Refresh + Atualizar + + + + MemoryView + + + Memory + Memória + + + + Inspect Address: + Inspecionar Endereço: + + + + : + : + + + + 0x + 0x + + + + Set Alignment: + Definir Alinhamento: + + + + &1 Byte + &1 Byte + + + + &2 Bytes + &2 Bytes + + + + &4 Bytes + &4 Bytes + + + + Unsigned Integer: + Unsigned Integer: + + + + Signed Integer: + Signed Integer: + + + + String: + String: + + + + Load TBL + Carregar TBL + + + + Copy Selection + Copiar Seleção + + + + Paste + Colar + + + + Save Selection + Salvar Seleção + + + + Save Range + Salvar Intervalo + + + + Load + Carregar + + + + ObjView + + + Sprites + Sprites + + + + + × + × + + + + Magnification + Ampliação + + + + Export + Exportar + + + + Attributes + Atributos + + + + Transform + Transformar + + + + Off + Desligado + + + + Palette + Paleta + + + + + + + 0 + 0 + + + + Copy + Copiar + + + + + +0.00 + +0.00 + + + + + +1.00 + +1.00 + + + + Matrix + Matriz + + + + Double Size + Tamanho Duplo + + + + + + + Return, Ctrl+R + Return, Ctrl+R + + + + Flipped + Invertido + + + + H + H + + + + V + V + + + + Mode + Modo + + + + Normal + Normal + + + + Mosaic + Mosaico + + + + Enabled + Habilitado + + + + Priority + Prioridade + + + + Tile + Bloco + + + + Geometry + Geometria + + + + Position + Posição + + + + , + , + + + + Dimensions + Dimensões + + + + + 8 + 8 + + + + Address + Endereço + + + + 0x07000000 + 0x07000000 + + + + OverrideView + + + Game Overrides + Game Overrides + + + + Game Boy Advance + Game Boy Advance + + + + + + + Autodetect + Autodetectar + + + + Realtime clock + Relógio em tempo real + + + + Gyroscope + Giroscópio + + + + Tilt + Inclinação + + + + Light sensor + Sensor de luz + + + + Rumble + Vibrar + + + + Save type + Tipo de salvamento + + + + + None + Nenhum + + + + SRAM + SRAM + + + + Flash 512kb + Flash 512kb + + + + Flash 1Mb + Flash 1Mb + + + + EEPROM + EEPROM + + + + Idle loop + Loop ocioso + + + + Game Boy Player features + Funções do Game Boy Player + + + + Game Boy + Game Boy + + + + Game Boy model + Modelo do Game Boy + + + + Game Boy (DMG) + Game Boy (DMG) + + + + Super Game Boy (SGB) + Super Game Boy (SGB) + + + + Game Boy Color (CGB) + Game Boy Color (CGB) + + + + Game Boy Advance (AGB) + Game Boy Advance (AGB) + + + + Memory bank controller + Controlador de banco de memória + + + + MBC1 + MBC1 + + + + MBC2 + MBC2 + + + + MBC3 + MBC3 + + + + MBC3 + RTC + MBC3 + RTC + + + + MBC5 + MBC5 + + + + MBC5 + Rumble + MBC5 + Rumble + + + + MBC6 + MBC6 + + + + MBC7 + MBC7 + + + + MMM01 + MMM01 + + + + Pocket Cam + Pocket Cam + + + + TAMA5 + TAMA5 + + + + HuC-1 + HuC-1 + + + + HuC-3 + HuC-3 + + + + Wisdom Tree (Unlicensed) + Wisdom Tree (Não licenciado) + + + + Pokémon Jade/Diamond (Unlicensed) + Pokémon Jade/Diamond (Não licenciado) + + + + Background Colors + Cores do Plano de Fundo + + + + Sprite Colors 1 + Cores de Sprite 1 + + + + Sprite Colors 2 + Cores de Sprite 2 + + + + PaletteView + + + Palette + Paleta + + + + Background + Plano de Fundo + + + + Objects + Objetos + + + + Selection + Seleção + + + + Red + Vermelho + + + + Green + Verde + + + + Blue + Azul + + + + + + 0x00 (00) + 0x00 (00) + + + + 16-bit value + 16-bit value + + + + Hex code + Código hexadecimal + + + + Palette index + Índice da paleta + + + + 0x0000 + 0x0000 + + + + #000000 + #000000 + + + + 0x000 (000) + 0x000 (000) + + + + Export BG + Exportar BG + + + + Export OBJ + Exportar OBJ + + + + PlacementControl + + + Adjust placement + Ajustar posicionamento + + + + All + Todos + + + + Offset + Deslocamento + + + + X + X + + + + Y + Y + + + + PrinterView + + + Game Boy Printer + Game Boy Printer + + + + Hurry up! + Se apresse! + + + + Tear off + Desligar + + + + × + × + + + + Magnification + Ampliação + + + + QGBA::AssetTile + + + %0%1%2 + %0%1%2 + + + + + + 0x%0 (%1) + 0x%0 (%1) + + + + QGBA::CheatsModel + + + (untitled) + (sem título) + + + + Failed to open cheats file: %1 + Falha ao abrir arquivo de cheats: %1 + + + + QGBA::CheatsView + + + + Add GameShark + Adicionar GameShark + + + + Add Pro Action Replay + Adicionar Pro Action Replay + + + + Add CodeBreaker + Adicionar CodeBreaker + + + + Add GameGenie + Adicionar GameGenie + + + + + Select cheats file + Selecionar arquivo de cheats + + + + QGBA::CoreController + + + Failed to open save file: %1 + Falha ao abrir o arquivo de salvamento: %1 + + + + Failed to open game file: %1 + Falha ao abrir o arquivo do jogo: %1 + + + + Failed to open snapshot file for reading: %1 + Falha ao abrir o arquivo de snapshot para leitura: %1 + + + + Failed to open snapshot file for writing: %1 + Falha ao abrir o arquivo de snapshot para escrita: %1 + + + + QGBA::CoreManager + + + Failed to open game file: %1 + Falha ao abrir o arquivo do jogo: %1 + + + + Could not load game. Are you sure it's in the correct format? + Não foi possível carregar o jogo. Tem certeza que está no formato correto? + + + + Failed to open save file. Is the save directory writable? + Falha ao abrir o arquivo de salvamento. O diretório para salvar tem permissão de escrita? + + + + QGBA::FrameView + + + Export frame + Exportar quadro + + + + Portable Network Graphics (*.png) + Portable Network Graphics (*.png) + + + + None + Nenhum + + + + Background + Plano de Fundo + + + + Window + Janela + + + + Sprite + Sprite + + + + Backdrop + Cor de Fundo + + + + %1 %2 + %1 %2 + + + + QGBA::GBAApp + + + Enable Discord Rich Presence + Habilitar o Discord Rich Presence + + + + QGBA::GBAKeyEditor + + + Clear Button + Limpar Botão + + + + Clear Analog + Limpar Analógico + + + + Refresh + Atualizar + + + + Set all + Definir todos + + + + QGBA::GDBWindow + + + Server settings + Configurações do servidor + + + + Local port + Porta local + + + + Bind address + Vincular endereço + + + + Break + Pausar + + + + Stop + Parar + + + + Start + Iniciar + + + + Crash + Travar + + + + Could not start GDB server + Não foi possível iniciar o servidor GDB + + + + QGBA::GIFView + + + Failed to open output file: %1 + Falha ao abrir arquivo de saída: %1 + + + + Select output file + Selecionar arquivo de saída + + + + Graphics Interchange Format (*.gif);;Animated Portable Network Graphics (*.png *.webp *.apng) + Graphics Interchange Format (*.gif);;Animated Portable Network Graphics (*.png *.webp *.apng) + + + + QGBA::IOViewer + + + Background mode + Modo do plano de fundo + + + + Mode 0: 4 tile layers + Modo 0: 4 camadas de bloco + + + + Mode 1: 2 tile layers + 1 rotated/scaled tile layer + Modo 1: 2 camadas de blocos + 1 camada de bloco rotacionado/escalonado + + + + Mode 2: 2 rotated/scaled tile layers + Modo 2: 2 camadas de blocos rotacionados/escalonados + + + + Mode 3: Full 15-bit bitmap + Modo 3: Bitmap 15-bit completo + + + + Mode 4: Full 8-bit bitmap + Modo 4: Bitmap 8-bits completo + + + + Mode 5: Small 15-bit bitmap + Modo 5: Bitmap 15-bits pequeno + + + + CGB Mode + Modo CGB + + + + Frame select + Selecionar quadro + + + + Unlocked HBlank + HBlank desbloqueado + + + + Linear OBJ tile mapping + Mapeamento linear do OBJ + + + + Force blank screen + Forçar limpeza da tela + + + + Enable background 0 + Habilitar plano de fundo 0 + + + + Enable background 1 + Habilitar plano de fundo 1 + + + + Enable background 2 + Habilitar plano de fundo 2 + + + + Enable background 3 + Habilitar plano de fundo 3 + + + + Enable OBJ + Habilitar OBJ + + + + Enable Window 0 + Habilitar Janela 0 + + + + Enable Window 1 + Habilitar Janela 1 + + + + Enable OBJ Window + Habilitar Janela do OBJ + + + + Currently in VBlank + Atualmente no VBlank + + + + Currently in HBlank + Atualmente no HBlank + + + + Currently in VCounter + Atualmente no VCounter + + + + Enable VBlank IRQ generation + Habilitar geração de VBlank IRQ + + + + Enable HBlank IRQ generation + Habilitar geração de HBlank IRQ + + + + Enable VCounter IRQ generation + Habilitar geração de VCounter IRQ + + + + VCounter scanline + Scanline do VCounter + + + + Current scanline + Scanline atual + + + + + + + Priority + Prioridade + + + + + + + Tile data base (* 16kB) + Base de dados de blocos (* 16kB) + + + + + + + Enable mosaic + Habilitar mosaico + + + + + + + Enable 256-color + Habilitar 256-cores + + + + + + + Tile map base (* 2kB) + Base do mapa de blocos (* 2 kB) + + + + + + + Background dimensions + Dimensões do plano de fundo + + + + + Overflow wraps + Overflow wraps + + + + + + + Horizontal offset + Deslocamento horizontal + + + + + + + Vertical offset + Deslocamento vertical + + + + + + + + + + + + + + + Fractional part + Parte fracionária + + + + + + + + + + + Integer part + Parte inteira + + + + + + + Integer part (bottom) + Parte inteira (inferior) + + + + + + + Integer part (top) + Parte inteira (superior) + + + + + End x + X final + + + + + Start x + X inicial + + + + + End y + Y final + + + + + Start y + Y inicial + + + + Window 0 enable BG 0 + Janela 0 habilitar BG 0 + + + + Window 0 enable BG 1 + Janela 0 habilitar BG 1 + + + + Window 0 enable BG 2 + Janela 0 habilitar BG 2 + + + + Window 0 enable BG 3 + Janela 0 habilitar BG 3 + + + + Window 0 enable OBJ + Janela 0 habilitar OBJ + + + + Window 0 enable blend + Janela 0 habilitar blend + + + + Window 1 enable BG 0 + Janela 1 habilitar BG 0 + + + + Window 1 enable BG 1 + Janela 1 habilitar BG 1 + + + + Window 1 enable BG 2 + Janela 1 habilitar BG 2 + + + + Window 1 enable BG 3 + Janela 1 habilitar BG 3 + + + + Window 1 enable OBJ + Janela 1 habilitar OBJ + + + + Window 1 enable blend + Janela 1 habilitar blend + + + + Outside window enable BG 0 + Fora da janela habilitar BG 0 + + + + Outside window enable BG 1 + Fora da janela habilitar BG 1 + + + + Outside window enable BG 2 + Fora da janela habilitar BG 2 + + + + Outside window enable BG 3 + Fora da janela habilitar BG 3 + + + + Outside window enable OBJ + Fora da janela habilitar OBJ + + + + Outside window enable blend + Fora da janela habilitar blend + + + + OBJ window enable BG 0 + Janela OBJ habilitar BG 0 + + + + OBJ window enable BG 1 + Janela OBJ habilitar BG 1 + + + + OBJ window enable BG 2 + Janela OBJ habilitar BG 2 + + + + OBJ window enable BG 3 + Janela OBJ habilitar BG 3 + + + + OBJ window enable OBJ + Janela OBJ habilitar OBJ + + + + OBJ window enable blend + Janela OBJ habilitar blend + + + + Background mosaic size vertical + Tamanho vertical do mosaico do plano de fundo + + + + Background mosaic size horizontal + Tamanho horizontal do mosaico do plano de fundo + + + + Object mosaic size vertical + Tamanho vertical do mosaico de objeto + + + + Object mosaic size horizontal + Tamanho horizontal do mosaico de objeto + + + + BG 0 target 1 + BG 0 alvo 1 + + + + BG 1 target 1 + BG 1 alvo 1 + + + + BG 2 target 1 + BG 2 alvo 1 + + + + BG 3 target 1 + BG 3 alvo 1 + + + + OBJ target 1 + OBJ alvo 1 + + + + Backdrop target 1 + Backdrop alvo 1 + + + + Blend mode + Blend mode + + + + Disabled + Desabilitado + + + + Additive blending + Blending aditivo + + + + Brighten + Clarear + + + + Darken + Escurecer + + + + BG 0 target 2 + BG 0 alvo 2 + + + + BG 1 target 2 + BG 1 alvo 2 + + + + BG 2 target 2 + BG 2 alvo 2 + + + + BG 3 target 2 + BG 3 alvo 2 + + + + OBJ target 2 + OBJ alvo 2 + + + + Backdrop target 2 + Backdrop alvo 2 + + + + Blend A (target 1) + Blend A (alvo 1) + + + + Blend B (target 2) + Blend B (alvo 2) + + + + Blend Y + Blend Y + + + + Sweep shifts + Sweep shifts + + + + Sweep subtract + Sweep subtract + + + + Sweep time (in 1/128s) + Sweep time (em 1/128s) + + + + + + + Sound length + Comprimento do som + + + + + Duty cycle + Ciclo de trabalho + + + + + + Envelope step time + Envelope step time + + + + + + Envelope increase + Envelope increase + + + + + + Initial volume + Volume inicial + + + + + + Sound frequency + Frequência de som + + + + + + + Timed + Programado + + + + + + + Reset + Resetar + + + + Double-size wave table + Double-size wave table + + + + Active wave table + Active wave table + + + + Enable channel 3 + Habilitar canal 3 + + + + Volume + Volume + + + + 0% + 0% + + + + + 100% + 100% + + + + + 50% + 50% + + + + + 25% + 25% + + + + + + + 75% + 75% + + + + Clock divider + Divisor de relógio + + + + Register stages + Register stages + + + + 15 + 15 + + + + 7 + 7 + + + + Shifter frequency + Frequência de turno + + + + PSG volume right + Volume PSG direito + + + + PSG volume left + Volume PSG esquerdo + + + + Enable channel 1 right + Habilitar canal 1 à direita + + + + Enable channel 2 right + Habilitar canal 2 à direita + + + + Enable channel 3 right + Habilitar canal 3 à direita + + + + Enable channel 4 right + Habilitar canal 4 à direita + + + + Enable channel 1 left + Habilitar canal 1 à esquerda + + + + Enable channel 2 left + Habilitar canal 2 esquerdo + + + + Enable channel 3 left + Habilitar canal 3 esquerdo + + + + Enable channel 4 left + Habilitar canal 4 esquerdo + + + + PSG master volume + Volume principal do PSG + + + + Loud channel A + Canal A alto + + + + Loud channel B + Canal B alto + + + + Enable channel A right + Habilitar canal A direito + + + + Enable channel A left + Ativar o canal A esquerdo + + + + Channel A timer + Temporizador do canal A + + + + + 0 + 0 + + + + + + + + + + + + 1 + 1 + + + + Channel A reset + Redefinir canal A + + + + Enable channel B right + Habilitar canal B direito + + + + Enable channel B left + Habilitar canal B esquerdo + + + + Channel B timer + Temporizador do canal B + + + + Channel B reset + Redefinir canal B + + + + Active channel 1 + Canal ativo 1 + + + + Active channel 2 + Canal ativo 2 + + + + Active channel 3 + Canal ativo 3 + + + + Active channel 4 + Canal ativo 4 + + + + Enable audio + Habilitar áudio + + + + Bias + Viés + + + + Resolution + Resolução + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sample + Amostra + + + + + + + + + + + Address (bottom) + Endereço (inferior) + + + + + + + + + + + Address (top) + Endereço (superior) + + + + + + + Word count + Contagem de palavras + + + + + + + Destination offset + Deslocamento de destino + + + + + + + + + + + Increment + Incrementar + + + + + + + + + + + Decrement + Decrementar + + + + + + + + + + + Fixed + Corrigido + + + + + + + Increment and reload + Incrementar e recarregar + + + + + + + Source offset + Deslocamento de origem + + + + + + + Repeat + Repetir + + + + + + + 32-bit + 32-bit + + + + + + + Start timing + Iniciar timing + + + + + + + Immediate + Imediato + + + + + + + + + VBlank + VBlank + + + + + + + + + HBlank + HBlank + + + + + + + + + + + + IRQ + IRQ + + + + + + + + + + + Enable + Habilitar + + + + + + Audio FIFO + Áudio FIFO + + + + Video Capture + Captura de Vídeo + + + + DRQ + DRQ + + + + + + + Value + Valor + + + + + + + Scale + Escala + + + + + + + 1/64 + 1/64 + + + + + + + 1/256 + 1/256 + + + + + + + 1/1024 + 1/1024 + + + + + + Cascade + Em cascata + + + + + A + A + + + + + B + B + + + + + Select + Select + + + + + Start + Start + + + + + Right + Direita + + + + + Left + Esquerda + + + + + Up + Cima + + + + + Down + Baixo + + + + + R + R + + + + + L + L + + + + Condition + Condição + + + + SC + SC + + + + SD + SD + + + + SI + SI + + + + SO + SO + + + + + VCounter + VCounter + + + + + Timer 0 + Cronômetro 0 + + + + + Timer 1 + Cronômetro 1 + + + + + Timer 2 + Cronômetro 2 + + + + + Timer 3 + Cronômetro 3 + + + + + SIO + SIO + + + + + DMA 0 + DMA 0 + + + + + DMA 1 + DMA 1 + + + + + DMA 2 + DMA 2 + + + + + DMA 3 + DMA 3 + + + + + Keypad + Keypad + + + + + Gamepak + Gamepak + + + + SRAM wait + Aguardar SRAM + + + + + + + + 4 + 4 + + + + + + + 3 + 3 + + + + + + + + 2 + 2 + + + + + + + + 8 + 8 + + + + Cart 0 non-sequential + Cart 0 non-sequential + + + + Cart 0 sequential + Cart 0 sequential + + + + Cart 1 non-sequential + Cart 1 non-sequential + + + + Cart 1 sequential + Cart 1 sequential + + + + Cart 2 non-sequential + Cart 2 non-sequential + + + + Cart 2 sequential + Cart 2 sequential + + + + PHI terminal + Terminal PHI + + + + Disable + Desabilitado + + + + 4.19MHz + 4.19MHz + + + + 8.38MHz + 8.38MHz + + + + 16.78MHz + 16.78MHz + + + + Gamepak prefetch + Pré-carregamento de Gamepak + + + + Enable IRQs + Habilitar IRQs + + + + QGBA::KeyEditor + + + + --- + --- + + + + Super (L) + Super (L) + + + + Super (R) + Super (R) + + + + Menu + Menu + + + + QGBA::LoadSaveState + + + Load State + Carregar Estado + + + + Save State + Salvar Estado + + + + Empty + Vazio + + + + Corrupted + Corrompido + + + + Slot %1 + Espaço %1 + + + + QGBA::LogConfigModel + + + + Default + Padrão + + + + Fatal + Fatal + + + + Error + Error + + + + Warning + Warning + + + + Info + Info + + + + Debug + Debug + + + + Stub + Stub + + + + Game Error + Erro do Jogo + + + + QGBA::LogController + + + [%1] %2: %3 + [%1] %2: %3 + + + + An error occurred + Ocorreu um erro + + + + DEBUG + DEBUG + + + + STUB + STUB + + + + INFO + INFO + + + + WARN + WARN + + + + ERROR + ERROR + + + + FATAL + FATAL + + + + GAME ERROR + GAME ERROR + + + + QGBA::MapView + + + Priority + Prioridade + + + + + Map base + Base do mapa + + + + + Tile base + Base do bloco + + + + Size + Tamanho + + + + + Offset + Deslocamento + + + + Xform + Xform + + + + Map Addr. + Endereço do Mapa + + + + Mirror + Espelhamento + + + + None + Nenhum + + + + Both + Ambos + + + + Horizontal + Horizontal + + + + Vertical + Vertical + + + + + + N/A + N/D + + + + Export map + Exportar mapa + + + + Portable Network Graphics (*.png) + Portable Network Graphics (*.png) + + + + QGBA::MemoryDump + + + Save memory region + Salvar região de memória + + + + Failed to open output file: %1 + Falha ao abrir arquivo de saída: %1 + + + + QGBA::MemoryModel + + + Copy selection + Copiar seleção + + + + Save selection + Salvar seleção + + + + Paste + Colar + + + + Load + Carregar + + + + All + Todos + + + + Load TBL + Carregar TBL + + + + Save selected memory + Salvar memória selecionada + + + + Failed to open output file: %1 + Falha ao abrir arquivo de saída: %1 + + + + Load memory + Carregar memória + + + + Failed to open input file: %1 + Falha ao abrir arquivo de entrada: %1 + + + + TBL + TBL + + + + ISO-8859-1 + ISO-8859-1 + + + + QGBA::MemorySearch + + + (%0/%1×) + (%0/%1×) + + + + (⅟%0×) + (⅟%0×) + + + + (%0×) + (%0×) + + + + %1 byte%2 + %1 byte%2 + + + + QGBA::ObjView + + + + 0x%0 + 0x%0 + + + + Off + Desligado + + + + + + + + + + + --- + --- + + + + Normal + Normal + + + + Trans + Trans + + + + OBJWIN + OBJWIN + + + + Invalid + Inválido + + + + + N/A + N/D + + + + Export sprite + Exportar sprite + + + + Portable Network Graphics (*.png) + Portable Network Graphics (*.png) + + + + QGBA::PaletteView + + + #%0 + #%0 + + + + 0x%0 + 0x%0 + + + + + + + 0x%0 (%1) + 0x%0 (%1) + + + + Export palette + Exportar paleta + + + + Windows PAL (*.pal);;Adobe Color Table (*.act) + Windows PAL (*.pal);;Adobe Color Table (*.act) + + + + Failed to open output palette file: %1 + Falha ao abrir arquivo de paleta de saída: %1 + + + + QGBA::ROMInfo + + + + + + + (unknown) + (desconhecido) + + + + + bytes + bytes + + + + (no database present) + (nenhum banco de dados) + + + + QGBA::SettingsView + + + + Qt Multimedia + Qt multimídia + + + + SDL + SDL + + + + Software (Qt) + Software (Qt) + + + + OpenGL + OpenGL + + + + OpenGL (force version 1.x) + OpenGL (forçar versão 1.x) + + + + None (Still Image) + Nenhum (Still Image) + + + + Keyboard + Teclado + + + + Controllers + Controles + + + + Shortcuts + Atalhos + + + + + Shaders + Shaders + + + + Select BIOS + Selecionar BIOS + + + + (%1×%2) + (%1×%2) + + + + QGBA::ShaderSelector + + + No shader active + Nenhum shader ativo + + + + Load shader + Carregar shader + + + + No shader loaded + Nenhum shader carregado + + + + by %1 + por %1 + + + + Preprocessing + Pré-processamento + + + + Pass %1 + Passar %1 + + + + QGBA::ShortcutModel + + + Action + Acão + + + + Keyboard + Teclado + + + + Gamepad + Controle + + + + QGBA::TileView + + + Export tiles + Exportar blocos + + + + + Portable Network Graphics (*.png) + Portable Network Graphics (*.png) + + + + Export tile + Exportar bloco + + + + QGBA::VideoView + + + Failed to open output video file: %1 + Falha ao abrir arquivo de vídeo de saída: %1 + + + + Native (%0x%1) + Nativo (%0x%1) + + + + Select output file + Selecione o arquivo de saída + + + + QGBA::Window + + + Game Boy Advance ROMs (%1) + ROMs de Game Boy Advance (%1) + + + + Game Boy ROMs (%1) + ROMs de Game Boy (%1) + + + + All ROMs (%1) + Todas as ROMs (%1) + + + + %1 Video Logs (*.mvl) + %1 Logs de Vídeo (*.mvl) + + + + Archives (%1) + Arquivos (%1) + + + + + + Select ROM + Selecionar ROM + + + + Select folder + Selecionar pasta + + + + Game Boy Advance save files (%1) + Arquivos salvos de Game Boy Advance (%1) + + + + + + Select save + Selecionar salvamento + + + + mGBA savestate files (%1) + Arquivos de savestate do mGBA (%1) + + + + + Select savestate + Selecionar savestate + + + + Select patch + Selecione correção + + + + Patches (*.ips *.ups *.bps) + Patches (*.ips *.ups *.bps) + + + + Select e-Reader dotcode + Selecione dotcode do e-Reader + + + + e-Reader card (*.raw *.bin *.bmp) + e-Reader card (*.raw *.bin *.bmp) + + + + Select image + Selecionar imagem + + + + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) + Arquivo de imagem (*.png *.gif *.jpg *.jpeg);;Todos os arquivos (*) + + + + + GameShark saves (*.sps *.xps) + GameShark saves (*.sps *.xps) + + + + Select video log + Selecionar registro de vídeo + + + + Video logs (*.mvl) + Video logs (*.mvl) + + + + Crash + Travamento + + + + The game has crashed with the following error: + +%1 + O jogo travou com o seguinte erro: + +%1 + + + + Unimplemented BIOS call + Chamada de BIOS não implementada + + + + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. + Este jogo usa uma chamada de BIOS que não está implementada. Por favor, use a BIOS oficial para uma melhor experiência. + + + + Really make portable? + Quer mesmo tornar portátil? + + + + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? + Isto fará com que o emulador carregue sua configuração a partir do mesmo diretório que o executável. Você quer continuar? + + + + Restart needed + É necessário reiniciar + + + + Some changes will not take effect until the emulator is restarted. + Algumas alterações não terão efeito até que o emulador seja reiniciado. + + + + - Player %1 of %2 + - Jogador %1 de %2 + + + + %1 - %2 + %1 - %2 + + + + %1 - %2 - %3 + %1 - %2 - %3 + + + + %1 - %2 (%3 fps) - %4 + %1 - %2 (%3 fps) - %4 + + + + &File + &Arquivo + + + + Load &ROM... + Carregar &ROM... + + + + Load ROM in archive... + Carregar ROM em arquivo... + + + + Add folder to library... + Adicionar pasta à biblioteca... + + + + Load alternate save... + Carregar salvamento alternativo... + + + + Load temporary save... + Carregar salvamento temporário... + + + + Load &patch... + Carregar &patch... + + + + Boot BIOS + Rodar BIOS + + + + Replace ROM... + Substituir ROM... + + + + ROM &info... + &Informações da ROM... + + + + Recent + Recente + + + + Make portable + Tornar portátil + + + + &Load state + &Carregar Estado + + + + About... + Sobre... + + + + Game Pak sensors... + Sensores de Game Pak... + + + + Clear + Limpar + + + + Load state file... + Carregar arquivo de estado... + + + + &Save state + &Salvar Estado + + + + Save state file... + Salvar arquivo de estado... + + + + Quick load + Carregamento rápido + + + + Quick save + Salvamento rápido + + + + Load recent + Carregar recente + + + + Save recent + Salvar recente + + + + Undo load state + Desfazer carregar estado + + + + Undo save state + Desfazer salvar estado + + + + + State &%1 + Estado &%1 + + + + Load camera image... + Carregar imagem da câmera... + + + + New multiplayer window + Nova janela multijogador + + + + E&xit + &Sair + + + + &Emulation + &Emulação + + + + &Reset + &Resetar + + + + Sh&utdown + &Desligar + + + + Yank game pak + Remover game pak + + + + &Pause + &Pausar + + + + &Next frame + &Próximo quadro + + + + Fast forward (held) + Avançar rápido (segurado) + + + + &Fast forward + Avanço &Rápido + + + + Fast forward speed + Velocidade de avanço + + + + Unbounded + Ilimitado + + + + %0x + %0x + + + + Rewind (held) + Retroceder (segurado) + + + + Re&wind + Re&troceder + + + + Step backwards + Voltar um passo + + + + Sync to &video + Sincronizar para &vídeo + + + + Sync to &audio + Sincronizar para &áudio + + + + Solar sensor + Sensor solar + + + + Increase solar level + Aumentar nível solar + + + + Decrease solar level + Diminuir nível solar + + + + Brightest solar level + Nível solar mais brilhante + + + + Darkest solar level + Nível solar mais escuro + + + + Brightness %1 + Brilho %1 + + + + Audio/&Video + Áudio/&Vídeo + + + + Frame size + Tamanho do quadro + + + + Toggle fullscreen + Alternar tela cheia + + + + Lock aspect ratio + Fixar proporção + + + + Force integer scaling + Forçar dimensionamento inteiro + + + + Bilinear filtering + Filtragem bilinear + + + + Frame&skip + &Salto de quadro + + + + Mute + Mudo + + + + FPS target + Meta de FPS + + + + Native (59.7275) + Nativo (59,7275) + + + + Take &screenshot + Capturar &tela + + + + F12 + F12 + + + + Game Boy Printer... + Game Boy Printer... + + + + BattleChip Gate... + BattleChip Gate... + + + + %1× + %1× + + + + Interframe blending + Interframe blending + + + + Record A/V... + Gravar A/V... + + + + Video layers + Camadas de vídeo + + + + Audio channels + Canais de áudio + + + + Adjust layer placement... + Ajustar posicionamento da camada... + + + + &Tools + &Ferramentas + + + + View &logs... + Visualizar &registros... + + + + Game &overrides... + Game &overrides... + + + + Couldn't Start + Não foi possível Iniciar + + + + Could not start game. + Não foi possível iniciar o jogo. + + + + Scan e-Reader dotcodes... + Escanear dotcode do e-Reader... + + + + Import GameShark Save... + Importar salvamento do GameShark... + + + + Export GameShark Save... + Exportar salvamento do GameShark... + + + + Record GIF/WebP/APNG... + Gravar GIF/WebP/APNG... + + + + &Cheats... + &Cheats... + + + + Settings... + Configurações... + + + + Open debugger console... + Abrir console de depuração... + + + + Start &GDB server... + Iniciar servidor &GDB... + + + + View &palette... + Visualizar &paleta... + + + + View &sprites... + Visualizar &sprites... + + + + View &tiles... + Visualizar &blocos... + + + + View &map... + Visualizar &mapa... + + + + &Frame inspector... + Inspetor de &quadro... + + + + View memory... + Visualizar memória... + + + + Search memory... + Pesquisar memória... + + + + View &I/O registers... + Visualizar registros de &E/S... + + + + Record debug video log... + Gravar log de vídeo de depuração... + + + + Stop debug video log + Parar log de vídeo de depuração + + + + Exit fullscreen + Sair da tela cheia + + + + GameShark Button (held) + Botão de GameShark (segurado) + + + + Autofire + Disparo automático + + + + Autofire A + Disparo automático A + + + + Autofire B + Disparo automático B + + + + Autofire L + Disparo automático L + + + + Autofire R + Disparo automático R + + + + Autofire Start + Disparo automático Start + + + + Autofire Select + Disparo automático Select + + + + Autofire Up + Disparo automático Cima + + + + Autofire Right + Disparo automático Direita + + + + Autofire Down + Disparo automático Baixo + + + + Autofire Left + Disparo automático Esquerda + + + + QObject + + + GBA + GBA + + + + GB + GB + + + + ? + ? + + + + QShortcut + + + Shift + Shift + + + + Control + Control + + + + Alt + Alt + + + + Meta + Meta + + + + ROMInfo + + + ROM Info + Informações da ROM + + + + Game name: + Nome do jogo: + + + + {NAME} + {NAME} + + + + Internal name: + Nome interno: + + + + {TITLE} + {TITLE} + + + + Game ID: + ID do jogo: + + + + {ID} + {ID} + + + + File size: + Tamanho do arquivo: + + + + {SIZE} + {SIZE} + + + + CRC32: + CRC32: + + + + {CRC} + {CRC} + + + + SensorView + + + Sensors + Sensores + + + + Realtime clock + Relógio em tempo real + + + + Fixed time + Tempo fixo + + + + System time + Horário do sistema + + + + Start time at + Horário iniciando em + + + + Now + Agora + + + + MM/dd/yy hh:mm:ss AP + dd/MM/yy hh:mm:ss + + + + Light sensor + Sensor de luz + + + + Brightness + Brilho + + + + Tilt sensor + Sensor de inclinação + + + + + Set Y + Definir Y + + + + + Set X + Definir X + + + + Gyroscope + Giroscópio + + + + Sensitivity + Sensibilidade + + + + SettingsView + + + Settings + Configurações + + + + Audio/Video + Áudio/Vídeo + + + + Interface + Interface + + + + Emulation + Emulação + + + + Enhancements + Melhorias + + + + BIOS + BIOS + + + + Paths + Caminhos + + + + Logging + Registros + + + + Game Boy + Game Boy + + + + Audio driver: + Driver de áudio: + + + + Audio buffer: + Buffer de áudio: + + + + + 1536 + 1536 + + + + 512 + 512 + + + + 768 + 768 + + + + 1024 + 1024 + + + + 2048 + 2048 + + + + 3072 + 3072 + + + + 4096 + 4096 + + + + samples + amostras + + + + Sample rate: + Taxa de amostragem: + + + + + 44100 + 44100 + + + + 22050 + 22050 + + + + 32000 + 32000 + + + + 48000 + 48000 + + + + Hz + Hz + + + + Volume: + Volume: + + + + + Mute + Mudo + + + + Fast forward volume: + Volume durante avanço rápido: + + + + Display driver: + Driver de exibição: + + + + Frameskip: + Salto de quadro: + + + + Skip every + Ignorar a cada + + + + + frames + quadros + + + + FPS target: + Meta de FPS: + + + + frames per second + quadros por segundo + + + + Sync: + Sincronizar: + + + + Video + Vídeo + + + + Audio + Áudio + + + + Lock aspect ratio + Fixar proporção + + + + Bilinear filtering + Filtragem bilinear + + + + Native (59.7275) + Nativo (59,7275) + + + + Interframe blending + Interframe blending + + + + Pause when minimized + Pausar quando minimizado + + + + Show OSD messages + Exibir mensagens OSD + + + + Show filename instead of ROM name in title bar + Mostrar nome do arquivo em vez do nome da ROM na barra de título + + + + Fast forward (held) speed: + Velocidade de avanço (segurado): + + + + (240×160) + (240×160) + + + + Log to file + Registrar para arquivo + + + + Log to console + Registrar no console + + + + Select Log File + Selecionar Arquivo de Registro + + + + Game Boy model: + Modelo do Game Boy: + + + + Super Game Boy model: + Modelo do Super Game Boy: + + + + Game Boy Color model: + Modelo do Game Boy Color: + + + + Use GBC colors in GB games + Usar cores de GBC em jogos de GB + + + + Camera: + Câmera: + + + + Force integer scaling + Forçar dimensionamento inteiro + + + + Language + Idioma + + + + English + Português do Brasil + + + + Library: + Biblioteca: + + + + List view + Visualização em lista + + + + Tree view + Visualização em árvore + + + + Show when no game open + Exibir quando nenhum jogo estiver aberto + + + + Clear cache + Limpar cache + + + + Allow opposing input directions + Permitir direções de entrada opostas + + + + Suspend screensaver + Suspender protetor de tela + + + + Pause when inactive + Pausar quando inativo + + + + Show FPS in title bar + Mostrar FPS na barra de título + + + + Automatically save cheats + Salvar cheats automaticamente + + + + Automatically load cheats + Carregar cheats automaticamente + + + + Automatically save state + Salvar estado automaticamente + + + + Automatically load state + Carregar estado automaticamente + + + + Enable Discord Rich Presence + Habilitar Discord Rich Presence + + + + Fast forward speed: + Velocidade de avanço: + + + + + + × + × + + + + + Unbounded + Ilimitado + + + + Enable rewind + Ativar retrocesso + + + + Rewind history: + Histórico de retrocesso: + + + + Idle loops: + Loops ociosos: + + + + Run all + Executar todos + + + + Remove known + Remover conhecidos + + + + Detect and remove + Detectar e remover + + + + Savestate extra data: + Savestate extra data: + + + + + Screenshot + Captura de tela + + + + + Save data + Salvar dados + + + + + Cheat codes + Códigos de cheat + + + + Load extra data: + Carregar dados extras: + + + + Preload entire ROM into memory + Pré-carregar toda a ROM na memória + + + + Autofire interval: + Intervalo do Disparo Automático: + + + + Video renderer: + Renderizador de vídeo: + + + + Software + Software + + + + OpenGL + OpenGL + + + + OpenGL enhancements + Melhorias do OpenGL + + + + High-resolution scale: + Escala de alta resolução: + + + + XQ GBA audio (experimental) + XQ GBA audio (experimental) + + + + GB BIOS file: + Arquivo GB BIOS: + + + + + + + + + + + + Browse + Navegar + + + + Use BIOS file if found + Usar o arquivo BIOS se encontrado + + + + Skip BIOS intro + Pular introdução da BIOS + + + + GBA BIOS file: + Arquivo GBA BIOS: + + + + GBC BIOS file: + Arquivo GBC BIOS: + + + + SGB BIOS file: + Arquivo SGB BIOS: + + + + Save games + Arquivos de salvamento + + + + + + + + Same directory as the ROM + Mesmo diretório que a ROM + + + + Save states + Estados salvos + + + + Screenshots + Capturas de tela + + + + Patches + Patches + + + + Cheats + Cheats + + + + + + Autodetect + Autodetectar + + + + + + Game Boy (DMG) + Game Boy (DMG) + + + + + + Super Game Boy (SGB) + Super Game Boy (SGB) + + + + + + Game Boy Color (CGB) + Game Boy Color (CGB) + + + + + + Game Boy Advance (AGB) + Game Boy Advance (AGB) + + + + Default BG colors: + Cores padrão do BG: + + + + Super Game Boy borders + Bordas do Super Game Boy + + + + Camera driver: + Driver da Câmera: + + + + Default sprite colors 1: + Cores padrão do sprite 1: + + + + Default sprite colors 2: + Cores padrão do sprite 2: + + + + ShaderSelector + + + Shaders + Shaders + + + + Active Shader: + Shader Ativo: + + + + Name + Nome + + + + Author + Autor + + + + Description + Descrição + + + + Unload Shader + Remover Shader + + + + Load New Shader + Carregar Novo Shader + + + + ShortcutView + + + Edit Shortcuts + Editar Atalhos + + + + Keyboard + Teclado + + + + Gamepad + Controle + + + + Clear + Limpar + + + + TileView + + + Tiles + Blocos + + + + Export Selected + Exportar Selecionado + + + + Export All + Exportar Tudo + + + + 256 colors + 256 cores + + + + × + × + + + + Magnification + Ampliação + + + + Tiles per row + Blocos por linha + + + + Fit to window + Ajustar à janela + + + + Copy Selected + Copiar selecionado + + + + Copy All + Copiar Tudo + + + + VideoView + + + Record Video + Gravar Vídeo + + + + Start + Iniciar + + + + Stop + Parar + + + + Select File + Selecionar arquivo + + + + Presets + Predefinições + + + + + WebM + WebM + + + + Format + Formato + + + + MKV + MKV + + + + AVI + AVI + + + + + MP4 + MP4 + + + + High &Quality + Qualidade &Alta + + + + &YouTube + &YouTube + + + + &Lossless + &Sem perdas + + + + 4K + 4K + + + + &1080p + &1080p + + + + &720p + &720p + + + + &480p + &480p + + + + &Native + &Nativo + + + + h.264 + h.264 + + + + h.264 (NVENC) + h.264 (NVENC) + + + + HEVC + HEVC + + + + HEVC (NVENC) + HEVC (NVENC) + + + + VP8 + VP8 + + + + VP9 + VP9 + + + + FFV1 + FFV1 + + + + + None + Nenhum + + + + FLAC + FLAC + + + + Opus + Opus + + + + Vorbis + Vorbis + + + + MP3 + MP3 + + + + AAC + AAC + + + + Uncompressed + Sem compressão + + + + Bitrate (kbps) + Bitrate (kbps) + + + + VBR + VBR + + + + ABR + ABR + + + + Dimensions + Dimensões + + + + : + : + + + + × + × + + + + Lock aspect ratio + Fixar proporção + + + + Show advanced + Mostrar opções avançadas + + + From 19b77189c8f2a5d2f9172845836fae1e05263763 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 24 Nov 2020 00:16:00 -0800 Subject: [PATCH 19/20] GBA Hardware: Add support for "reduced" header e-Reader dumps --- src/gba/ereader.c | 104 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 18 deletions(-) diff --git a/src/gba/ereader.c b/src/gba/ereader.c index e288f78c6..5e3c64ef3 100644 --- a/src/gba/ereader.c +++ b/src/gba/ereader.c @@ -103,6 +103,16 @@ const uint16_t EREADER_ADDRESS_CODES[] = { 54679 }; +static const uint8_t DUMMY_HEADER_STRIP[2][0x10] = { + { 0x00, 0x30, 0x01, 0x01, 0x00, 0x01, 0x05, 0x10, 0x00, 0x00, 0x10, 0x13, 0x00, 0x00, 0x02, 0x00 }, + { 0x00, 0x30, 0x01, 0x02, 0x00, 0x01, 0x08, 0x10, 0x00, 0x00, 0x10, 0x12, 0x00, 0x00, 0x01, 0x00 } +}; + +static const uint8_t DUMMY_HEADER_FIXED[0x16] = { + 0x00, 0x00, 0x10, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x08, 0x4e, 0x49, 0x4e, 0x54, 0x45, 0x4e, + 0x44, 0x4f, 0x00, 0x22, 0x00, 0x09 +}; + static const uint8_t BLOCK_HEADER[2][0x18] = { { 0x00, 0x02, 0x00, 0x01, 0x40, 0x10, 0x00, 0x1c, 0x10, 0x6f, 0x40, 0xda, 0x39, 0x25, 0x8e, 0xe0, 0x7b, 0xb5, 0x98, 0xb6, 0x5b, 0xcf, 0x7f, 0x72 }, { 0x00, 0x03, 0x00, 0x19, 0x40, 0x10, 0x00, 0x2c, 0x0e, 0x88, 0xed, 0x82, 0x50, 0x67, 0xfb, 0xd1, 0x43, 0xee, 0x03, 0xc6, 0xc6, 0x2b, 0x2c, 0x93 } @@ -327,12 +337,18 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s memset(hw->eReaderDots, 0, EREADER_DOTCODE_SIZE); uint8_t blockRS[44][0x10]; + uint8_t block0[0x30]; bool parsed = false; bool bitmap = false; + bool reducedHeader = false; size_t blocks; int base; switch (size) { // Raw sizes + case 2076: + memcpy(block0, DUMMY_HEADER_STRIP[1], sizeof(DUMMY_HEADER_STRIP[1])); + reducedHeader = true; + // Fallthrough case 2112: parsed = true; // Fallthrough @@ -340,6 +356,10 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s base = 25; blocks = 28; break; + case 1308: + memcpy(block0, DUMMY_HEADER_STRIP[0], sizeof(DUMMY_HEADER_STRIP[0])); + reducedHeader = true; + // Fallthrough case 1344: parsed = true; // Fallthrough @@ -355,11 +375,12 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s return; } + const uint8_t* cdata = data; size_t i; if (bitmap) { size_t x; for (i = 0; i < 40; ++i) { - const uint8_t* line = &((const uint8_t*) data)[(i + 2) * 124]; + const uint8_t* line = &cdata[(i + 2) * 124]; uint8_t* origin = &hw->eReaderDots[EREADER_DOTCODE_STRIDE * i + 200]; for (x = 0; x < 124; ++x) { uint8_t byte = line[x]; @@ -386,8 +407,49 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s _eReaderAddress(origin, base + i); } if (parsed) { - for (i = 0; i < size / 48; ++i) { - _eReaderReedSolomon(&((const uint8_t*) data)[i * 48], blockRS[i]); + if (reducedHeader) { + memcpy(&block0[0x10], DUMMY_HEADER_FIXED, sizeof(DUMMY_HEADER_FIXED)); + block0[0x0D] = cdata[0x0]; + block0[0x0C] = cdata[0x1]; + block0[0x10] = cdata[0x2]; + block0[0x11] = cdata[0x3]; + block0[0x26] = cdata[0x4]; + block0[0x27] = cdata[0x5]; + block0[0x28] = cdata[0x6]; + block0[0x29] = cdata[0x7]; + block0[0x2A] = cdata[0x8]; + block0[0x2B] = cdata[0x9]; + block0[0x2C] = cdata[0xA]; + block0[0x2D] = cdata[0xB]; + for (i = 0; i < 12; ++i) { + block0[0x2E] ^= cdata[i]; + } + unsigned dataChecksum = 0; + int j; + for (i = 1; i < (size + 36) / 48; ++i) { + const uint8_t* block = &cdata[i * 48 - 36]; + _eReaderReedSolomon(block, blockRS[i]); + unsigned fragmentChecksum = 0; + for (j = 0; j < 0x30; j += 2) { + uint16_t halfword; + fragmentChecksum ^= block[j]; + fragmentChecksum ^= block[j + 1]; + LOAD_16BE(halfword, j, block); + dataChecksum += halfword; + } + block0[0x2F] += fragmentChecksum; + } + block0[0x13] = (~dataChecksum) >> 8; + block0[0x14] = ~dataChecksum; + for (i = 0; i < 0x2F; ++i) { + block0[0x2F] += block0[i]; + } + block0[0x2F] = ~block0[0x2F]; + _eReaderReedSolomon(block0, blockRS[0]); + } else { + for (i = 0; i < size / 48; ++i) { + _eReaderReedSolomon(&cdata[i * 48], blockRS[i]); + } } } size_t blockId = 0; @@ -407,23 +469,29 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s parsedBlockData[1] = header[(2 * i) % 0x18 + 1]; int j; for (j = 2; j < 104; ++j) { - if (byteOffset >= 0x40) { - break; - } - if (byteOffset >= 0x30) { - parsedBlockData[j] = blockRS[blockId][byteOffset - 0x30]; - } else { - parsedBlockData[j] = ((const uint8_t*) data)[blockId * 0x30 + byteOffset]; - } - ++blockId; - if (blockId * 0x30 >= size) { - blockId = 0; - ++byteOffset; - } + if (byteOffset >= 0x40) { + break; + } + if (byteOffset >= 0x30) { + parsedBlockData[j] = blockRS[blockId][byteOffset - 0x30]; + } else if (!reducedHeader) { + parsedBlockData[j] = cdata[blockId * 0x30 + byteOffset]; + } else { + if (blockId > 0) { + parsedBlockData[j] = cdata[blockId * 0x30 + byteOffset - 36]; + } else { + parsedBlockData[j] = block0[byteOffset]; + } + } + ++blockId; + if (blockId * 0x30 >= size) { + blockId = 0; + ++byteOffset; + } } blockData = parsedBlockData; } else { - blockData = &((const uint8_t*) data)[i * 104]; + blockData = &cdata[i * 104]; } int b; for (b = 0; b < 104; ++b) { @@ -646,4 +714,4 @@ void GBAEReaderQueueCard(struct GBA* gba, const void* data, size_t size) { gba->memory.hw.eReaderCards[i].size = size; return; } -} \ No newline at end of file +} From 1a694b0b56ac3ead10ff5dc281ee46985a593223 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 24 Nov 2020 00:21:37 -0800 Subject: [PATCH 20/20] Debugger: Fix change watchpoints (fixes #1947) --- CHANGES | 1 + include/mgba/debugger/debugger.h | 3 ++- src/arm/debugger/memory-debugger.c | 13 ++++++++++--- src/sm83/debugger/memory-debugger.c | 6 +++++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 57a9b957b..5cb6fe228 100644 --- a/CHANGES +++ b/CHANGES @@ -57,6 +57,7 @@ Other fixes: - Core: Fix threading improperly setting paused state while interrupted - Debugger: Don't skip undefined instructions when debugger attached - Debugger: Close trace log when done tracing + - Debugger: Fix change watchpoints (fixes mgba.io/i/1947) - FFmpeg: Fix some small memory leaks - FFmpeg: Fix encoding of time base - GB Video: Fix SGB video logs diff --git a/include/mgba/debugger/debugger.h b/include/mgba/debugger/debugger.h index f3404c02b..2adfa117c 100644 --- a/include/mgba/debugger/debugger.h +++ b/include/mgba/debugger/debugger.h @@ -38,7 +38,8 @@ enum mWatchpointType { WATCHPOINT_WRITE = 1, WATCHPOINT_READ = 2, WATCHPOINT_RW = 3, - WATCHPOINT_WRITE_CHANGE = 4, + WATCHPOINT_CHANGE = 4, + WATCHPOINT_WRITE_CHANGE = 5, }; enum mBreakpointType { diff --git a/src/arm/debugger/memory-debugger.c b/src/arm/debugger/memory-debugger.c index dce4b9771..8ccb592e7 100644 --- a/src/arm/debugger/memory-debugger.c +++ b/src/arm/debugger/memory-debugger.c @@ -106,17 +106,24 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st } } + uint32_t oldValue; switch (width + 1) { case 1: - info->type.wp.oldValue = debugger->originalMemory.load8(debugger->cpu, address, 0); + oldValue = debugger->originalMemory.load8(debugger->cpu, address, 0); break; case 2: - info->type.wp.oldValue = debugger->originalMemory.load16(debugger->cpu, address, 0); + oldValue = debugger->originalMemory.load16(debugger->cpu, address, 0); break; case 4: - info->type.wp.oldValue = debugger->originalMemory.load32(debugger->cpu, address, 0); + oldValue = debugger->originalMemory.load32(debugger->cpu, address, 0); break; + default: + continue; } + if ((watchpoint->type & WATCHPOINT_CHANGE) && newValue == oldValue) { + continue; + } + info->type.wp.oldValue = oldValue; info->type.wp.newValue = newValue; info->address = address; info->type.wp.watchType = watchpoint->type; diff --git a/src/sm83/debugger/memory-debugger.c b/src/sm83/debugger/memory-debugger.c index c41350c67..2cd81669e 100644 --- a/src/sm83/debugger/memory-debugger.c +++ b/src/sm83/debugger/memory-debugger.c @@ -55,7 +55,11 @@ static bool _checkWatchpoints(struct SM83Debugger* debugger, uint16_t address, s return false; } } - info->type.wp.oldValue = debugger->originalMemory.load8(debugger->cpu, address); + uint8_t oldValue = debugger->originalMemory.load8(debugger->cpu, address); + if ((watchpoint->type & WATCHPOINT_CHANGE) && newValue == oldValue) { + continue; + } + info->type.wp.oldValue = oldValue; info->type.wp.newValue = newValue; info->address = address; info->type.wp.watchType = watchpoint->type;