mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
3b379d7e8d
6
CHANGES
6
CHANGES
|
@ -65,6 +65,12 @@ Bugfixes:
|
|||
- GBA I/O: Fix writing to DISPCNT CGB flag (fixes mgba.io/i/902)
|
||||
- GBA Memory: Partially revert prefetch changes (fixes mgba.io/i/840)
|
||||
- PSP2: Fix issues causing poor audio
|
||||
- Wii: Fix screen tear when unpausing
|
||||
- GBA: Fix some GBA ROM misdetection (fixes mgba.io/i/978)
|
||||
- GBA Hardware: RTC accuracy improvements
|
||||
- GB Timer: Minor accuracy improvements
|
||||
- GB Audio: Clock frame events on DIV
|
||||
- GBA: Fix SharkPort saves for EEPROM games
|
||||
Misc:
|
||||
- GBA Timer: Use global cycles for timers
|
||||
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
fail: true
|
|
@ -1 +0,0 @@
|
|||
fail: true
|
|
@ -1 +0,0 @@
|
|||
fail: true
|
|
@ -232,6 +232,8 @@ void GBAudioWriteNR50(struct GBAudio* audio, uint8_t);
|
|||
void GBAudioWriteNR51(struct GBAudio* audio, uint8_t);
|
||||
void GBAudioWriteNR52(struct GBAudio* audio, uint8_t);
|
||||
|
||||
void GBAudioUpdateFrame(struct GBAudio* audio, struct mTiming* timing);
|
||||
|
||||
void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right);
|
||||
|
||||
struct GBSerializedPSGState;
|
||||
|
|
|
@ -102,7 +102,7 @@ void GBASavedataDeinit(struct GBASavedata* savedata);
|
|||
|
||||
void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback);
|
||||
void GBASavedataUnmask(struct GBASavedata* savedata);
|
||||
size_t GBASavedataSize(struct GBASavedata* savedata);
|
||||
size_t GBASavedataSize(const struct GBASavedata* savedata);
|
||||
bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out);
|
||||
bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in);
|
||||
void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming);
|
||||
|
|
|
@ -109,10 +109,12 @@ void GBAudioReset(struct GBAudio* audio) {
|
|||
mTimingDeschedule(audio->timing, &audio->ch3Fade);
|
||||
mTimingDeschedule(audio->timing, &audio->ch4Event);
|
||||
mTimingDeschedule(audio->timing, &audio->sampleEvent);
|
||||
mTimingSchedule(audio->timing, &audio->frameEvent, 0);
|
||||
if (audio->style != GB_AUDIO_GBA) {
|
||||
mTimingSchedule(audio->timing, &audio->sampleEvent, 0);
|
||||
}
|
||||
if (audio->style == GB_AUDIO_GBA) {
|
||||
mTimingSchedule(audio->timing, &audio->frameEvent, 0);
|
||||
}
|
||||
audio->ch1 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } };
|
||||
audio->ch2 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } };
|
||||
audio->ch3 = (struct GBAudioWaveChannel) { .bank = 0 };
|
||||
|
@ -486,7 +488,13 @@ void GBAudioWriteNR52(struct GBAudio* audio, uint8_t value) {
|
|||
|
||||
void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
||||
struct GBAudio* audio = user;
|
||||
GBAudioUpdateFrame(audio, timing);
|
||||
if (audio->style == GB_AUDIO_GBA) {
|
||||
mTimingSchedule(timing, &audio->frameEvent, audio->timingFactor * FRAME_CYCLES - cyclesLate);
|
||||
}
|
||||
}
|
||||
|
||||
void GBAudioUpdateFrame(struct GBAudio* audio, struct mTiming* timing) {
|
||||
int frame = (audio->frame + 1) & 7;
|
||||
audio->frame = frame;
|
||||
|
||||
|
@ -576,8 +584,6 @@ void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
mTimingSchedule(timing, &audio->frameEvent, audio->timingFactor * FRAME_CYCLES - cyclesLate);
|
||||
}
|
||||
|
||||
void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) {
|
||||
|
@ -959,8 +965,10 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt
|
|||
audio->playingCh4 = !!(*audio->nr52 & 0x0008);
|
||||
audio->enable = GBAudioEnableGetEnable(*audio->nr52);
|
||||
|
||||
LOAD_32LE(when, 0, &state->ch1.nextFrame);
|
||||
mTimingSchedule(audio->timing, &audio->frameEvent, when);
|
||||
if (audio->style == GB_AUDIO_GBA) {
|
||||
LOAD_32LE(when, 0, &state->ch1.nextFrame);
|
||||
mTimingSchedule(audio->timing, &audio->frameEvent, when);
|
||||
}
|
||||
|
||||
LOAD_32LE(flags, 0, flagsIn);
|
||||
audio->frame = GBSerializedAudioFlagsGetFrame(flags);
|
||||
|
|
11
src/gb/io.c
11
src/gb/io.c
|
@ -380,8 +380,17 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
|
|||
}
|
||||
break;
|
||||
case REG_TIMA:
|
||||
if (value && mTimingUntil(&gb->timing, &gb->timer.irq) > 1) {
|
||||
mTimingDeschedule(&gb->timing, &gb->timer.irq);
|
||||
}
|
||||
if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case REG_TMA:
|
||||
// Handled transparently by the registers
|
||||
if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) {
|
||||
gb->memory.io[REG_TIMA] = value;
|
||||
}
|
||||
break;
|
||||
case REG_TAC:
|
||||
value = GBTimerUpdateTAC(&gb->timer, value);
|
||||
|
|
|
@ -27,9 +27,13 @@ static void _GBTimerDivIncrement(struct GBTimer* timer, uint32_t cyclesLate) {
|
|||
if (timer->timaPeriod > 0 && (timer->internalDiv & (timer->timaPeriod - 1)) == timer->timaPeriod - 1) {
|
||||
++timer->p->memory.io[REG_TIMA];
|
||||
if (!timer->p->memory.io[REG_TIMA]) {
|
||||
mTimingSchedule(&timer->p->timing, &timer->irq, 4 - cyclesLate);
|
||||
mTimingSchedule(&timer->p->timing, &timer->irq, 7 - ((timer->p->cpu->executionState - cyclesLate) & 3));
|
||||
}
|
||||
}
|
||||
int timingFactor = 0x3FF >> !timer->p->doubleSpeed;
|
||||
if ((timer->internalDiv & timingFactor) == timingFactor) {
|
||||
GBAudioUpdateFrame(&timer->p->audio, &timer->p->timing);
|
||||
}
|
||||
++timer->internalDiv;
|
||||
timer->p->memory.io[REG_DIV] = timer->internalDiv >> 4;
|
||||
}
|
||||
|
@ -69,13 +73,17 @@ void GBTimerReset(struct GBTimer* timer) {
|
|||
void GBTimerDivReset(struct GBTimer* timer) {
|
||||
timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event);
|
||||
mTimingDeschedule(&timer->p->timing, &timer->event);
|
||||
_GBTimerDivIncrement(timer, (timer->p->cpu->executionState + 1) & 3);
|
||||
if (timer->internalDiv & (timer->timaPeriod >> 1)) {
|
||||
_GBTimerDivIncrement(timer, 0);
|
||||
if (((timer->internalDiv << 1) | ((timer->nextDiv >> 3) & 1)) & timer->timaPeriod) {
|
||||
++timer->p->memory.io[REG_TIMA];
|
||||
if (!timer->p->memory.io[REG_TIMA]) {
|
||||
mTimingSchedule(&timer->p->timing, &timer->irq, 4 - ((timer->p->cpu->executionState + 1) & 3));
|
||||
mTimingSchedule(&timer->p->timing, &timer->irq, 7 - (timer->p->cpu->executionState & 3));
|
||||
}
|
||||
}
|
||||
int timingFactor = 0x200 >> !timer->p->doubleSpeed;
|
||||
if (timer->internalDiv & 0x200) {
|
||||
GBAudioUpdateFrame(&timer->p->audio, &timer->p->timing);
|
||||
}
|
||||
timer->p->memory.io[REG_DIV] = 0;
|
||||
timer->internalDiv = 0;
|
||||
timer->nextDiv = GB_DMG_DIV_PERIOD;
|
||||
|
@ -101,7 +109,7 @@ uint8_t GBTimerUpdateTAC(struct GBTimer* timer, GBRegisterTAC tac) {
|
|||
|
||||
timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event);
|
||||
mTimingDeschedule(&timer->p->timing, &timer->event);
|
||||
_GBTimerDivIncrement(timer, (timer->p->cpu->executionState + 1) & 3);
|
||||
_GBTimerDivIncrement(timer, (timer->p->cpu->executionState + 2) & 3);
|
||||
timer->nextDiv += GB_DMG_DIV_PERIOD;
|
||||
mTimingSchedule(&timer->p->timing, &timer->event, timer->nextDiv);
|
||||
} else {
|
||||
|
|
|
@ -33,6 +33,9 @@ const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
|
|||
static const size_t GBA_ROM_MAGIC_OFFSET = 3;
|
||||
static const uint8_t GBA_ROM_MAGIC[] = { 0xEA };
|
||||
|
||||
static const size_t GBA_ROM_MAGIC_OFFSET2 = 0xB2;
|
||||
static const uint8_t GBA_ROM_MAGIC2[] = { 0x96 };
|
||||
|
||||
static const size_t GBA_MB_MAGIC_OFFSET = 0xC0;
|
||||
|
||||
static void GBAInit(void* cpu, struct mCPUComponent* component);
|
||||
|
@ -542,17 +545,48 @@ bool GBAIsROM(struct VFile* vf) {
|
|||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t signature[sizeof(GBA_ROM_MAGIC) + sizeof(GBA_ROM_MAGIC2)];
|
||||
if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) {
|
||||
return false;
|
||||
}
|
||||
uint8_t signature[sizeof(GBA_ROM_MAGIC)];
|
||||
if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) {
|
||||
if (vf->read(vf, &signature, sizeof(GBA_ROM_MAGIC)) != sizeof(GBA_ROM_MAGIC)) {
|
||||
return false;
|
||||
}
|
||||
if (memcmp(signature, GBA_ROM_MAGIC, sizeof(GBA_ROM_MAGIC)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET2, SEEK_SET) < 0) {
|
||||
return false;
|
||||
}
|
||||
if (vf->read(vf, &signature, sizeof(GBA_ROM_MAGIC2)) != sizeof(GBA_ROM_MAGIC2)) {
|
||||
return false;
|
||||
}
|
||||
if (memcmp(signature, GBA_ROM_MAGIC2, sizeof(GBA_ROM_MAGIC2)) != 0) {
|
||||
// If the signature byte is missing then we must be using an unfixed ROM
|
||||
uint32_t buffer[0x9C / sizeof(uint32_t)];
|
||||
if (vf->seek(vf, 0x4, SEEK_SET) < 0) {
|
||||
return false;
|
||||
}
|
||||
if (vf->read(vf, &buffer, sizeof(buffer)) != sizeof(buffer)) {
|
||||
return false;
|
||||
}
|
||||
uint32_t bits = 0;
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(buffer) / sizeof(*buffer); ++i) {
|
||||
bits |= buffer[i];
|
||||
}
|
||||
if (bits) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (GBAIsBIOS(vf)) {
|
||||
return false;
|
||||
}
|
||||
return memcmp(signature, GBA_ROM_MAGIC, sizeof(signature)) == 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GBAIsMB(struct VFile* vf) {
|
||||
|
|
|
@ -63,7 +63,7 @@ void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
|
|||
|
||||
void GBAHardwareClear(struct GBACartridgeHardware* hw) {
|
||||
hw->devices = HW_NONE | (hw->devices & HW_GB_PLAYER_DETECTION);
|
||||
hw->direction = GPIO_WRITE_ONLY;
|
||||
hw->readWrite = GPIO_WRITE_ONLY;
|
||||
hw->pinState = 0;
|
||||
hw->direction = 0;
|
||||
|
||||
|
@ -79,7 +79,7 @@ void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uin
|
|||
switch (address) {
|
||||
case GPIO_REG_DATA:
|
||||
hw->pinState &= ~hw->direction;
|
||||
hw->pinState |= value;
|
||||
hw->pinState |= value & hw->direction;
|
||||
_readPins(hw);
|
||||
break;
|
||||
case GPIO_REG_DIRECTION:
|
||||
|
@ -92,13 +92,13 @@ void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uin
|
|||
mLOG(GBA_HW, WARN, "Invalid GPIO address");
|
||||
}
|
||||
if (hw->readWrite) {
|
||||
uint16_t old;
|
||||
LOAD_16(old, 0, hw->gpioBase);
|
||||
old &= ~hw->direction;
|
||||
old |= hw->pinState;
|
||||
STORE_16(old, 0, hw->gpioBase);
|
||||
STORE_16(hw->pinState, 0, hw->gpioBase);
|
||||
STORE_16(hw->direction, 2, hw->gpioBase);
|
||||
STORE_16(hw->readWrite, 4, hw->gpioBase);
|
||||
} else {
|
||||
hw->gpioBase[0] = 0;
|
||||
hw->gpioBase[1] = 0;
|
||||
hw->gpioBase[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,11 +165,15 @@ void _rtcReadPins(struct GBACartridgeHardware* hw) {
|
|||
if ((hw->pinState & 5) == 1) {
|
||||
hw->rtc.transferStep = 1;
|
||||
}
|
||||
_outputPins(hw, 1);
|
||||
break;
|
||||
case 1:
|
||||
if ((hw->pinState & 5) == 5) {
|
||||
hw->rtc.transferStep = 2;
|
||||
} else {
|
||||
hw->rtc.transferStep = 0;
|
||||
}
|
||||
_outputPins(hw, 5);
|
||||
break;
|
||||
case 2:
|
||||
if (!(hw->pinState & 1)) {
|
||||
|
@ -177,11 +181,7 @@ void _rtcReadPins(struct GBACartridgeHardware* hw) {
|
|||
hw->rtc.bits |= ((hw->pinState & 2) >> 1) << hw->rtc.bitsRead;
|
||||
} else {
|
||||
if (hw->pinState & 4) {
|
||||
// GPIO direction should always != reading
|
||||
if (hw->direction & 2) {
|
||||
if (RTCCommandDataIsReading(hw->rtc.command)) {
|
||||
mLOG(GBA_HW, GAME_ERROR, "Attempting to write to RTC while in read mode");
|
||||
}
|
||||
if (!RTCCommandDataIsReading(hw->rtc.command)) {
|
||||
++hw->rtc.bitsRead;
|
||||
if (hw->rtc.bitsRead == 8) {
|
||||
GBARTCProcessByte(&hw->rtc, hw->p->rtcSource);
|
||||
|
@ -193,7 +193,7 @@ void _rtcReadPins(struct GBACartridgeHardware* hw) {
|
|||
--hw->rtc.bytesRemaining;
|
||||
if (hw->rtc.bytesRemaining <= 0) {
|
||||
hw->rtc.commandActive = 0;
|
||||
hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command);
|
||||
hw->rtc.command = 0;
|
||||
}
|
||||
hw->rtc.bitsRead = 0;
|
||||
}
|
||||
|
@ -202,8 +202,9 @@ void _rtcReadPins(struct GBACartridgeHardware* hw) {
|
|||
hw->rtc.bitsRead = 0;
|
||||
hw->rtc.bytesRemaining = 0;
|
||||
hw->rtc.commandActive = 0;
|
||||
hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command);
|
||||
hw->rtc.transferStep = 0;
|
||||
hw->rtc.command = 0;
|
||||
hw->rtc.transferStep = hw->pinState & 1;
|
||||
_outputPins(hw, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -269,6 +270,10 @@ void GBARTCProcessByte(struct GBARTC* rtc, struct mRTCSource* source) {
|
|||
|
||||
unsigned GBARTCOutput(struct GBARTC* rtc) {
|
||||
uint8_t outputByte = 0;
|
||||
if (!rtc->commandActive) {
|
||||
mLOG(GBA_HW, GAME_ERROR, "Attempting to use RTC without an active command");
|
||||
return 0;
|
||||
}
|
||||
switch (RTCCommandDataGetCommand(rtc->command)) {
|
||||
case RTC_STATUS1:
|
||||
outputByte = rtc->control;
|
||||
|
|
|
@ -138,7 +138,7 @@ bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {
|
|||
return true;
|
||||
}
|
||||
|
||||
size_t GBASavedataSize(struct GBASavedata* savedata) {
|
||||
size_t GBASavedataSize(const struct GBASavedata* savedata) {
|
||||
switch (savedata->type) {
|
||||
case SAVEDATA_SRAM:
|
||||
return SIZE_CART_SRAM;
|
||||
|
|
|
@ -130,8 +130,21 @@ bool GBASavedataImportSharkPort(struct GBA* gba, struct VFile* vf, bool testChec
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
memcpy(gba->memory.savedata.data, &payload[0x1C], copySize);
|
||||
gba->memory.savedata.vf && gba->memory.savedata.vf->sync(gba->memory.savedata.vf, gba->memory.savedata.data, size);
|
||||
if (gba->memory.savedata.type == SAVEDATA_EEPROM) {
|
||||
size_t i;
|
||||
for (i = 0; i < copySize; i += 8) {
|
||||
uint32_t lo, hi;
|
||||
LOAD_32BE(lo, i + 0x1C, payload);
|
||||
LOAD_32BE(hi, i + 0x20, payload);
|
||||
STORE_32LE(hi, i, gba->memory.savedata.data);
|
||||
STORE_32LE(lo, i + 4, gba->memory.savedata.data);
|
||||
}
|
||||
} else {
|
||||
memcpy(gba->memory.savedata.data, &payload[0x1C], copySize);
|
||||
}
|
||||
if (gba->memory.savedata.vf) {
|
||||
gba->memory.savedata.vf->sync(gba->memory.savedata.vf, gba->memory.savedata.data, size);
|
||||
}
|
||||
|
||||
free(payload);
|
||||
return true;
|
||||
|
@ -146,7 +159,7 @@ bool GBASavedataExportSharkPort(const struct GBA* gba, struct VFile* vf) {
|
|||
char c[0x1C];
|
||||
int32_t i;
|
||||
} buffer;
|
||||
int32_t size = strlen(SHARKPORT_HEADER);
|
||||
uint32_t size = strlen(SHARKPORT_HEADER);
|
||||
STORE_32(size, 0, &buffer.i);
|
||||
if (vf->write(vf, &buffer.i, 4) < 4) {
|
||||
return false;
|
||||
|
@ -187,22 +200,8 @@ bool GBASavedataExportSharkPort(const struct GBA* gba, struct VFile* vf) {
|
|||
}
|
||||
|
||||
// Write payload
|
||||
size = 0x1C;
|
||||
switch (gba->memory.savedata.type) {
|
||||
case SAVEDATA_SRAM:
|
||||
size += SIZE_CART_SRAM;
|
||||
break;
|
||||
case SAVEDATA_FLASH512:
|
||||
size += SIZE_CART_FLASH512;
|
||||
break;
|
||||
case SAVEDATA_FLASH1M:
|
||||
size += SIZE_CART_FLASH1M;
|
||||
break;
|
||||
case SAVEDATA_EEPROM:
|
||||
size += SIZE_CART_EEPROM;
|
||||
break;
|
||||
case SAVEDATA_FORCE_NONE:
|
||||
case SAVEDATA_AUTODETECT:
|
||||
size = 0x1C + GBASavedataSize(&gba->memory.savedata);
|
||||
if (size == 0x1C) {
|
||||
return false;
|
||||
}
|
||||
STORE_32(size, 0, &buffer.i);
|
||||
|
@ -229,17 +228,24 @@ bool GBASavedataExportSharkPort(const struct GBA* gba, struct VFile* vf) {
|
|||
}
|
||||
|
||||
uint32_t checksum = 0;
|
||||
int i;
|
||||
size_t i;
|
||||
for (i = 0; i < 0x1C; ++i) {
|
||||
checksum += buffer.c[i] << (checksum % 24);
|
||||
}
|
||||
|
||||
if (vf->write(vf, gba->memory.savedata.data, size) < size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
checksum += ((char) gba->memory.savedata.data[i]) << (checksum % 24);
|
||||
if (gba->memory.savedata.type == SAVEDATA_EEPROM) {
|
||||
for (i = 0; i < size; ++i) {
|
||||
char byte = gba->memory.savedata.data[i ^ 7];
|
||||
checksum += byte << (checksum % 24);
|
||||
vf->write(vf, &byte, 1);
|
||||
}
|
||||
} else if (vf->write(vf, gba->memory.savedata.data, size) < size) {
|
||||
return false;
|
||||
} else {
|
||||
for (i = 0; i < size; ++i) {
|
||||
checksum += ((char) gba->memory.savedata.data[i]) << (checksum % 24);
|
||||
}
|
||||
}
|
||||
|
||||
STORE_32(checksum, 0, &buffer.i);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "DisplayGL.h"
|
||||
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES)
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
|
||||
#include "CoreController.h"
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#pragma once
|
||||
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES)
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
|
||||
#include "Display.h"
|
||||
|
||||
|
|
|
@ -291,13 +291,13 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
}
|
||||
|
||||
SettingsView::~SettingsView() {
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES)
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
setShaderSelector(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SettingsView::setShaderSelector(ShaderSelector* shaderSelector) {
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES)
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
if (m_shader) {
|
||||
auto items = m_ui.tabs->findItems(tr("Shaders"), Qt::MatchFixedString);
|
||||
for (const auto& item : items) {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <mgba-util/vfs.h>
|
||||
#include "platform/video-backend.h"
|
||||
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES)
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
|
||||
#if !defined(_WIN32) || defined(USE_EPOXY)
|
||||
#include "platform/opengl/gles2.h"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#pragma once
|
||||
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES)
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
|
|
|
@ -852,7 +852,7 @@ void Window::reloadDisplayDriver() {
|
|||
detachWidget(m_display.get());
|
||||
}
|
||||
m_display = std::move(std::unique_ptr<Display>(Display::create(this)));
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES)
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
m_shaderView.reset();
|
||||
m_shaderView = std::make_unique<ShaderSelector>(m_display.get(), m_config);
|
||||
#endif
|
||||
|
@ -871,7 +871,7 @@ void Window::reloadDisplayDriver() {
|
|||
const mCoreOptions* opts = m_config->options();
|
||||
m_display->lockAspectRatio(opts->lockAspectRatio);
|
||||
m_display->filter(opts->resampleVideo);
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES)
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
if (opts->shader) {
|
||||
struct VDir* shader = VDirOpen(opts->shader);
|
||||
if (shader && m_display->supportsShaders()) {
|
||||
|
|
|
@ -187,7 +187,7 @@ private:
|
|||
QMenu* m_mruMenu = nullptr;
|
||||
QMenu* m_videoLayers;
|
||||
QMenu* m_audioChannels;
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES)
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
std::unique_ptr<ShaderSelector> m_shaderView;
|
||||
#endif
|
||||
bool m_fullscreenOnStart = false;
|
||||
|
|
|
@ -123,15 +123,15 @@ void mSDLGLES2Runloop(struct mSDLRenderer* renderer, void* user) {
|
|||
SDL_Event event;
|
||||
struct VideoBackend* v = &renderer->gl2.d;
|
||||
|
||||
while (context->state < THREAD_EXITING) {
|
||||
while (mCoreThreadIsActive(context)) {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
mSDLHandleEvent(context, &renderer->player, &event);
|
||||
}
|
||||
|
||||
if (mCoreSyncWaitFrameStart(&context->sync)) {
|
||||
if (mCoreSyncWaitFrameStart(&context->impl->sync)) {
|
||||
v->postFrame(v, renderer->outputBuffer);
|
||||
}
|
||||
mCoreSyncWaitFrameEnd(&context->sync);
|
||||
mCoreSyncWaitFrameEnd(&context->impl->sync);
|
||||
v->drawFrame(v);
|
||||
#ifdef BUILD_RASPI
|
||||
eglSwapBuffers(renderer->display, renderer->surface);
|
||||
|
|
|
@ -733,6 +733,7 @@ void _gameLoaded(struct mGUIRunner* runner) {
|
|||
|
||||
void _unpaused(struct mGUIRunner* runner) {
|
||||
u32 level = 0;
|
||||
VIDEO_WaitVSync();
|
||||
_CPU_ISR_Disable(level);
|
||||
referenceRetraceCount = retraceCount;
|
||||
_CPU_ISR_Restore(level);
|
||||
|
|
Loading…
Reference in New Issue