Permalink
Browse files

Merge pull request #87 from endrift/libretro

Sync with 0.6 branch
  • Loading branch information...
twinaphex committed Jan 13, 2018
2 parents 05e2ff4 + 9e2e520 commit 932908bfe8d3b954516901616cda628de8bd86a8
View
@@ -9,6 +9,12 @@ Bugfixes:
- GB Memory: HDMAs should not start when LCD is off (fixes mgba.io/i/310)
- GBA Cheats: Fix slide codes not initializing properly
- Qt: Fix locale being set to English on settings save (fixes mgba.io/i/906)
+ - LR35902: Fix watchpoints not reporting new value
+ - GBA Audio: Increase PSG volume (fixes mgba.io/i/932)
+ - GBA BIOS: Fix incorrect exit condition in LZ77
+ - 3DS: Fix opening files in directory names with trailing slashes
+ - GB MBC: Fix MBC2 saves (fixes mgba.io/i/954)
+ - GBA Memory: Fix copy-on-write memory leak
Misc:
- GBA: Improve multiboot image detection
- GB MBC: Remove erroneous bank 0 wrapping
@@ -31,6 +31,8 @@ struct GBVideoSoftwareRenderer {
uint8_t wy;
uint8_t wx;
uint8_t currentWy;
+ int lastY;
+ bool hasWindow;
GBRegisterLCDC lcdc;
enum GBModel model;
View
@@ -252,15 +252,15 @@ void mCoreInitConfig(struct mCore* core, const char* port) {
}
void mCoreLoadConfig(struct mCore* core) {
-#ifndef MINIMAL_CORE
+#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
mCoreConfigLoad(&core->config);
#endif
mCoreLoadForeignConfig(core, &core->config);
}
void mCoreLoadForeignConfig(struct mCore* core, const struct mCoreConfig* config) {
mCoreConfigMap(config, &core->opts);
-#ifndef MINIMAL_CORE
+#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
mDirectorySetMapOptions(&core->dirs, &core->opts);
#endif
if (core->opts.audioBuffers) {
@@ -165,6 +165,7 @@ void mGUIInit(struct mGUIRunner* runner, const char* port) {
mCoreConfigSetDefaultIntValue(&runner->config, "volume", 0x100);
mCoreConfigSetDefaultValue(&runner->config, "idleOptimization", "detect");
mCoreConfigLoad(&runner->config);
+ mCoreConfigGetIntValue(&runner->config, "logLevel", &logger.logLevel);
char path[PATH_MAX];
mCoreConfigDirectory(path, PATH_MAX);
@@ -283,7 +284,7 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
if (runner->core) {
mLOG(GUI_RUNNER, INFO, "Found core");
runner->core->init(runner->core);
- mCoreConfigInit(&runner->core->config, runner->port);
+ mCoreInitConfig(runner->core, runner->port);
mInputMapInit(&runner->core->inputMap, &GBAInputInfo);
found = mCoreLoadFile(runner->core, path);
if (!found) {
@@ -302,7 +303,6 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
}
mLOG(GUI_RUNNER, DEBUG, "Loading config...");
mCoreLoadForeignConfig(runner->core, &runner->config);
- logger.logLevel = runner->core->opts.logLevel;
mLOG(GUI_RUNNER, DEBUG, "Loading save...");
mCoreAutoloadSave(runner->core);
View
@@ -30,6 +30,7 @@ static void _GBMBC7(struct GB*, uint16_t address, uint8_t value);
static void _GBHuC3(struct GB*, uint16_t address, uint8_t value);
static void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value);
+static uint8_t _GBMBC2Read(struct GBMemory*, uint16_t address);
static uint8_t _GBMBC7Read(struct GBMemory*, uint16_t address);
static uint8_t _GBPocketCamRead(struct GBMemory*, uint16_t address);
@@ -183,7 +184,8 @@ void GBMBCInit(struct GB* gb) {
break;
case GB_MBC2:
gb->memory.mbcWrite = _GBMBC2;
- gb->sramSize = 0x200;
+ gb->memory.mbcRead = _GBMBC2Read;
+ gb->sramSize = 0x100;
break;
case GB_MBC3:
gb->memory.mbcWrite = _GBMBC3;
@@ -355,6 +357,7 @@ void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) {
void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) {
struct GBMemory* memory = &gb->memory;
+ int shift = (address & 1) * 4;
int bank = value & 0xF;
switch (address >> 13) {
case 0x0:
@@ -364,7 +367,6 @@ void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) {
break;
case 0xA:
memory->sramAccess = true;
- GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
break;
default:
// TODO
@@ -378,13 +380,26 @@ void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) {
}
GBMBCSwitchBank(gb, bank);
break;
+ case 0x5:
+ if (!memory->sramAccess) {
+ return;
+ }
+ address &= 0x1FF;
+ memory->sramBank[(address >> 1)] &= 0xF0 >> shift;
+ memory->sramBank[(address >> 1)] |= (value & 0xF) << shift;
default:
// TODO
mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value);
break;
}
}
+static uint8_t _GBMBC2Read(struct GBMemory* memory, uint16_t address) {
+ address &= 0x1FF;
+ int shift = (address & 1) * 4;
+ return (memory->sramBank[(address >> 1)] >> shift) | 0xF0;
+}
+
void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
struct GBMemory* memory = &gb->memory;
int bank = value & 0x7F;
View
@@ -289,7 +289,7 @@ void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
case GB_REGION_EXTERNAL_RAM + 1:
if (memory->rtcAccess) {
memory->rtcRegs[memory->activeRtcReg] = value;
- } else if (memory->sramAccess && memory->sram) {
+ } else if (memory->sramAccess && memory->sram && memory->mbcType != GB_MBC2) {
memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value;
} else if (memory->mbcType == GB_MBC7) {
GBMBC7Write(memory, address, value);
@@ -38,6 +38,10 @@ static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) {
}
}
+static bool _inWindow(struct GBVideoSoftwareRenderer* renderer) {
+ return GBRegisterLCDCIsWindow(renderer->lcdc) && GB_VIDEO_HORIZONTAL_PIXELS + 7 > renderer->wx;
+}
+
void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer* renderer) {
renderer->d.init = GBVideoSoftwareRendererInit;
renderer->d.deinit = GBVideoSoftwareRendererDeinit;
@@ -65,6 +69,8 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G
softwareRenderer->scx = 0;
softwareRenderer->wy = 0;
softwareRenderer->currentWy = 0;
+ softwareRenderer->lastY = 0;
+ softwareRenderer->hasWindow = false;
softwareRenderer->wx = 0;
softwareRenderer->model = model;
}
@@ -74,11 +80,31 @@ static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer) {
UNUSED(softwareRenderer);
}
+static void GBVideoSoftwareRendererUpdateWindow(struct GBVideoSoftwareRenderer* renderer, bool before, bool after) {
+ if (renderer->lastY >= GB_VIDEO_VERTICAL_PIXELS || after == before) {
+ return;
+ }
+ if (renderer->lastY >= renderer->wy) {
+ if (!after) {
+ renderer->currentWy -= renderer->lastY;
+ renderer->hasWindow = true;
+ } else {
+ if (!renderer->hasWindow) {
+ renderer->currentWy = renderer->lastY + 1 - renderer->wy;
+ } else {
+ renderer->currentWy += renderer->lastY;
+ }
+ }
+ }
+}
+
static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
+ bool wasWindow = _inWindow(softwareRenderer);
switch (address) {
case REG_LCDC:
softwareRenderer->lcdc = value;
+ GBVideoSoftwareRendererUpdateWindow(softwareRenderer, wasWindow, _inWindow(softwareRenderer));
break;
case REG_SCY:
softwareRenderer->scy = value;
@@ -88,9 +114,11 @@ static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer*
break;
case REG_WY:
softwareRenderer->wy = value;
+ GBVideoSoftwareRendererUpdateWindow(softwareRenderer, wasWindow, _inWindow(softwareRenderer));
break;
case REG_WX:
softwareRenderer->wx = value;
+ GBVideoSoftwareRendererUpdateWindow(softwareRenderer, wasWindow, _inWindow(softwareRenderer));
break;
}
return value;
@@ -134,6 +162,7 @@ static void GBVideoSoftwareRendererWriteOAM(struct GBVideoRenderer* renderer, ui
static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
+ softwareRenderer->lastY = y;
uint8_t* maps = &softwareRenderer->d.vram[GB_BASE_MAP];
if (GBRegisterLCDCIsTileMap(softwareRenderer->lcdc)) {
maps += GB_SIZE_MAP;
@@ -142,7 +171,8 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
memset(&softwareRenderer->row[startX], 0, endX - startX);
}
if (GBRegisterLCDCIsBgEnable(softwareRenderer->lcdc) || softwareRenderer->model >= GB_MODEL_CGB) {
- if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && softwareRenderer->wy <= y && endX >= softwareRenderer->wx - 7) {
+ int wy = softwareRenderer->wy + softwareRenderer->currentWy;
+ if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && wy <= y && endX >= softwareRenderer->wx - 7) {
if (softwareRenderer->wx - 7 > 0 && !softwareRenderer->d.disableBG) {
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx, softwareRenderer->scy + y);
}
@@ -152,7 +182,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
maps += GB_SIZE_MAP;
}
if (!softwareRenderer->d.disableWIN) {
- GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx, softwareRenderer->currentWy);
+ GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx, y - wy);
}
} else if (!softwareRenderer->d.disableBG) {
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx, softwareRenderer->scy + y);
@@ -201,7 +231,9 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer)
if (!GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) {
_clearScreen(softwareRenderer);
}
+ softwareRenderer->lastY = GB_VIDEO_VERTICAL_PIXELS;
softwareRenderer->currentWy = 0;
+ softwareRenderer->hasWindow = false;
}
static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int sx, int sy) {
View
@@ -260,7 +260,7 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
struct GBAAudio* audio = user;
int16_t sampleLeft = 0;
int16_t sampleRight = 0;
- int psgShift = 5 - audio->volume;
+ int psgShift = 4 - audio->volume;
GBAudioSamplePSG(&audio->psg, &sampleLeft, &sampleRight);
sampleLeft >>= psgShift;
sampleRight >>= psgShift;
View
@@ -529,8 +529,10 @@ static void _unLz77(struct GBA* gba, int width) {
source += 2;
disp = dest - (block & 0x0FFF) - 1;
bytes = (block >> 12) + 3;
- while (bytes-- && remaining) {
- --remaining;
+ while (bytes--) {
+ if (remaining) {
+ --remaining;
+ }
if (width == 2) {
byte = (int16_t) cpu->memory.load16(cpu, disp & ~1, 0);
if (dest & 1) {
View
@@ -85,6 +85,15 @@ uint16_t GBADMAWriteCNT_HI(struct GBA* gba, int dma, uint16_t control) {
currentDma->reg = GBADMARegisterClearSrcControl(currentDma->reg);
}
currentDma->nextDest = currentDma->dest;
+
+ uint32_t width = 2 << GBADMARegisterGetWidth(currentDma->reg);
+ if (currentDma->nextSource & (width - 1)) {
+ mLOG(GBA_MEM, GAME_ERROR, "Misaligned DMA source address: 0x%08X", currentDma->nextSource);
+ }
+ if (currentDma->nextDest & (width - 1)) {
+ mLOG(GBA_MEM, GAME_ERROR, "Misaligned DMA destination address: 0x%08X", currentDma->nextDest);
+ }
+
GBADMASchedule(gba, dma, currentDma);
}
// If the DMA has already occurred, this value might have changed since the function started
View
@@ -1561,4 +1561,5 @@ void _pristineCow(struct GBA* gba) {
}
gba->memory.rom = newRom;
gba->memory.hw.gpioBase = &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1];
+ gba->isPristine = false;
}
@@ -148,7 +148,8 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23;
x >>= 23;
uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1];
- unsigned charBase = (GBAObjAttributesCGetTile(sprite->c) & ~GBAObjAttributesAGet256Color(sprite->a)) * 0x20;
+ bool align = GBAObjAttributesAIs256Color(sprite->a) && !GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt);
+ unsigned charBase = (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x20;
if (GBARegisterDISPCNTGetMode(renderer->dispcnt) >= 3 && GBAObjAttributesCGetTile(sprite->c) < 512) {
return 0;
}
@@ -27,19 +27,19 @@ static bool _checkWatchpoints(struct LR35902Debugger* debugger, uint16_t address
debuggerFound: break; \
} while(0)
-#define CREATE_WATCHPOINT_SHIM(NAME, RW, RETURN, TYPES, ...) \
+#define CREATE_WATCHPOINT_SHIM(NAME, RW, VALUE, RETURN, TYPES, ...) \
static RETURN DebuggerShim_ ## NAME TYPES { \
struct LR35902Debugger* debugger; \
FIND_DEBUGGER(debugger, cpu); \
struct mDebuggerEntryInfo info; \
- if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_ ## RW, 0)) { \
+ if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_ ## RW, VALUE)) { \
mDebuggerEnter(debugger->d.p, DEBUGGER_ENTER_WATCHPOINT, &info); \
} \
return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \
}
-CREATE_WATCHPOINT_SHIM(load8, READ, uint8_t, (struct LR35902Core* cpu, uint16_t address), address)
-CREATE_WATCHPOINT_SHIM(store8, WRITE, void, (struct LR35902Core* cpu, uint16_t address, int8_t value), address, value)
+CREATE_WATCHPOINT_SHIM(load8, READ, 0, uint8_t, (struct LR35902Core* cpu, uint16_t address), address)
+CREATE_WATCHPOINT_SHIM(store8, WRITE, value, void, (struct LR35902Core* cpu, uint16_t address, int8_t value), address, value)
static bool _checkWatchpoints(struct LR35902Debugger* debugger, uint16_t address, struct mDebuggerEntryInfo* info, enum mWatchpointType type, uint8_t newValue) {
struct LR35902DebugWatchpoint* watchpoint;
View
@@ -241,7 +241,11 @@ static struct VFile* _vd3dOpenFile(struct VDir* vd, const char* path, int mode)
}
const char* dir = vd3d->path;
char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2));
- sprintf(combined, "%s/%s", dir, path);
+ if (dir[strlen(dir) - 1] == '/') {
+ sprintf(combined, "%s%s", dir, path);
+ } else {
+ sprintf(combined, "%s/%s", dir, path);
+ }
struct VFile* file = VFileOpen(combined, mode);
free(combined);
@@ -255,7 +259,11 @@ static struct VDir* _vd3dOpenDir(struct VDir* vd, const char* path) {
}
const char* dir = vd3d->path;
char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2));
- sprintf(combined, "%s/%s", dir, path);
+ if (dir[strlen(dir) - 1] == '/') {
+ sprintf(combined, "%s%s", dir, path);
+ } else {
+ sprintf(combined, "%s/%s", dir, path);
+ }
struct VDir* vd2 = VDirOpen(combined);
if (!vd2) {
@@ -272,7 +280,11 @@ static bool _vd3dDeleteFile(struct VDir* vd, const char* path) {
}
const char* dir = vd3d->path;
char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2));
- sprintf(combined, "%s/%s", dir, path);
+ if (dir[strlen(dir) - 1] == '/') {
+ sprintf(combined, "%s%s", dir, path);
+ } else {
+ sprintf(combined, "%s/%s", dir, path);
+ }
uint16_t utf16Path[PATH_MAX + 1];
ssize_t units = utf8_to_utf16(utf16Path, (const uint8_t*) combined, PATH_MAX);
@@ -10,6 +10,10 @@
#include <mgba-util/vfs.h>
#include <mgba-util/memory.h>
+#ifndef SCE_CST_SIZE
+#define SCE_CST_SIZE 0x0004
+#endif
+
struct VFileSce {
struct VFile d;
@@ -120,20 +124,8 @@ static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size) {
static void _vfsceTruncate(struct VFile* vf, size_t size) {
struct VFileSce* vfsce = (struct VFileSce*) vf;
- SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
- SceOff end = sceIoLseek(vfsce->fd, 0, SEEK_END);
- if (end < size) {
- uint8_t buffer[2048] = {};
- size_t write = size - end;
- while (write >= sizeof(buffer)) {
- sceIoWrite(vfsce->fd, buffer, sizeof(buffer));
- write -= sizeof(buffer);
- }
- if (write) {
- sceIoWrite(vfsce->fd, buffer, write);
- }
- } // TODO: Else
- sceIoLseek(vfsce->fd, cur, SEEK_SET);
+ SceIoStat stat = { .st_size = size };
+ sceIoChstatByFd(vfsce->fd, &stat, SCE_CST_SIZE);
}
ssize_t _vfsceSize(struct VFile* vf) {
Oops, something went wrong.

0 comments on commit 932908b

Please sign in to comment.