Merge branch 'master' (early part) into medusa

This commit is contained in:
Vicki Pfau 2019-06-28 15:50:12 -07:00
commit 39ad11d471
11 changed files with 153 additions and 72 deletions

View File

@ -73,6 +73,9 @@ Bugfixes:
- GBA: Fix SharkPort saves for EEPROM games
- Qt: Fix opening in fullscreen (fixes mgba.io/i/993)
- Python: Fix package directory
- GB Memory: Fix OAM DMA blocking regions (fixes mgba.io/i/1013)
- Wii: Fix various setup and teardown drawing issues (fixes mgba.io/i/988)
- GBA Timer: Fix timers sometimes being late (fixes mgba.io/i/1012)
Misc:
- GBA Timer: Use global cycles for timers
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)

View File

@ -11,7 +11,9 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146")
endif()
set(USE_DEBUGGERS ON CACHE BOOL "Whether or not to enable the debugging infrastructure")
set(USE_EDITLINE ON CACHE BOOL "Whether or not to enable the CLI-mode debugger")
if (NOT WIN32)
set(USE_EDITLINE ON CACHE BOOL "Whether or not to enable the CLI-mode debugger")
endif()
set(USE_GDB_STUB ON CACHE BOOL "Whether or not to enable the GDB stub ARM debugger")
set(USE_FFMPEG ON CACHE BOOL "Whether or not to enable FFmpeg support")
set(USE_ZLIB ON CACHE BOOL "Whether or not to enable zlib support")
@ -1023,7 +1025,9 @@ if(NOT QUIET)
message(STATUS " DS: ${M_CORE_DS}")
message(STATUS "Features:")
message(STATUS " Debuggers: ${USE_DEBUGGERS}")
if(NOT WIN32)
message(STATUS " CLI debugger: ${USE_EDITLINE}")
endif()
message(STATUS " GDB stub: ${USE_GDB_STUB}")
message(STATUS " Video recording: ${USE_FFMPEG}")
message(STATUS " GIF recording: ${USE_MAGICK}")

View File

@ -154,11 +154,11 @@ To build on Windows for development, using MSYS2 is recommended. Follow the inst
For x86 (32 bit) builds:
pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git}
pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git}
For x86_64 (64 bit) builds:
pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git}
pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git}
Check out the source code by running this command:

View File

@ -136,11 +136,11 @@ Um mGBA auf Windows zu kompilieren, wird MSYS2 empfohlen. Befolge die Installati
Für x86 (32 Bit):
pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git}
pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git}
Für x86_64 (64 Bit):
pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git}
pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git}
Lade den aktuellen mGBA-Quellcode mithilfe des folgenden Kommandos herunter:

View File

@ -26,7 +26,6 @@ enum {
GB_VIDEO_HORIZONTAL_LENGTH = 456,
GB_VIDEO_MODE_1_LENGTH = 65664,
GB_VIDEO_TOTAL_LENGTH = 70224,
GB_BASE_MAP = 0x1800,

View File

@ -16,31 +16,33 @@
mLOG_DEFINE_CATEGORY(GB_MEM, "GB Memory", "gb.memory");
struct OAMBlock {
uint16_t low;
uint16_t high;
enum GBBus {
GB_BUS_CPU,
GB_BUS_MAIN,
GB_BUS_VRAM,
GB_BUS_RAM
};
static const struct OAMBlock _oamBlockDMG[] = {
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0x8000, 0xA000 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
static const enum GBBus _oamBlockDMG[] = {
GB_BUS_MAIN, // 0x0000
GB_BUS_MAIN, // 0x2000
GB_BUS_MAIN, // 0x4000
GB_BUS_MAIN, // 0x6000
GB_BUS_VRAM, // 0x8000
GB_BUS_MAIN, // 0xA000
GB_BUS_MAIN, // 0xC000
GB_BUS_CPU, // 0xE000
};
static const struct OAMBlock _oamBlockCGB[] = {
{ 0xA000, 0xC000 },
{ 0xA000, 0xC000 },
{ 0xA000, 0xC000 },
{ 0xA000, 0xC000 },
{ 0x8000, 0xA000 },
{ 0xA000, 0xC000 },
{ 0xC000, 0xFE00 },
{ 0xA000, 0xC000 },
static const enum GBBus _oamBlockCGB[] = {
GB_BUS_MAIN, // 0x0000
GB_BUS_MAIN, // 0x2000
GB_BUS_MAIN, // 0x4000
GB_BUS_MAIN, // 0x6000
GB_BUS_VRAM, // 0x8000
GB_BUS_MAIN, // 0xA000
GB_BUS_RAM, // 0xC000
GB_BUS_CPU // 0xE000
};
static void _pristineCow(struct GB* gba);
@ -192,9 +194,10 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
struct GB* gb = (struct GB*) cpu->master;
struct GBMemory* memory = &gb->memory;
if (gb->memory.dmaRemaining) {
const struct OAMBlock* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB;
block = &block[memory->dmaSource >> 13];
if (address >= block->low && address < block->high) {
const enum GBBus* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB;
enum GBBus dmaBus = block[memory->dmaSource >> 13];
enum GBBus accessBus = block[address >> 13];
if (dmaBus != GB_BUS_CPU && dmaBus == accessBus) {
return 0xFF;
}
if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) {
@ -264,9 +267,10 @@ void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
struct GB* gb = (struct GB*) cpu->master;
struct GBMemory* memory = &gb->memory;
if (gb->memory.dmaRemaining) {
const struct OAMBlock* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB;
block = &block[memory->dmaSource >> 13];
if (address >= block->low && address < block->high) {
const enum GBBus* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB;
enum GBBus dmaBus = block[memory->dmaSource >> 13];
enum GBBus accessBus = block[address >> 13];
if (dmaBus != GB_BUS_CPU && dmaBus == accessBus) {
return;
}
if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) {

View File

@ -75,25 +75,25 @@ static void _regenerateSGBBorder(struct GBVideoSoftwareRenderer* renderer) {
tileData[3] = renderer->d.sgbCharRam[(SGBBgAttributesGetTile(mapData) * 16 + localY) * 2 + 0x11];
size_t base = y * renderer->outputBufferStride + x;
int p = SGBBgAttributesGetPalette(mapData) * 0x10;
int paletteBase = SGBBgAttributesGetPalette(mapData) * 0x10;
int colorSelector;
if (SGBBgAttributesIsXFlip(mapData)) {
renderer->outputBuffer[base + 0] = renderer->palette[p | ((tileData[0] >> 0) & 0x1) | ((tileData[1] << 1) & 0x2) | ((tileData[2] << 2) & 0x4) | ((tileData[3] << 3) & 0x8)];
renderer->outputBuffer[base + 1] = renderer->palette[p | ((tileData[0] >> 1) & 0x1) | ((tileData[1] >> 0) & 0x2) | ((tileData[2] << 1) & 0x4) | ((tileData[3] << 2) & 0x8)];
renderer->outputBuffer[base + 2] = renderer->palette[p | ((tileData[0] >> 2) & 0x1) | ((tileData[1] >> 1) & 0x2) | ((tileData[2] >> 0) & 0x4) | ((tileData[3] << 1) & 0x8)];
renderer->outputBuffer[base + 3] = renderer->palette[p | ((tileData[0] >> 3) & 0x1) | ((tileData[1] >> 2) & 0x2) | ((tileData[2] >> 1) & 0x4) | ((tileData[3] >> 0) & 0x8)];
renderer->outputBuffer[base + 4] = renderer->palette[p | ((tileData[0] >> 4) & 0x1) | ((tileData[1] >> 3) & 0x2) | ((tileData[2] >> 2) & 0x4) | ((tileData[3] >> 1) & 0x8)];
renderer->outputBuffer[base + 5] = renderer->palette[p | ((tileData[0] >> 5) & 0x1) | ((tileData[1] >> 4) & 0x2) | ((tileData[2] >> 3) & 0x4) | ((tileData[3] >> 2) & 0x8)];
renderer->outputBuffer[base + 6] = renderer->palette[p | ((tileData[0] >> 6) & 0x1) | ((tileData[1] >> 5) & 0x2) | ((tileData[2] >> 4) & 0x4) | ((tileData[3] >> 3) & 0x8)];
renderer->outputBuffer[base + 7] = renderer->palette[p | ((tileData[0] >> 7) & 0x1) | ((tileData[1] >> 6) & 0x2) | ((tileData[2] >> 5) & 0x4) | ((tileData[3] >> 4) & 0x8)];
for (i = 0; i < 8; ++i) {
colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3;
// The first color of every palette is transparent
if (colorSelector) {
renderer->outputBuffer[base + i] = renderer->palette[paletteBase | colorSelector];
}
}
} else {
renderer->outputBuffer[base + 0] = renderer->palette[p | ((tileData[0] >> 7) & 0x1) | ((tileData[1] >> 6) & 0x2) | ((tileData[2] >> 5) & 0x4) | ((tileData[3] >> 4) & 0x8)];
renderer->outputBuffer[base + 1] = renderer->palette[p | ((tileData[0] >> 6) & 0x1) | ((tileData[1] >> 5) & 0x2) | ((tileData[2] >> 4) & 0x4) | ((tileData[3] >> 3) & 0x8)];
renderer->outputBuffer[base + 2] = renderer->palette[p | ((tileData[0] >> 5) & 0x1) | ((tileData[1] >> 4) & 0x2) | ((tileData[2] >> 3) & 0x4) | ((tileData[3] >> 2) & 0x8)];
renderer->outputBuffer[base + 3] = renderer->palette[p | ((tileData[0] >> 4) & 0x1) | ((tileData[1] >> 3) & 0x2) | ((tileData[2] >> 2) & 0x4) | ((tileData[3] >> 1) & 0x8)];
renderer->outputBuffer[base + 4] = renderer->palette[p | ((tileData[0] >> 3) & 0x1) | ((tileData[1] >> 2) & 0x2) | ((tileData[2] >> 1) & 0x4) | ((tileData[3] >> 0) & 0x8)];
renderer->outputBuffer[base + 5] = renderer->palette[p | ((tileData[0] >> 2) & 0x1) | ((tileData[1] >> 1) & 0x2) | ((tileData[2] >> 0) & 0x4) | ((tileData[3] << 1) & 0x8)];
renderer->outputBuffer[base + 6] = renderer->palette[p | ((tileData[0] >> 1) & 0x1) | ((tileData[1] >> 0) & 0x2) | ((tileData[2] << 1) & 0x4) | ((tileData[3] << 2) & 0x8)];
renderer->outputBuffer[base + 7] = renderer->palette[p | ((tileData[0] >> 0) & 0x1) | ((tileData[1] << 1) & 0x2) | ((tileData[2] << 2) & 0x4) | ((tileData[3] << 3) & 0x8)];
for (i = 7; i >= 0; --i) {
colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3;
if (colorSelector) {
renderer->outputBuffer[base + 7 - i] = renderer->palette[paletteBase | colorSelector];
}
}
}
}
}

View File

@ -50,7 +50,7 @@ void GBATimerUpdate(struct mTiming* timing, struct GBATimer* timer, uint16_t* io
int32_t tickMask = (1 << GBATimerFlagsGetPrescaleBits(timer->flags)) - 1;
currentTime &= ~tickMask;
timer->lastEvent = currentTime;
GBATimerUpdateRegisterInternal(timer, timing, io, 0);
GBATimerUpdateRegisterInternal(timer, timing, io, TIMER_RELOAD_DELAY + cyclesLate);
if (GBATimerFlagsIsDoIrq(timer->flags)) {
timer->flags = GBATimerFlagsFillIrqPending(timer->flags);
@ -171,7 +171,7 @@ void GBATimerUpdateRegisterInternal(struct GBATimer* timer, struct mTiming* timi
if (!mTimingIsScheduled(timing, &timer->event)) {
tickIncrement = (0x10000 - tickIncrement) << prescaleBits;
currentTime -= mTimingCurrentTime(timing) - skew;
mTimingSchedule(timing, &timer->event, TIMER_RELOAD_DELAY + tickIncrement + currentTime);
mTimingSchedule(timing, &timer->event, tickIncrement + currentTime);
}
}

View File

@ -63,6 +63,27 @@ static void _reloadSettings(void) {
};
struct retro_variable var;
enum GBModel model;
const char* modelName;
var.key = "mgba_model";
var.value = 0;
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
if (strcmp(var.value, "Game Boy") == 0) {
model = GB_MODEL_DMG;
} else if (strcmp(var.value, "Super Game Boy") == 0) {
model = GB_MODEL_SGB;
} else if (strcmp(var.value, "Game Boy Color") == 0) {
model = GB_MODEL_CGB;
} else {
model = GB_MODEL_AUTODETECT;
}
modelName = GBModelToName(model);
mCoreConfigSetDefaultValue(&core->config, "gb.model", modelName);
mCoreConfigSetDefaultValue(&core->config, "sgb.model", modelName);
mCoreConfigSetDefaultValue(&core->config, "cgb.model", modelName);
}
var.key = "mgba_use_bios";
var.value = 0;
@ -119,6 +140,7 @@ void retro_set_environment(retro_environment_t env) {
struct retro_variable vars[] = {
{ "mgba_solar_sensor_level", "Solar sensor level; 0|1|2|3|4|5|6|7|8|9|10" },
{ "mgba_allow_opposing_directions", "Allow opposing directional input; OFF|ON" },
{ "mgba_model", "Game Boy model (requires restart); Autodetect|Game Boy|Super Game Boy|Game Boy Color" },
{ "mgba_use_bios", "Use BIOS file if found (requires restart); ON|OFF" },
{ "mgba_skip_bios", "Skip BIOS intro (requires restart); OFF|ON" },
{ "mgba_sgb_borders", "Use Super Game Boy borders (requires restart); ON|OFF" },
@ -299,7 +321,7 @@ void retro_run(void) {
videoCallback(outputBuffer, width, height, BYTES_PER_PIXEL * 256);
}
void static _setupMaps(struct mCore* core) {
static void _setupMaps(struct mCore* core) {
#ifdef M_CORE_GBA
if (core->platform(core) == PLATFORM_GBA) {
struct GBA* gba = core->board;
@ -417,7 +439,9 @@ bool retro_load_game(const struct retro_game_info* game) {
core->init(core);
core->setAVStream(core, &stream);
outputBuffer = malloc(256 * 224 * BYTES_PER_PIXEL);
size_t size = 256 * 224 * BYTES_PER_PIXEL;
outputBuffer = malloc(size);
memset(outputBuffer, 0xFF, size);
core->setVideoBuffer(core, outputBuffer, 256);
core->setAudioBufferSize(core, SAMPLES);
@ -434,21 +458,52 @@ bool retro_load_game(const struct retro_game_info* game) {
core->loadROM(core, rom);
core->loadSave(core, save);
const char* sysDir = 0;
const char* biosName = 0;
char biosPath[PATH_MAX];
environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir);
#ifdef M_CORE_GBA
if (core->platform(core) == PLATFORM_GBA) {
core->setPeripheral(core, mPERIPH_GBA_LUMINANCE, &lux);
biosName = "gba_bios.bin";
const char* sysDir = 0;
if (core->opts.useBios && environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir)) {
char biosPath[PATH_MAX];
snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, "gba_bios.bin");
}
#endif
#ifdef M_CORE_GB
if (core->platform(core) == PLATFORM_GB) {
const char* modelName = mCoreConfigGetValue(&core->config, "gb.model");
struct GB* gb = core->board;
if (modelName) {
gb->model = GBNameToModel(modelName);
} else {
GBDetectModel(gb);
}
switch (gb->model) {
case GB_MODEL_CGB:
biosName = "gbc_bios.bin";
break;
case GB_MODEL_SGB:
biosName = "sgb_bios.bin";
break;
case GB_MODEL_DMG:
default:
biosName = "gb_bios.bin";
break;
};
}
#endif
if (core->opts.useBios && sysDir && biosName) {
snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, biosName);
struct VFile* bios = VFileOpen(biosPath, O_RDONLY);
if (bios) {
core->loadBIOS(core, bios, 0);
}
}
}
#endif
core->reset(core);
_setupMaps(core);

View File

@ -173,7 +173,7 @@ if(Qt5Multimedia_FOUND)
VideoDumper.cpp)
if (WIN32 AND QT_STATIC)
list(APPEND QT_LIBRARIES Qt5::QWindowsAudioPlugin Qt5::DSServicePlugin
strmiids winmm mfuuid mfplat mf ksguid dxva2 evr d3d9)
strmiids mfuuid mfplat mf ksguid dxva2 evr d3d9)
endif()
list(APPEND QT_LIBRARIES Qt5::Multimedia)
list(APPEND QT_DEFINES BUILD_QT_MULTIMEDIA)
@ -275,7 +275,7 @@ if(BUILD_GL OR BUILD_GLES2)
endif()
if(WIN32 AND QT_STATIC)
list(APPEND QT_LIBRARIES qwindows dwmapi imm32 uxtheme Qt5EventDispatcherSupport Qt5FontDatabaseSupport Qt5ThemeSupport)
set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "qtpcre2;version;ws2_32")
set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "qtpcre2;version;winmm;ws2_32")
endif()
target_link_libraries(${BINARY_NAME}-qt ${PLATFORM_LIBRARY} ${BINARY_NAME} ${QT_LIBRARIES})
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}" PARENT_SCOPE)

View File

@ -194,18 +194,20 @@ static void reconfigureScreen(struct mGUIRunner* runner) {
free(framebuffer[0]);
free(framebuffer[1]);
framebuffer[0] = SYS_AllocateFramebuffer(vmode);
framebuffer[1] = SYS_AllocateFramebuffer(vmode);
VIDEO_SetBlack(true);
VIDEO_Configure(vmode);
framebuffer[0] = SYS_AllocateFramebuffer(vmode);
framebuffer[1] = SYS_AllocateFramebuffer(vmode);
VIDEO_ClearFrameBuffer(vmode, framebuffer[0], COLOR_BLACK);
VIDEO_ClearFrameBuffer(vmode, framebuffer[1], COLOR_BLACK);
VIDEO_SetNextFramebuffer(framebuffer[whichFb]);
VIDEO_Flush();
VIDEO_WaitVSync();
if (vmode->viTVMode & VI_NON_INTERLACE) {
VIDEO_WaitVSync();
}
VIDEO_SetBlack(false);
GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
f32 yscale = GX_GetYScaleFactor(vmode->efbHeight, vmode->xfbHeight);
@ -238,6 +240,9 @@ static void reconfigureScreen(struct mGUIRunner* runner) {
int main(int argc, char* argv[]) {
VIDEO_Init();
VIDEO_SetBlack(true);
VIDEO_Flush();
VIDEO_WaitVSync();
PAD_Init();
WPAD_Init();
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
@ -481,6 +486,10 @@ int main(int argc, char* argv[]) {
mGUIInit(&runner, "wii");
reconfigureScreen(&runner);
// Make sure screen is properly initialized by drawing a blank frame
_drawStart();
_drawEnd();
_mapKey(&runner.params.keyMap, GCN1_INPUT, PAD_BUTTON_A, GUI_INPUT_SELECT);
_mapKey(&runner.params.keyMap, GCN1_INPUT, PAD_BUTTON_B, GUI_INPUT_BACK);
_mapKey(&runner.params.keyMap, GCN1_INPUT, PAD_TRIGGER_Z, GUI_INPUT_CANCEL);
@ -516,6 +525,9 @@ int main(int argc, char* argv[]) {
} else {
mGUIRunloop(&runner);
}
VIDEO_SetBlack(true);
VIDEO_Flush();
VIDEO_WaitVSync();
mGUIDeinit(&runner);
#ifdef FIXED_ROM_BUFFER
@ -546,6 +558,8 @@ static void _audioDMA(void) {
}
static void _drawStart(void) {
VIDEO_SetBlack(false);
u32 level = 0;
_CPU_ISR_Disable(level);
if (referenceRetraceCount > retraceCount) {
@ -563,12 +577,11 @@ static void _drawStart(void) {
}
static void _drawEnd(void) {
whichFb = !whichFb;
GX_CopyDisp(framebuffer[whichFb], GX_TRUE);
GX_DrawDone();
VIDEO_SetNextFramebuffer(framebuffer[whichFb]);
VIDEO_Flush();
whichFb = !whichFb;
u32 level = 0;
_CPU_ISR_Disable(level);
@ -713,6 +726,9 @@ void _gameUnloaded(struct mGUIRunner* runner) {
UNUSED(runner);
AUDIO_StopDMA();
frameLimiter = true;
VIDEO_SetBlack(true);
VIDEO_Flush();
VIDEO_WaitVSync();
}
void _gameLoaded(struct mGUIRunner* runner) {