From 083585b56525e5985291ff7ee895857ae618a5ea Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 28 Nov 2022 22:37:31 -0800 Subject: [PATCH 01/20] GB Audio: Fix channels 1/2 not playing when resetting volume (fixes #2614) --- CHANGES | 1 + src/gb/audio.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index daa24e880..73b36504c 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ Features: - New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81 - Debugger: Add range watchpoints Emulation fixes: + - GB Audio: Fix channels 1/2 not playing when resetting volume (fixes mgba.io/i/2614) - GB Serialize: Don't write BGP/OBP when loading SCGB state (fixes mgba.io/i/2694) - GB SIO: Further fix bidirectional transfer starting - GBA: Fix resetting key IRQ state (fixes mgba.io/i/2716) diff --git a/src/gb/audio.c b/src/gb/audio.c index 0b6a03ecb..26675a983 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -480,7 +480,7 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) { GBAudioSample(audio, timestamp); } - if (audio->playingCh1 && (channels & 0x1)) { + if (audio->playingCh1 && (channels & 0x1) && audio->ch1.envelope.dead != 2) { int period = 4 * (2048 - audio->ch1.control.frequency) * audio->timingFactor; int32_t diff = timestamp - audio->ch1.lastUpdate; if (diff >= period) { @@ -490,7 +490,7 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) { _updateSquareSample(&audio->ch1); } } - if (audio->playingCh2 && (channels & 0x2)) { + if (audio->playingCh2 && (channels & 0x2) && audio->ch2.envelope.dead != 2) { int period = 4 * (2048 - audio->ch2.control.frequency) * audio->timingFactor; int32_t diff = timestamp - audio->ch2.lastUpdate; if (diff >= period) { @@ -863,7 +863,7 @@ bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudi envelope->currentVolume &= 0xF; } _updateEnvelopeDead(envelope); - return (envelope->initialVolume || envelope->direction) && envelope->dead != 2; + return envelope->initialVolume || envelope->direction; } static void _updateSquareSample(struct GBAudioSquareChannel* ch) { From 2ba42761b8d96346ed9b5b3f5da6f88e301ade64 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 29 Nov 2022 02:20:02 -0800 Subject: [PATCH 02/20] Libretro: Add back missing audio overkill (fixes #2734) --- src/platform/libretro/libretro.c | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index 9bbd55ae6..2c0184d99 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -617,6 +617,39 @@ void retro_run(void) { core->desiredVideoDimensions(core, &width, &height); videoCallback(outputBuffer, width, height, BYTES_PER_PIXEL * 256); +#ifdef M_CORE_GBA + if (core->platform(core) == mPLATFORM_GBA) { + blip_t *audioChannelLeft = core->getAudioChannel(core, 0); + blip_t *audioChannelRight = core->getAudioChannel(core, 1); + int samplesAvail = blip_samples_avail(audioChannelLeft); + if (samplesAvail > 0) { + /* Update 'running average' of number of + * samples per frame. + * Note that this is not a true running + * average, but just a leaky-integrator/ + * exponential moving average, used because + * it is simple and fast (i.e. requires no + * window of samples). */ + audioSamplesPerFrameAvg = (SAMPLES_PER_FRAME_MOVING_AVG_ALPHA * (float)samplesAvail) + + ((1.0f - SAMPLES_PER_FRAME_MOVING_AVG_ALPHA) * audioSamplesPerFrameAvg); + size_t samplesToRead = (size_t)(audioSamplesPerFrameAvg); + /* Resize audio output buffer, if required */ + if (audioSampleBufferSize < (samplesToRead * 2)) { + audioSampleBufferSize = (samplesToRead * 2); + audioSampleBuffer = realloc(audioSampleBuffer, audioSampleBufferSize * sizeof(int16_t)); + } + int produced = blip_read_samples(audioChannelLeft, audioSampleBuffer, samplesToRead, true); + blip_read_samples(audioChannelRight, audioSampleBuffer + 1, samplesToRead, true); + if (produced > 0) { + if (audioLowPassEnabled) { + _audioLowPassFilter(audioSampleBuffer, produced); + } + audioCallback(audioSampleBuffer, (size_t)produced); + } + } + } +#endif + if (rumbleCallback) { if (rumbleUp) { rumbleCallback(0, RETRO_RUMBLE_STRONG, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); From 3385f02b5154b22154db6be8aa7856a47751ec9c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 30 Nov 2022 17:44:53 -0800 Subject: [PATCH 03/20] GBA DMA: Minor optimization of warm function --- src/gba/dma.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/gba/dma.c b/src/gba/dma.c index 14b9fb777..60a8eb056 100644 --- a/src/gba/dma.c +++ b/src/gba/dma.c @@ -244,7 +244,6 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { struct GBAMemory* memory = &gba->memory; struct ARMCore* cpu = gba->cpu; uint32_t width = 2 << GBADMARegisterGetWidth(info->reg); - int32_t wordsRemaining = info->nextCount; uint32_t source = info->nextSource; uint32_t dest = info->nextDest; uint32_t sourceRegion = source >> BASE_OFFSET; @@ -252,6 +251,8 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { int32_t cycles = 2; gba->cpuBlocked = true; + gba->performingDMA = 1 | (number << 1); + if (info->count == info->nextCount) { if (width == 4) { cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion]; @@ -267,12 +268,10 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { } info->when += cycles; - gba->performingDMA = 1 | (number << 1); if (width == 4) { if (source) { memory->dmaTransferRegister = cpu->memory.load32(cpu, source, 0); } - gba->bus = memory->dmaTransferRegister; cpu->memory.store32(cpu, dest, memory->dmaTransferRegister, 0); } else { if (sourceRegion == REGION_CART2_EX && (memory->savedata.type == SAVEDATA_EEPROM || memory->savedata.type == SAVEDATA_EEPROM512)) { @@ -288,14 +287,13 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { GBASavedataInitEEPROM(&memory->savedata); } if (memory->savedata.type == SAVEDATA_EEPROM512 || memory->savedata.type == SAVEDATA_EEPROM) { - GBASavedataWriteEEPROM(&memory->savedata, memory->dmaTransferRegister, wordsRemaining); + GBASavedataWriteEEPROM(&memory->savedata, memory->dmaTransferRegister, info->nextCount); } } else { cpu->memory.store16(cpu, dest, memory->dmaTransferRegister, 0); - } - gba->bus = memory->dmaTransferRegister; } + gba->bus = memory->dmaTransferRegister; int sourceOffset; if (info->nextSource >= BASE_CART0 && info->nextSource < BASE_CART_SRAM && GBADMARegisterGetSrcControl(info->reg) < 3) { @@ -305,15 +303,12 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { } int destOffset = DMA_OFFSET[GBADMARegisterGetDestControl(info->reg)] * width; if (source) { - source += sourceOffset; + info->nextSource += sourceOffset; } - dest += destOffset; - --wordsRemaining; - gba->performingDMA = 0; + info->nextDest += destOffset; + --info->nextCount; - info->nextCount = wordsRemaining; - info->nextSource = source; - info->nextDest = dest; + gba->performingDMA = 0; int i; for (i = 0; i < 4; ++i) { @@ -324,7 +319,7 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { } } - if (!wordsRemaining) { + if (!info->nextCount) { info->nextCount |= 0x80000000; if (sourceRegion < REGION_CART0 || destRegion < REGION_CART0) { info->when += 2; From e9ec009836d9501909a519fc94b52d09c2ad6ddd Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 7 Dec 2022 01:21:21 -0800 Subject: [PATCH 04/20] GB Audio: Fix channel 3 volume being changed between samples (fixes #1896) --- CHANGES | 1 + src/gb/audio.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/CHANGES b/CHANGES index 73b36504c..07d262ca1 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ Features: - Debugger: Add range watchpoints Emulation fixes: - GB Audio: Fix channels 1/2 not playing when resetting volume (fixes mgba.io/i/2614) + - GB Audio: Fix channel 3 volume being changed between samples (fixes mgba.io/i/1896) - GB Serialize: Don't write BGP/OBP when loading SCGB state (fixes mgba.io/i/2694) - GB SIO: Further fix bidirectional transfer starting - GBA: Fix resetting key IRQ state (fixes mgba.io/i/2716) diff --git a/src/gb/audio.c b/src/gb/audio.c index 26675a983..516c6c663 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -269,6 +269,29 @@ void GBAudioWriteNR31(struct GBAudio* audio, uint8_t value) { void GBAudioWriteNR32(struct GBAudio* audio, uint8_t value) { GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4); audio->ch3.volume = GBAudioRegisterBankVolumeGetVolumeGB(value); + + audio->ch3.sample = audio->ch3.wavedata8[audio->ch3.window >> 1]; + if (!(audio->ch3.window & 1)) { + audio->ch3.sample >>= 4; + } + audio->ch3.sample &= 0xF; + int volume; + switch (audio->ch3.volume) { + case 0: + volume = 4; + break; + case 1: + volume = 0; + break; + case 2: + volume = 1; + break; + default: + case 3: + volume = 2; + break; + } + audio->ch3.sample >>= volume; } void GBAudioWriteNR33(struct GBAudio* audio, uint8_t value) { From b220c7a68b56d7572fc976be2a2200cb6d03f575 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 7 Dec 2022 02:35:08 -0800 Subject: [PATCH 05/20] Qt: Attempt to fix 5.8 build --- src/platform/qt/ForwarderController.cpp | 12 ++++++++++-- src/platform/qt/GBAApp.cpp | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/ForwarderController.cpp b/src/platform/qt/ForwarderController.cpp index fe0530a73..56e202019 100644 --- a/src/platform/qt/ForwarderController.cpp +++ b/src/platform/qt/ForwarderController.cpp @@ -180,6 +180,9 @@ void ForwarderController::downloadBuild(const QUrl& url) { connectReply(reply, BASE, &ForwarderController::gotBuild); connect(reply, &QNetworkReply::readyRead, this, [this, reply]() { + if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() / 100 != 2) { + return; + } QByteArray data = reply->readAll(); m_sourceFile.write(data); }); @@ -236,8 +239,13 @@ void ForwarderController::connectReply(QNetworkReply* reply, Download download, emit buildFailed(); }); - connect(reply, &QNetworkReply::finished, this, [this, reply, next]() { - (this->*next)(reply); + connect(reply, &QNetworkReply::finished, this, [this, reply, download, next]() { + if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() / 100 == 3) { + QNetworkReply* newReply = GBAApp::app()->httpGet(reply->header(QNetworkRequest::LocationHeader).toString()); + connectReply(newReply, download, next); + } else { + (this->*next)(reply); + } }); connect(reply, &QNetworkReply::downloadProgress, this, [this, download](qint64 bytesReceived, qint64 bytesTotal) { emit downloadProgress(download, bytesReceived, bytesTotal); diff --git a/src/platform/qt/GBAApp.cpp b/src/platform/qt/GBAApp.cpp index 1e3c6a894..30287262a 100644 --- a/src/platform/qt/GBAApp.cpp +++ b/src/platform/qt/GBAApp.cpp @@ -82,7 +82,9 @@ GBAApp::GBAApp(int& argc, char* argv[], ConfigController* config) m_configController->updateOption("useDiscordPresence"); #endif +#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) m_netman.setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy); +#endif cleanupAfterUpdate(); From dc5f6e37e133c6cd509a969aaf493362363b6118 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 7 Dec 2022 20:56:16 -0800 Subject: [PATCH 06/20] GB Audio: Initialize ch3 window value --- src/gb/audio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gb/audio.c b/src/gb/audio.c index 516c6c663..a1af17247 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -116,6 +116,7 @@ void GBAudioReset(struct GBAudio* audio) { audio->ch3.wavedata8[13] = 0xFF; audio->ch3.wavedata8[14] = 0x00; audio->ch3.wavedata8[15] = 0xFF; + audio->ch3.window = 0; audio->ch4 = (struct GBAudioNoiseChannel) { .envelope = { .dead = 2 } }; audio->frame = 0; audio->sampleInterval = SAMPLE_INTERVAL * GB_MAX_SAMPLES; From 4f70b313fcf82b043bee232dd5af231a7755e1d8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 8 Dec 2022 01:20:51 -0800 Subject: [PATCH 07/20] GB Memory: Actually, HDMAs should start when LCD is off (fixes #2662) --- CHANGES | 1 + src/gb/memory.c | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 07d262ca1..ec39e3bce 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ Features: Emulation fixes: - GB Audio: Fix channels 1/2 not playing when resetting volume (fixes mgba.io/i/2614) - GB Audio: Fix channel 3 volume being changed between samples (fixes mgba.io/i/1896) + - GB Memory: Actually, HDMAs should start when LCD is off (fixes mgba.io/i/2662) - GB Serialize: Don't write BGP/OBP when loading SCGB state (fixes mgba.io/i/2694) - GB SIO: Further fix bidirectional transfer starting - GBA: Fix resetting key IRQ state (fixes mgba.io/i/2716) diff --git a/src/gb/memory.c b/src/gb/memory.c index 50b9b7d6f..5c4d97876 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -558,7 +558,7 @@ uint8_t GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) { gb->memory.hdmaDest |= 0x8000; bool wasHdma = gb->memory.isHdma; gb->memory.isHdma = value & 0x80; - if ((!wasHdma && !gb->memory.isHdma) || (GBRegisterLCDCIsEnable(gb->memory.io[GB_REG_LCDC]) && gb->video.mode == 0)) { + if ((!wasHdma && !gb->memory.isHdma) || gb->video.mode == 0) { if (gb->memory.isHdma) { gb->memory.hdmaRemaining = 0x10; } else { @@ -566,8 +566,6 @@ uint8_t GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) { } gb->cpuBlocked = true; mTimingSchedule(&gb->timing, &gb->memory.hdmaEvent, 0); - } else if (gb->memory.isHdma && !GBRegisterLCDCIsEnable(gb->memory.io[GB_REG_LCDC])) { - return 0x80 | ((value + 1) & 0x7F); } return value & 0x7F; } From 50fd46506c01b6028f1c27c097e9e4ecbf4caf54 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 11 Dec 2022 19:08:53 -0800 Subject: [PATCH 08/20] GB Audio: Fix up boot sequence --- CHANGES | 1 + src/gb/audio.c | 1 - src/gb/gb.c | 21 ++++++++++++++++++++- src/gb/io.c | 31 +------------------------------ 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index ec39e3bce..f88219117 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ Features: Emulation fixes: - GB Audio: Fix channels 1/2 not playing when resetting volume (fixes mgba.io/i/2614) - GB Audio: Fix channel 3 volume being changed between samples (fixes mgba.io/i/1896) + - GB Audio: Fix up boot sequence - GB Memory: Actually, HDMAs should start when LCD is off (fixes mgba.io/i/2662) - GB Serialize: Don't write BGP/OBP when loading SCGB state (fixes mgba.io/i/2694) - GB SIO: Further fix bidirectional transfer starting diff --git a/src/gb/audio.c b/src/gb/audio.c index a1af17247..516c6c663 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -116,7 +116,6 @@ void GBAudioReset(struct GBAudio* audio) { audio->ch3.wavedata8[13] = 0xFF; audio->ch3.wavedata8[14] = 0x00; audio->ch3.wavedata8[15] = 0xFF; - audio->ch3.window = 0; audio->ch4 = (struct GBAudioNoiseChannel) { .envelope = { .dead = 2 } }; audio->frame = 0; audio->sampleInterval = SAMPLE_INTERVAL * GB_MAX_SAMPLES; diff --git a/src/gb/gb.c b/src/gb/gb.c index dc3a37191..a3a870f28 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -596,13 +596,13 @@ void GBReset(struct SM83Core* cpu) { GBVideoReset(&gb->video); GBTimerReset(&gb->timer); GBIOReset(gb); + GBAudioReset(&gb->audio); if (!gb->biosVf && gb->memory.rom) { GBSkipBIOS(gb); } else { mTimingSchedule(&gb->timing, &gb->timer.event, 0); } - GBAudioReset(&gb->audio); GBSIOReset(&gb->sio); cpu->memory.setActiveRegion(cpu, cpu->pc); @@ -744,6 +744,25 @@ void GBSkipBIOS(struct GB* gb) { GBUnmapBIOS(gb); } + GBIOWrite(gb, GB_REG_NR52, 0xF1); + GBIOWrite(gb, GB_REG_NR14, 0x3F); + GBIOWrite(gb, GB_REG_NR10, 0x80); + GBIOWrite(gb, GB_REG_NR11, 0xBF); + GBIOWrite(gb, GB_REG_NR12, 0xF3); + GBIOWrite(gb, GB_REG_NR13, 0xF3); + GBIOWrite(gb, GB_REG_NR24, 0x3F); + GBIOWrite(gb, GB_REG_NR21, 0x3F); + GBIOWrite(gb, GB_REG_NR22, 0x00); + GBIOWrite(gb, GB_REG_NR34, 0x3F); + GBIOWrite(gb, GB_REG_NR30, 0x7F); + GBIOWrite(gb, GB_REG_NR31, 0xFF); + GBIOWrite(gb, GB_REG_NR32, 0x9F); + GBIOWrite(gb, GB_REG_NR44, 0x3F); + GBIOWrite(gb, GB_REG_NR41, 0xFF); + GBIOWrite(gb, GB_REG_NR42, 0x00); + GBIOWrite(gb, GB_REG_NR43, 0x00); + GBIOWrite(gb, GB_REG_NR50, 0x77); + GBIOWrite(gb, GB_REG_NR51, 0xF3); GBIOWrite(gb, GB_REG_LCDC, 0x91); gb->memory.io[GB_REG_BANK] = 0x1; GBVideoSkipBIOS(&gb->video); diff --git a/src/gb/io.c b/src/gb/io.c index 06a7927cd..511989d0a 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -162,36 +162,7 @@ void GBIOReset(struct GB* gb) { GBIOWrite(gb, GB_REG_TMA, 0); GBIOWrite(gb, GB_REG_TAC, 0); GBIOWrite(gb, GB_REG_IF, 1); - gb->audio.playingCh1 = false; - gb->audio.playingCh2 = false; - gb->audio.playingCh3 = false; - gb->audio.playingCh4 = false; - GBIOWrite(gb, GB_REG_NR52, 0xF1); - GBIOWrite(gb, GB_REG_NR14, 0x3F); - GBIOWrite(gb, GB_REG_NR10, 0x80); - GBIOWrite(gb, GB_REG_NR11, 0xBF); - GBIOWrite(gb, GB_REG_NR12, 0xF3); - GBIOWrite(gb, GB_REG_NR13, 0xF3); - GBIOWrite(gb, GB_REG_NR24, 0x3F); - GBIOWrite(gb, GB_REG_NR21, 0x3F); - GBIOWrite(gb, GB_REG_NR22, 0x00); - GBIOWrite(gb, GB_REG_NR34, 0x3F); - GBIOWrite(gb, GB_REG_NR30, 0x7F); - GBIOWrite(gb, GB_REG_NR31, 0xFF); - GBIOWrite(gb, GB_REG_NR32, 0x9F); - GBIOWrite(gb, GB_REG_NR44, 0x3F); - GBIOWrite(gb, GB_REG_NR41, 0xFF); - GBIOWrite(gb, GB_REG_NR42, 0x00); - GBIOWrite(gb, GB_REG_NR43, 0x00); - GBIOWrite(gb, GB_REG_NR50, 0x77); - GBIOWrite(gb, GB_REG_NR51, 0xF3); - if (!gb->biosVf) { - GBIOWrite(gb, GB_REG_LCDC, 0x91); - gb->memory.io[GB_REG_BANK] = 1; - } else { - GBIOWrite(gb, GB_REG_LCDC, 0x00); - gb->memory.io[GB_REG_BANK] = 0xFF; - } + GBIOWrite(gb, GB_REG_LCDC, 0x00); GBIOWrite(gb, GB_REG_SCY, 0x00); GBIOWrite(gb, GB_REG_SCX, 0x00); GBIOWrite(gb, GB_REG_LYC, 0x00); From 27076733d4ef556634efcd23d4bf575e6b05b1d8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 11 Dec 2022 19:09:21 -0800 Subject: [PATCH 09/20] GB Audio: Fix updating channels other than 2 when writing NR5x --- CHANGES | 1 + src/gb/audio.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index f88219117..d06564d26 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ Emulation fixes: - GB Audio: Fix channels 1/2 not playing when resetting volume (fixes mgba.io/i/2614) - GB Audio: Fix channel 3 volume being changed between samples (fixes mgba.io/i/1896) - GB Audio: Fix up boot sequence + - GB Audio: Fix updating channels other than 2 when writing NR5x - GB Memory: Actually, HDMAs should start when LCD is off (fixes mgba.io/i/2662) - GB Serialize: Don't write BGP/OBP when loading SCGB state (fixes mgba.io/i/2694) - GB SIO: Further fix bidirectional transfer starting diff --git a/src/gb/audio.c b/src/gb/audio.c index 516c6c663..8bce46e07 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -400,13 +400,13 @@ void GBAudioWriteNR44(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR50(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0xF); audio->volumeRight = GBRegisterNR50GetVolumeRight(value); audio->volumeLeft = GBRegisterNR50GetVolumeLeft(value); } void GBAudioWriteNR51(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0xF); audio->ch1Right = GBRegisterNR51GetCh1Right(value); audio->ch2Right = GBRegisterNR51GetCh2Right(value); audio->ch3Right = GBRegisterNR51GetCh3Right(value); From 1127cf8b849106dee61781269aa1fd907327f6a8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 12 Dec 2022 03:12:06 -0800 Subject: [PATCH 10/20] Qt: Fix proxy context creation on Nvidia (fixes #2746) --- src/platform/qt/DisplayGL.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index b8c0f8cd9..9f5729a67 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -425,10 +425,10 @@ void DisplayGL::setVideoProxy(std::shared_ptr proxy) { void DisplayGL::setupProxyThread() { m_proxyContext->moveToThread(&m_proxyThread); + m_proxySurface.create(); connect(&m_proxyThread, &QThread::started, m_proxyContext.get(), [this]() { m_proxyContext->setShareContext(m_painter->shareContext()); m_proxyContext->create(); - m_proxySurface.create(); m_proxyContext->makeCurrent(&m_proxySurface); #if defined(_WIN32) && defined(USE_EPOXY) epoxy_handle_external_wglMakeCurrent(); @@ -576,6 +576,7 @@ void PainterGL::create() { m_backend->filter = false; m_backend->lockAspectRatio = false; m_backend->interframeBlending = false; + m_gl->doneCurrent(); emit created(); } From 4626cac9e8c532775359daba7ce5fcb1e7dd4028 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 12 Dec 2022 03:58:12 -0800 Subject: [PATCH 11/20] Qt: Tentative fix for renderer switching crash --- src/platform/qt/DisplayGL.cpp | 5 +++++ src/platform/qt/Window.cpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 9f5729a67..3816a658b 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -938,6 +938,11 @@ QOpenGLContext* PainterGL::shareContext() { void PainterGL::updateFramebufferHandle() { QOpenGLFunctions_Baseline* fn = m_gl->versionFunctions(); fn->glFinish(); + + CoreController::Interrupter interrupter(m_context); + if (!m_context->hardwareAccelerated()) { + return; + } enqueue(m_bridgeTexIn); m_context->setFramebufferHandle(m_bridgeTexIn); } diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 02460aeb8..cdfb5b9c1 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1061,6 +1061,8 @@ void Window::changeRenderer() { if (!m_controller) { return; } + + CoreController::Interrupter interrupter(m_controller); if (m_config->getOption("hwaccelVideo").toInt() && m_display->supportsShaders() && m_controller->supportsFeature(CoreController::Feature::OPENGL)) { std::shared_ptr proxy = m_display->videoProxy(); if (!proxy) { From b3f9d9b18621258a5ee64293745177404dbf2be0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 12 Dec 2022 14:31:41 -0800 Subject: [PATCH 12/20] Qt: Fix loading/unloading shaders --- src/platform/qt/DisplayGL.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 3816a658b..ec496e7ad 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -887,12 +887,20 @@ void PainterGL::setShaders(struct VDir* dir) { return; } #if defined(BUILD_GLES2) || defined(BUILD_GLES3) + if (!m_started) { + makeCurrent(); + } + if (m_shader.passes) { mGLES2ShaderDetach(reinterpret_cast(m_backend)); mGLES2ShaderFree(&m_shader); } mGLES2ShaderLoad(&m_shader, dir); mGLES2ShaderAttach(reinterpret_cast(m_backend), static_cast(m_shader.passes), m_shader.nPasses); + + if (!m_started) { + m_gl->doneCurrent(); + } #endif } @@ -901,10 +909,18 @@ void PainterGL::clearShaders() { return; } #if defined(BUILD_GLES2) || defined(BUILD_GLES3) + if (!m_started) { + makeCurrent(); + } + if (m_shader.passes) { mGLES2ShaderDetach(reinterpret_cast(m_backend)); mGLES2ShaderFree(&m_shader); } + + if (!m_started) { + m_gl->doneCurrent(); + } #endif } From ab82b2c856f44049604019452ff01c6f201ed78f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 13 Dec 2022 15:18:21 -0800 Subject: [PATCH 13/20] GB IO: Fix BANK not getting initialized after recent change --- src/gb/io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gb/io.c b/src/gb/io.c index 511989d0a..ba4473550 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -174,6 +174,7 @@ void GBIOReset(struct GB* gb) { } GBIOWrite(gb, GB_REG_WY, 0x00); GBIOWrite(gb, GB_REG_WX, 0x00); + gb->memory.io[GB_REG_BANK] = 0xFF; if (gb->model & GB_MODEL_CGB) { GBIOWrite(gb, GB_REG_KEY0, 0); GBIOWrite(gb, GB_REG_JOYP, 0xFF); From 0ac446bedad95bf1d422691a16f5670a6758ff28 Mon Sep 17 00:00:00 2001 From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Fri, 16 Dec 2022 22:12:24 -0800 Subject: [PATCH 14/20] Check gba->mbVf for force skipping the BIOS (#2754) --- CHANGES | 1 + src/gba/core.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index d06564d26..04ab3c850 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,7 @@ Emulation fixes: - GBA Video: Ignore disabled backgrounds as OBJ blend target (fixes mgba.io/i/2489) - GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722) Other fixes: + - GBA: Fix forceskip BIOS logic for multiboot ROMs (fixes mgba.io/i/2753) - Qt: Manually split filename to avoid overzealous splitting (fixes mgba.io/i/2681) - Qt: Expand criteria for tag branch names (fixes mgba.io/i/2679) - Qt: Fix scanning specific e-Reader dotcodes (fixes mgba.io/i/2693) diff --git a/src/gba/core.c b/src/gba/core.c index 68ea66c79..b44c8aa5c 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -700,7 +700,7 @@ static void _GBACoreReset(struct mCore* core) { #endif ARMReset(core->cpu); - bool forceSkip = gba->romVf && GBAIsMB(gba->romVf); + bool forceSkip = gba->mbVf; if (!(forceSkip || core->opts.skipBios) && (gba->romVf || gba->memory.rom) && gba->pristineRomSize >= 0xA0 && gba->biosVf) { uint32_t crc = doCrc32(&gba->memory.rom[1], 0x9C); if (crc != LOGO_CRC32) { From 83578d915bece29d7497412ee531b0d5c9612e04 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 17 Dec 2022 00:21:07 -0800 Subject: [PATCH 15/20] Qt: Refactor and fix dequeueAll so keep mode keeps last draw tex too --- src/platform/qt/DisplayGL.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index ec496e7ad..86e115517 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -861,17 +861,23 @@ void PainterGL::dequeueAll(bool keep) { m_free.append(buffer); } } - m_queueTex.clear(); - m_freeTex.clear(); - for (auto tex : m_bridgeTexes) { - m_freeTex.enqueue(tex); - } - m_bridgeTexIn = m_freeTex.dequeue(); - m_bridgeTexOut = std::numeric_limits::max(); if (m_buffer && !keep) { m_free.append(m_buffer); m_buffer = nullptr; } + + m_queueTex.clear(); + m_freeTex.clear(); + for (auto tex : m_bridgeTexes) { + if (keep && tex == m_bridgeTexIn) { + continue; + } + m_freeTex.enqueue(tex); + } + if (!keep) { + m_bridgeTexIn = m_freeTex.dequeue(); + m_bridgeTexOut = std::numeric_limits::max(); + } } void PainterGL::setVideoProxy(std::shared_ptr proxy) { From d2949383d584cdf9a00f1e80d986eda0f8fb9dfb Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 17 Dec 2022 00:21:07 -0800 Subject: [PATCH 16/20] GBA: Clean up BIOS skip detection; add second multiboot entry --- src/gba/core.c | 6 +++--- src/gba/gba.c | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gba/core.c b/src/gba/core.c index b44c8aa5c..a50c11175 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -700,8 +700,8 @@ static void _GBACoreReset(struct mCore* core) { #endif ARMReset(core->cpu); - bool forceSkip = gba->mbVf; - if (!(forceSkip || core->opts.skipBios) && (gba->romVf || gba->memory.rom) && gba->pristineRomSize >= 0xA0 && gba->biosVf) { + bool forceSkip = gba->mbVf || core->opts.skipBios; + if (!forceSkip && (gba->romVf || gba->memory.rom) && gba->pristineRomSize >= 0xA0 && gba->biosVf) { uint32_t crc = doCrc32(&gba->memory.rom[1], 0x9C); if (crc != LOGO_CRC32) { mLOG(STATUS, WARN, "Invalid logo, skipping BIOS"); @@ -709,7 +709,7 @@ static void _GBACoreReset(struct mCore* core) { } } - if (forceSkip || (core->opts.skipBios && (gba->romVf || gba->memory.rom))) { + if (forceSkip) { GBASkipBIOS(core->board); } diff --git a/src/gba/gba.c b/src/gba/gba.c index f40e85ace..b26ec85af 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -275,8 +275,10 @@ void GBASkipBIOS(struct GBA* gba) { if (cpu->gprs[ARM_PC] == BASE_RESET + WORD_SIZE_ARM) { if (gba->memory.rom) { cpu->gprs[ARM_PC] = BASE_CART0; - } else { + } else if (gba->memory.wram[0x30]) { cpu->gprs[ARM_PC] = BASE_WORKING_RAM + 0xC0; + } else { + cpu->gprs[ARM_PC] = BASE_WORKING_RAM; } gba->video.vcount = 0x7E; gba->memory.io[REG_VCOUNT >> 1] = 0x7E; From 90893dff603f14d4bf45d5ae1e5028db8480d0b4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 18 Dec 2022 17:01:01 -0800 Subject: [PATCH 17/20] GBA Video: Fix #2489 in OpenGL renderer --- src/gba/renderers/gl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index 9d7ccafa7..b6ffa2aac 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -664,10 +664,12 @@ static const char* const _finalize = " if (((topFlags.y & 13) == 5 || topFlags.w > 0) && (bottomFlags.y & 2) == 2) {\n" " topPixel.rgb *= float(topFlags.z) / 16.;\n" " topPixel.rgb += bottomPixel.rgb * float(windowFlags.y) / 16.;\n" - " } else if ((topFlags.y & 13) == 9) {\n" - " topPixel.rgb += (1. - topPixel.rgb) * float(windowFlags.z) / 16.;\n" - " } else if ((topFlags.y & 13) == 13) {\n" - " topPixel.rgb -= topPixel.rgb * float(windowFlags.z) / 16.;\n" + " } else if (topFlags.w == 0) { \n" + " if ((topFlags.y & 13) == 9) {\n" + " topPixel.rgb += (1. - topPixel.rgb) * float(windowFlags.z) / 16.;\n" + " } else if ((topFlags.y & 13) == 13) {\n" + " topPixel.rgb -= topPixel.rgb * float(windowFlags.z) / 16.;\n" + " }\n" " }\n" " color = topPixel;\n" "}"; From 455e34edcfbb64fb3021a6219ded317a8af907b7 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 18 Dec 2022 21:48:08 -0800 Subject: [PATCH 18/20] Qt: glFlush is (thankfully) sufficient here --- src/platform/qt/DisplayGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 86e115517..4b0fcdce3 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -959,7 +959,7 @@ QOpenGLContext* PainterGL::shareContext() { void PainterGL::updateFramebufferHandle() { QOpenGLFunctions_Baseline* fn = m_gl->versionFunctions(); - fn->glFinish(); + fn->glFlush(); CoreController::Interrupter interrupter(m_context); if (!m_context->hardwareAccelerated()) { From 86bcbf171651804df0f77e5a2a104f36ae938c2a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 21 Dec 2022 22:13:23 -0800 Subject: [PATCH 19/20] Qt: Start OpenGL bug list with glFlush cross-thread on Windows (fixes #2761) --- src/platform/qt/CMakeLists.txt | 1 + src/platform/qt/DisplayGL.cpp | 9 ++++++++- src/platform/qt/OpenGLBug.cpp | 34 ++++++++++++++++++++++++++++++++++ src/platform/qt/OpenGLBug.h | 17 +++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/platform/qt/OpenGLBug.cpp create mode 100644 src/platform/qt/OpenGLBug.h diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 099bb9d8e..1bb8758c7 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -123,6 +123,7 @@ set(SOURCE_FILES MessagePainter.cpp MultiplayerController.cpp ObjView.cpp + OpenGLBug.cpp OverrideView.cpp PaletteView.cpp PlacementControl.cpp diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 4b0fcdce3..0528922fb 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -44,6 +44,8 @@ using QOpenGLFunctions_Baseline = QOpenGLFunctions_3_2_Core; #define OVERHEAD_NSEC 300000 #endif +#include "OpenGLBug.h" + using namespace QGBA; QHash DisplayGL::s_supports; @@ -959,7 +961,12 @@ QOpenGLContext* PainterGL::shareContext() { void PainterGL::updateFramebufferHandle() { QOpenGLFunctions_Baseline* fn = m_gl->versionFunctions(); - fn->glFlush(); + // TODO: Figure out why glFlush doesn't work here on Intel/Windows + if (glContextHasBug(OpenGLBug::CROSS_THREAD_FLUSH)) { + fn->glFinish(); + } else { + fn->glFlush(); + } CoreController::Interrupter interrupter(m_context); if (!m_context->hardwareAccelerated()) { diff --git a/src/platform/qt/OpenGLBug.cpp b/src/platform/qt/OpenGLBug.cpp new file mode 100644 index 000000000..e00310c56 --- /dev/null +++ b/src/platform/qt/OpenGLBug.cpp @@ -0,0 +1,34 @@ +/* Copyright (c) 2013-2022 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "OpenGLBug.h" + +#include +#include + +namespace QGBA { + +bool glContextHasBug(OpenGLBug bug) { + QOpenGLContext* context = QOpenGLContext::currentContext(); + if (!context) { + abort(); + } + QOpenGLFunctions* fn = context->functions(); + QString vendor(reinterpret_cast(fn->glGetString(GL_VENDOR))); + QString renderer(reinterpret_cast(fn->glGetString(GL_RENDERER))); + + switch (bug) { + case OpenGLBug::CROSS_THREAD_FLUSH: +#ifndef Q_OS_WIN + return false; +#else + return vendor == "Intel"; +#endif + default: + return false; + } +} + +} diff --git a/src/platform/qt/OpenGLBug.h b/src/platform/qt/OpenGLBug.h new file mode 100644 index 000000000..fda0ed555 --- /dev/null +++ b/src/platform/qt/OpenGLBug.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2013-2022 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#pragma once + +namespace QGBA { + +enum class OpenGLBug { + // mgba.io/i/2761 + CROSS_THREAD_FLUSH +}; + +bool glContextHasBug(OpenGLBug); + +} From 1b9671bf21c6332a08b49679174950adcb9e1c24 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 22 Dec 2022 16:02:12 -0800 Subject: [PATCH 20/20] GBA Cheats: Fix issues detecting unencrypted cheats (fixes #2724) --- CHANGES | 1 + src/gba/cheats.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 04ab3c850..00e8d7587 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,7 @@ Emulation fixes: - GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722) Other fixes: - GBA: Fix forceskip BIOS logic for multiboot ROMs (fixes mgba.io/i/2753) + - GBA Cheats: Fix issues detecting unencrypted cheats (fixes mgba.io/i/2724) - Qt: Manually split filename to avoid overzealous splitting (fixes mgba.io/i/2681) - Qt: Expand criteria for tag branch names (fixes mgba.io/i/2679) - Qt: Fix scanning specific e-Reader dotcodes (fixes mgba.io/i/2693) diff --git a/src/gba/cheats.c b/src/gba/cheats.c index ec92bc3c2..08848077b 100644 --- a/src/gba/cheats.c +++ b/src/gba/cheats.c @@ -126,13 +126,13 @@ static bool GBACheatAddAutodetect(struct GBACheatSet* set, uint32_t op1, uint32_ GBACheatSetGameSharkVersion(set, GBA_GS_PARV3); } - rgsaP = GBACheatGameSharkProbability(op1, op1); + rgsaP = GBACheatGameSharkProbability(op1, op2); if (rgsaP > maxProbability) { maxProbability = rgsaP; GBACheatSetGameSharkVersion(set, GBA_GS_GSAV1_RAW); } - rparP = GBACheatProActionReplayProbability(op1, op1); + rparP = GBACheatProActionReplayProbability(op1, op2); if (rparP > maxProbability) { maxProbability = rparP; GBACheatSetGameSharkVersion(set, GBA_GS_PARV3_RAW);