Merge branch 'master' (early part) into medusa

This commit is contained in:
Vicki Pfau 2021-06-11 18:59:29 -07:00
commit 9c5144909b
28 changed files with 595 additions and 546 deletions

77
CHANGES
View File

@ -46,23 +46,18 @@ 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
Emulation fixes:
- ARM: Fix ALU reading PC after shifting
- ARM: Fix STR storing PC after address calculation
- ARM: Fix Addressing mode 1 shifter on rs == pc (fixes mgba.io/i/1926)
- GB: Partially fix timing for skipped BIOS
- GB Audio: Fix initial sweep state
- GB Audio: Fix serializing sweep time
- GB Audio: Fix deserializing audio channels 2 and 3
- GB Audio: Fix deserializing while audio was disabled (fixes mgba.io/i/1305)
- GB MBC: Fix MBC1 mode changing behavior
- GB MBC: Fix some MBC3 bit masking
- GB Video: Fix state after skipping BIOS (fixes mgba.io/i/1715 and mgba.io/i/1716)
- GB Video: Fix drawing background when window is force-disabled by frontend
- GBA: Fix timing advancing too quickly in rare cases
- GBA: Clear GBP connection on reset
- GBA Audio: Fix deserializing SOUNDCNT_L
- GBA Audio: Fix stereo in XQ audio
- GBA Audio: Fix volume/mute in XQ audio (fixes mgba.io/i/1864)
- GBA Audio: Revamp FIFO emulation (fixes mgba.io/i/356, mgba.io/i/875, mgba.io/i/1847)
- GBA BIOS: Implement dummy sound driver calls
- GBA BIOS: Improve HLE BIOS timing
@ -70,7 +65,6 @@ Emulation fixes:
- GBA BIOS: Make HLE BIOS calls interruptable (fixes mgba.io/i/1711 and mgba.io/i/1823)
- GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320)
- GBA DMA: Fix ordering and timing of overlapping DMAs
- GBA Hardware: Fix GB Player detection on big endian platforms
- GBA I/O: Green swap register should be readable
- GBA Memory: Improve gamepak prefetch timing
- GBA Memory: Stall on VRAM access in mode 2 (fixes mgba.io/i/190)
@ -80,45 +74,24 @@ Emulation fixes:
- GBA SIO: Fix deseralizing SIO registers
- GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319)
- GBA Video: Fix Hblank timing
- GBA Video: Invalidate map cache when modifying BGCNT (fixes mgba.io/i/1846)
- GBA Video: Don't draw sprites using unmapped VRAM in GL renderer (fixes mgba.io/i/1865)
- GBA Video: Implement green swap (fixes mgba.io/i/1609)
- GBA Video: Fix rare regression blending semitransparent sprites (fixes mgba.io/i/1876)
- GBA Video: Emulate sprite cycle limits in OpenGL renderer (fixes mgba.io/i/1635)
- GBA Video: Do not affect OBJ pixel priority when writing OBJWIN (fixes mgba.io/i/1890)
- GBA Video: Fix deferred blending when OBJWIN matches window (fixes mgba.io/i/1905)
- GBA Video: Fix mode 4 transparency in OpenGL (fixes mgba.io/i/1907)
- SM83: Emulate HALT bug
Other fixes:
- 3DS: Redo video sync to be more precise
- 3DS: Fix crash with libctru 2.0 when exiting
- 3DS: Fix thread cleanup
- All: Improve export headers (fixes mgba.io/i/1738)
- CMake: Fix build with downstream minizip that exports incompatible symbols
- Core: Ensure ELF regions can be written before trying
- Core: Fix reported ROM size when a fixed buffer size is used
- Core: Fix memory leak loading ELF files
- Debugger: Don't skip undefined instructions when debugger attached
- FFmpeg: Fix some small memory leaks
- FFmpeg: Fix encoding of time base
- GBA: Disable more checks when loading GS save with checks disabled (fixes mgba.io/i/1851)
- GBA: Fix endianness issues in renderer proxy
- GBA Core: Fix memory leak when loading symbols
- Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642)
- Qt: Fix static compilation in MinGW (fixes mgba.io/i/1769)
- Qt: Fix a race condition in the frame inspector
- Qt: Add dummy English translation file (fixes mgba.io/i/1469)
- Qt: Fix Battle Chip view not displaying chips on some DPI settings
- Qt: Fix camera image being upside-down sometimes (fixes mgba.io/i/829 again)
- Qt: Fix drawing on macOS break when using OpenGL (fixes mgba.io/i/1899)
- Qt: Load/save bytes from memory viewer in the order visible (fixes mgba.io/i/1900)
- Qt: Fix stride changing when toggling SGB borders (fixes mgba.io/i/1898)
- Qt: Fix aliasing on background logo (fixes mgba.io/i/1886)
- mGUI: Fix closing down a game if an exit is signalled
- mGUI: Fix cycling through config setting states with accept button
- mVL: Fix injecting accidentally draining non-injection buffer
- Qt: Fix running proxied video if it gets pushed to the main thread
- SM83: Simplify register pair access on big endian
- SM83: Disassemble STOP as one byte
- VFS: Fix directory node listing on some filesystems
Misc:
- 3DS: Use "wide mode" where applicable for slightly better filtering
- Core: Add savedataUpdated callback
@ -128,7 +101,6 @@ Misc:
- GBA: Allow pausing event loop while CPU is blocked
- GBA BIOS: Division by zero should emit a FATAL error
- GBA Video: Convert OpenGL VRAM texture to integer
- GBA Video: Improve speed of window texture generation on AMD
- Debugger: Keep track of global cycle count
- FFmpeg: Add looping option for GIF/APNG
- mGUI: Show battery percentage
@ -141,6 +113,47 @@ Misc:
- Util: Reset vector size on deinit
- VFS: Change semantics of VFile.sync on mapped files (fixes mgba.io/i/1730)
0.8.4: (2020-10-29)
Emulation fixes:
- GB Audio: Fix initial sweep state
- GB Audio: Fix deserializing audio channels 2 and 3
- GB Audio: Fix deserializing while audio was disabled (fixes mgba.io/i/1305)
- GB Video: Fix drawing background when window is force-disabled by frontend
- GB, GBA Video: Copy disable flags when drawing scanlines in proxy when not blocking
- GBA Audio: Fix deserializing SOUNDCNT_L
- GBA Audio: Fix stereo in XQ audio
- GBA Audio: Fix volume/mute in XQ audio (fixes mgba.io/i/1864)
- GBA Hardware: Fix GB Player detection on big endian platforms
- GBA Video: Invalidate map cache when modifying BGCNT (fixes mgba.io/i/1846)
- GBA Video: Don't draw sprites using unmapped VRAM in GL renderer (fixes mgba.io/i/1865)
- GBA Video: Fix rare regression blending semitransparent sprites (fixes mgba.io/i/1876)
- GBA Video: Do not affect OBJ pixel priority when writing OBJWIN (fixes mgba.io/i/1890)
- GBA Video: Fix deferred blending when OBJWIN matches window (fixes mgba.io/i/1905)
- GBA Video: Fix mode 4 transparency in OpenGL (fixes mgba.io/i/1907)
Other fixes:
- 3DS: Redo video sync to be more precise
- 3DS: Fix crash with libctru 2.0 when exiting
- ARM Decoder: Fix decoding pre-indexed writeback instructions (fixes mgba.io/i/1915)
- Core: Fix reported ROM size when a fixed buffer size is used
- Core: Fix memory leak loading ELF files
- GBA: Disable more checks when loading GS save with checks disabled (fixes mgba.io/i/1851)
- GBA: Fix endianness issues in renderer proxy
- GBA Core: Fix memory leak when loading symbols
- GBA Serialize: Ensure program counter is aligned when loading
- Qt: Add dummy English translation file (fixes mgba.io/i/1469)
- Qt: Fix Battle Chip view not displaying chips on some DPI settings
- Qt: Fix camera image being upside-down sometimes (fixes mgba.io/i/829 again)
- Qt: Fix drawing on macOS break when using OpenGL (fixes mgba.io/i/1899)
- Qt: Fix stride changing when toggling SGB borders (fixes mgba.io/i/1898)
- Qt: Fix aliasing on background logo (fixes mgba.io/i/1886)
- mGUI: Fix closing down a game if an exit is signalled
- mGUI: Fix cycling through config setting states with accept button
- mVL: Fix injecting accidentally draining non-injection buffer
- VFS: Fix directory node listing on some filesystems
Misc:
- GBA Video: Improve speed of window texture generation on AMD
- Vita: Clear both buffers when loading a game
0.8.3: (2020-08-03)
Emulation fixes:
- ARM: Fix LDM^ writeback to user-mode register

View File

@ -682,6 +682,12 @@ elseif(USE_MINIZIP)
list(APPEND FEATURES MINIZIP)
list(APPEND VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-zip.c)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libminizip1")
set(CMAKE_REQUIRED_LIBRARIES ${MINIZIP_LIBRARIES})
check_function_exists(unztell64 HAVE_UNZTELL64)
unset(CMAKE_REQUIRED_LIBRARIES)
if(NOT HAVE_UNZTELL64)
add_definitions(-Dunztell64=unzTell64) # Bug in downstream minizip that some distros use
endif()
elseif(USE_ZLIB)
list(APPEND VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-zip.c
${CMAKE_CURRENT_SOURCE_DIR}/src/third-party/zlib/contrib/minizip/ioapi.c

View File

@ -34,6 +34,17 @@ enum GBASIOJOYCommand {
JOY_RECV = 0x15
};
enum GBAVideoLayer {
GBA_LAYER_BG0 = 0,
GBA_LAYER_BG1,
GBA_LAYER_BG2,
GBA_LAYER_BG3,
GBA_LAYER_OBJ,
GBA_LAYER_WIN0,
GBA_LAYER_WIN1,
GBA_LAYER_OBJWIN,
};
struct GBA;
struct GBAAudio;
struct GBASIO;

View File

@ -40,7 +40,7 @@ struct ARMDebugger {
void (*entered)(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
ssize_t (*setSoftwareBreakpoint)(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode);
bool (*setSoftwareBreakpoint)(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode);
void (*clearSoftwareBreakpoint)(struct ARMDebugger*, const struct ARMDebugBreakpoint*);
};

View File

@ -135,6 +135,8 @@ struct GBAVideoSoftwareRenderer {
struct GBAVideoWindowRegion h;
struct GBAVideoWindowRegion v;
struct WindowControl control;
int16_t offsetX;
int16_t offsetY;
} winN[2];
struct WindowControl winout;

View File

@ -199,6 +199,8 @@ struct GBAVideoRenderer {
bool disableBG[4];
bool disableOBJ;
bool disableWIN[2];
bool disableOBJWIN;
bool highlightBG[4];
bool highlightOBJ[128];

View File

@ -1,6 +1,4 @@
Miras Absar
Emily A. Bellows
Jaime J. Denizard
Benedikt Feih
Mored1984
Johnathan Roatch
Yuri Kunde Schlesner

View File

@ -218,6 +218,7 @@
ARM_MEMORY_ ## FORMAT, \
ADDRESSING_MODE, FORMAT ## _CYCLES, ARM_ACCESS_ ## TYPE, OTHER_AFFECTED) \
DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## PUW, MNEMONIC, \
ARM_MEMORY_PRE_INCREMENT | \
ARM_MEMORY_WRITEBACK | \
ARM_MEMORY_ ## FORMAT, \
ADDRESSING_MODE, FORMAT ## _CYCLES, ARM_ACCESS_ ## TYPE, OTHER_AFFECTED) \

View File

@ -20,15 +20,11 @@ static inline void _shiftLSL(struct ARMCore* cpu, uint32_t opcode) {
if (opcode & 0x00000010) {
int rs = (opcode >> 8) & 0x0000000F;
++cpu->cycles;
int shift = cpu->gprs[rs];
if (rs == ARM_PC) {
shift += 4;
}
shift &= 0xFF;
int32_t shiftVal = cpu->gprs[rm];
if (rm == ARM_PC) {
shiftVal += 4;
}
int shift = cpu->gprs[rs] & 0xFF;
if (!shift) {
cpu->shifterOperand = shiftVal;
cpu->shifterCarryOut = cpu->cpsr.c;
@ -59,15 +55,11 @@ static inline void _shiftLSR(struct ARMCore* cpu, uint32_t opcode) {
if (opcode & 0x00000010) {
int rs = (opcode >> 8) & 0x0000000F;
++cpu->cycles;
int shift = cpu->gprs[rs];
if (rs == ARM_PC) {
shift += 4;
}
shift &= 0xFF;
uint32_t shiftVal = cpu->gprs[rm];
if (rm == ARM_PC) {
shiftVal += 4;
}
int shift = cpu->gprs[rs] & 0xFF;
if (!shift) {
cpu->shifterOperand = shiftVal;
cpu->shifterCarryOut = cpu->cpsr.c;
@ -98,15 +90,11 @@ static inline void _shiftASR(struct ARMCore* cpu, uint32_t opcode) {
if (opcode & 0x00000010) {
int rs = (opcode >> 8) & 0x0000000F;
++cpu->cycles;
int shift = cpu->gprs[rs];
if (rs == ARM_PC) {
shift += 4;
}
shift &= 0xFF;
int shiftVal = cpu->gprs[rm];
if (rm == ARM_PC) {
shiftVal += 4;
}
int shift = cpu->gprs[rs] & 0xFF;
if (!shift) {
cpu->shifterOperand = shiftVal;
cpu->shifterCarryOut = cpu->cpsr.c;
@ -137,15 +125,11 @@ static inline void _shiftROR(struct ARMCore* cpu, uint32_t opcode) {
if (opcode & 0x00000010) {
int rs = (opcode >> 8) & 0x0000000F;
++cpu->cycles;
int shift = cpu->gprs[rs];
if (rs == ARM_PC) {
shift += 4;
}
shift &= 0xFF;
int shiftVal = cpu->gprs[rm];
if (rm == ARM_PC) {
shiftVal += 4;
}
int shift = cpu->gprs[rs] & 0xFF;
int rotate = shift & 0x1F;
if (!shift) {
cpu->shifterOperand = shiftVal;
@ -319,13 +303,13 @@ ATTRIBUTE_NOINLINE static void _neutralS(struct ARMCore* cpu, int32_t d) {
#define DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, S_BODY, SHIFTER, BODY) \
DEFINE_INSTRUCTION_ARM(NAME, \
SHIFTER(cpu, opcode); \
int rd = (opcode >> 12) & 0xF; \
int rn = (opcode >> 16) & 0xF; \
int32_t n = cpu->gprs[rn]; \
if (UNLIKELY(rn == ARM_PC && (opcode & 0x02000010) == 0x00000010)) { \
n += WORD_SIZE_ARM; \
} \
SHIFTER(cpu, opcode); \
BODY; \
S_BODY; \
if (rd == ARM_PC) { \

View File

@ -235,6 +235,9 @@ 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;
proxyRenderer->backend->drawRange(proxyRenderer->backend, startX, endX, y);
}
mVideoLoggerRendererDrawRange(proxyRenderer->logger, startX, endX, y);

View File

@ -37,11 +37,14 @@
#endif
static const struct mCoreChannelInfo _GBAVideoLayers[] = {
{ 0, "bg0", "Background 0", NULL },
{ 1, "bg1", "Background 1", NULL },
{ 2, "bg2", "Background 2", NULL },
{ 3, "bg3", "Background 3", NULL },
{ 4, "obj", "Objects", NULL },
{ GBA_LAYER_BG0, "bg0", "Background 0", NULL },
{ GBA_LAYER_BG1, "bg1", "Background 1", NULL },
{ GBA_LAYER_BG2, "bg2", "Background 2", NULL },
{ GBA_LAYER_BG3, "bg3", "Background 3", NULL },
{ GBA_LAYER_OBJ, "obj", "Objects", NULL },
{ GBA_LAYER_WIN0, "win0", "Window 0", NULL },
{ GBA_LAYER_WIN1, "win1", "Window 1", NULL },
{ GBA_LAYER_OBJWIN, "objwin", "Object Window", NULL },
};
static const struct mCoreChannelInfo _GBAAudioChannels[] = {
@ -1060,15 +1063,24 @@ static size_t _GBACoreListAudioChannels(const struct mCore* core, const struct m
static void _GBACoreEnableVideoLayer(struct mCore* core, size_t id, bool enable) {
struct GBA* gba = core->board;
switch (id) {
case 0:
case 1:
case 2:
case 3:
case GBA_LAYER_BG0:
case GBA_LAYER_BG1:
case GBA_LAYER_BG2:
case GBA_LAYER_BG3:
gba->video.renderer->disableBG[id] = !enable;
break;
case 4:
case GBA_LAYER_OBJ:
gba->video.renderer->disableOBJ = !enable;
break;
case GBA_LAYER_WIN0:
gba->video.renderer->disableWIN[0] = !enable;
break;
case GBA_LAYER_WIN1:
gba->video.renderer->disableWIN[1] = !enable;
break;
case GBA_LAYER_OBJWIN:
gba->video.renderer->disableOBJWIN = !enable;
break;
default:
break;
}
@ -1097,18 +1109,22 @@ static void _GBACoreEnableAudioChannel(struct mCore* core, size_t id, bool enabl
static void _GBACoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, int32_t y) {
struct GBACore* gbacore = (struct GBACore*) core;
switch (id) {
case 0:
case 1:
case 2:
case 3:
case GBA_LAYER_BG0:
case GBA_LAYER_BG1:
case GBA_LAYER_BG2:
case GBA_LAYER_BG3:
gbacore->renderer.bg[id].offsetX = x;
gbacore->renderer.bg[id].offsetY = y;
break;
case 4:
case GBA_LAYER_OBJ:
gbacore->renderer.objOffsetX = x;
gbacore->renderer.objOffsetY = y;
gbacore->renderer.oamDirty = 1;
break;
case GBA_LAYER_WIN0:
gbacore->renderer.winN[id - GBA_LAYER_WIN0].offsetX = x;
gbacore->renderer.winN[id - GBA_LAYER_WIN0].offsetY = y;
break;
default:
return;
}

View File

@ -43,6 +43,9 @@ void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct
renderer->d.disableBG[2] = false;
renderer->d.disableBG[3] = false;
renderer->d.disableOBJ = false;
renderer->d.disableWIN[0] = false;
renderer->d.disableWIN[1] = false;
renderer->d.disableOBJWIN = false;
renderer->d.highlightBG[0] = false;
renderer->d.highlightBG[1] = false;
@ -216,6 +219,9 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD
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];
@ -315,6 +321,18 @@ 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];
proxyRenderer->backend->drawScanline(proxyRenderer->backend, y);
}
mVideoLoggerRendererDrawScanline(proxyRenderer->logger, y);

View File

@ -233,7 +233,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
uint32_t flags = GBAObjAttributesCGetPriority(sprite->c) << OFFSET_PRIORITY;
flags |= FLAG_TARGET_1 * ((GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT);
flags |= FLAG_OBJWIN * (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN);
if ((flags & FLAG_OBJWIN) && renderer->currentWindow.priority < renderer->objwin.priority) {
if ((flags & FLAG_OBJWIN) && (renderer->currentWindow.priority < renderer->objwin.priority || renderer->d.disableOBJWIN)) {
return 0;
}
int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23;

View File

@ -59,6 +59,16 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
renderer->d.disableBG[2] = false;
renderer->d.disableBG[3] = false;
renderer->d.disableOBJ = false;
renderer->d.disableWIN[0] = false;
renderer->d.disableWIN[1] = false;
renderer->d.disableOBJWIN = false;
renderer->d.highlightBG[0] = false;
renderer->d.highlightBG[1] = false;
renderer->d.highlightBG[2] = false;
renderer->d.highlightBG[3] = false;
renderer->tileStride = 0x20;
renderer->bitmapStride = 0;
renderer->combinedObjSort = false;
@ -66,10 +76,6 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
renderer->masterHeight = GBA_VIDEO_VERTICAL_PIXELS;
renderer->masterScanlines = VIDEO_VERTICAL_TOTAL_PIXELS;
renderer->d.highlightBG[0] = false;
renderer->d.highlightBG[1] = false;
renderer->d.highlightBG[2] = false;
renderer->d.highlightBG[3] = false;
int i;
for (i = 0; i < 128; ++i) {
renderer->d.highlightOBJ[i] = false;
@ -457,13 +463,13 @@ static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* render
static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win, int y) {
if (win->v.end >= win->v.start) {
if (y >= win->v.end) {
if (y >= win->v.end + win->offsetY) {
return;
}
if (y < win->v.start) {
if (y < win->v.start + win->offsetY) {
return;
}
} else if (y >= win->v.end && y < win->v.start) {
} else if (y >= win->v.end + win->offsetY && y < win->v.start + win->offsetY) {
return;
}
if (win->h.end > softwareRenderer->masterEnd || win->h.end < win->h.start) {
@ -880,10 +886,10 @@ void GBAVideoSoftwareRendererPreprocessBuffer(struct GBAVideoSoftwareRenderer* s
softwareRenderer->nWindows = 1;
if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt)) {
softwareRenderer->windows[0].control = softwareRenderer->winout;
if (GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt)) {
if (GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) && !softwareRenderer->d.disableWIN[1]) {
_breakWindow(softwareRenderer, &softwareRenderer->winN[1], y);
}
if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt)) {
if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) && !softwareRenderer->d.disableWIN[0]) {
_breakWindow(softwareRenderer, &softwareRenderer->winN[0], y);
}
} else {

View File

@ -154,6 +154,11 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
LOAD_32(gba->cpu->bankedSPSRs[i], i * sizeof(gba->cpu->bankedSPSRs[0]), state->cpu.bankedSPSRs);
}
gba->cpu->privilegeMode = gba->cpu->cpsr.priv;
uint32_t pcMask = (gba->cpu->executionMode == MODE_THUMB ? WORD_SIZE_THUMB : WORD_SIZE_ARM) - 1;
if (gba->cpu->gprs[ARM_PC] & pcMask) {
mLOG(GBA_STATE, WARN, "Savestate has unaligned PC and is probably corrupted");
gba->cpu->gprs[ARM_PC] &= ~pcMask;
}
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
if (state->biosPrefetch) {
LOAD_32(gba->memory.biosPrefetch, 0, &state->biosPrefetch);

View File

@ -615,9 +615,10 @@ bool retro_load_game(const struct retro_game_info* game) {
cam.width = GBCAM_WIDTH;
cam.caps = 1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER;
cam.frame_raw_framebuffer = _updateCamera;
core->setPeripheral(core, mPERIPH_IMAGE_SOURCE, &imageSource);
if (environCallback(RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE, &cam)) {
core->setPeripheral(core, mPERIPH_IMAGE_SOURCE, &imageSource);
}
environCallback(RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE, &cam);
const char* modelName = mCoreConfigGetValue(&core->config, "gb.model");
struct GB* gb = core->board;

View File

@ -328,6 +328,9 @@ void mPSP2Setup(struct mGUIRunner* runner) {
currentTex = 0;
screenshot = vita2d_create_empty_texture_format(256, toPow2(height), SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR);
memset(vita2d_texture_get_datap(tex[0]), 0xFF, 256 * toPow2(height) * 4);
memset(vita2d_texture_get_datap(tex[1]), 0xFF, 256 * toPow2(height) * 4);
runner->core->setVideoBuffer(runner->core, vita2d_texture_get_datap(tex[currentTex]), 256);
runner->core->setAudioBufferSize(runner->core, PSP2_SAMPLES);

View File

@ -5,7 +5,23 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from ._pylib import ffi, lib # pylint: disable=no-name-in-module
from collections import namedtuple
class Git:
commit = None
if lib.gitCommit and lib.gitCommit != "(unknown)":
commit = ffi.string(lib.gitCommit).decode('utf-8')
commitShort = None
if lib.gitCommitShort and lib.gitCommitShort != "(unknown)":
commitShort = ffi.string(lib.gitCommitShort).decode('utf-8')
branch = None
if lib.gitBranch and lib.gitBranch != "(unknown)":
branch = ffi.string(lib.gitBranch).decode('utf-8')
revision = None
if lib.gitRevision > 0:
revision = lib.gitRevision
def create_callback(struct_name, cb_name, func_name=None):
@ -20,17 +36,3 @@ def create_callback(struct_name, cb_name, func_name=None):
__version__ = ffi.string(lib.projectVersion).decode('utf-8')
GitInfo = namedtuple("GitInfo", "commit commitShort branch revision")
GIT = {}
if lib.gitCommit and lib.gitCommit != "(unknown)":
GIT['commit'] = ffi.string(lib.gitCommit).decode('utf-8')
if lib.gitCommitShort and lib.gitCommitShort != "(unknown)":
GIT['commitShort'] = ffi.string(lib.gitCommitShort).decode('utf-8')
if lib.gitBranch and lib.gitBranch != "(unknown)":
GIT['branch'] = ffi.string(lib.gitBranch).decode('utf-8')
if lib.gitRevision > 0:
GIT['revision'] = lib.gitRevision
GIT = GitInfo(**GIT)

View File

@ -24,6 +24,7 @@
#endif
#ifdef M_CORE_GB
#include <mgba/internal/gb/gb.h>
#include <mgba/internal/gb/io.h>
#include <mgba/internal/gb/memory.h>
#endif
@ -153,16 +154,44 @@ void FrameView::updateTilesGBA(bool) {
uint16_t* io = static_cast<GBA*>(m_controller->thread()->core->board)->memory.io;
QRgb backdrop = M_RGB5_TO_RGB8(static_cast<GBA*>(m_controller->thread()->core->board)->video.palette[0]);
m_gbaDispcnt = io[REG_DISPCNT >> 1];
int mode = GBARegisterDISPCNTGetMode(m_gbaDispcnt);
GBARegisterDISPCNT gbaDispcnt = io[REG_DISPCNT >> 1];
int mode = GBARegisterDISPCNTGetMode(gbaDispcnt);
std::array<bool, 4> enabled{
bool(GBARegisterDISPCNTIsBg0Enable(m_gbaDispcnt)),
bool(GBARegisterDISPCNTIsBg1Enable(m_gbaDispcnt)),
bool(GBARegisterDISPCNTIsBg2Enable(m_gbaDispcnt)),
bool(GBARegisterDISPCNTIsBg3Enable(m_gbaDispcnt)),
bool(GBARegisterDISPCNTIsBg0Enable(gbaDispcnt)),
bool(GBARegisterDISPCNTIsBg1Enable(gbaDispcnt)),
bool(GBARegisterDISPCNTIsBg2Enable(gbaDispcnt)),
bool(GBARegisterDISPCNTIsBg3Enable(gbaDispcnt)),
};
if (GBARegisterDISPCNTIsWin0Enable(gbaDispcnt)) {
m_queue.append({
{ LayerId::WINDOW, 0 },
!m_disabled.contains({ LayerId::WINDOW, 0 }),
{},
{}, {0, 0}, true, false
});
}
if (GBARegisterDISPCNTIsWin1Enable(gbaDispcnt)) {
m_queue.append({
{ LayerId::WINDOW, 1 },
!m_disabled.contains({ LayerId::WINDOW, 1 }),
{},
{}, {0, 0}, true, false
});
}
if (GBARegisterDISPCNTIsObjwinEnable(gbaDispcnt)) {
m_queue.append({
{ LayerId::WINDOW, 2 },
!m_disabled.contains({ LayerId::WINDOW, 2 }),
{},
{}, {0, 0}, true, false
});
}
for (int priority = 0; priority < 4; ++priority) {
for (int sprite = 0; sprite < 128; ++sprite) {
ObjInfo info;
@ -270,6 +299,9 @@ void FrameView::injectGBA() {
gba->video.renderer->highlightBG[layer.id.index] = true;
}
break;
case LayerId::WINDOW:
m_vl->enableVideoLayer(m_vl, GBA_LAYER_WIN0 + layer.id.index, layer.enabled);
break;
}
}
if (m_overrideBackdrop.isValid()) {
@ -286,6 +318,9 @@ void FrameView::updateTilesGB(bool) {
m_queue.clear();
{
CoreController::Interrupter interrupter(m_controller);
uint8_t* io = static_cast<GB*>(m_controller->thread()->core->board)->memory.io;
GBRegisterLCDC lcdc = io[GB_REG_LCDC];
for (int sprite = 0; sprite < 40; ++sprite) {
ObjInfo info;
lookupObj(sprite, &info);
@ -312,6 +347,22 @@ void FrameView::updateTilesGB(bool) {
}
}
if (GBRegisterLCDCIsWindow(lcdc)) {
m_queue.append({
{ LayerId::WINDOW },
!m_disabled.contains({ LayerId::WINDOW }),
{},
{}, {0, 0}, false, false
});
}
m_queue.append({
{ LayerId::BACKGROUND },
!m_disabled.contains({ LayerId::BACKGROUND }),
{},
{}, {0, 0}, false, false
});
updateRendered();
}
invalidateQueue(m_controller->screenDimensions());
@ -328,6 +379,12 @@ void FrameView::injectGB() {
mVideoLoggerInjectOAM(logger, layer.id.index << 2, 0);
}
break;
case LayerId::BACKGROUND:
m_vl->enableVideoLayer(m_vl, GB_LAYER_BACKGROUND, layer.enabled);
break;
case LayerId::WINDOW:
m_vl->enableVideoLayer(m_vl, GB_LAYER_WINDOW, layer.enabled);
break;
}
}
}
@ -495,6 +552,11 @@ QString FrameView::LayerId::readable() const {
break;
case WINDOW:
typeStr = tr("Window");
#ifdef M_CORE_GBA
if (index == 2) {
return tr("Objwin");
}
#endif
break;
case SPRITE:
typeStr = tr("Sprite");

View File

@ -72,7 +72,7 @@ private:
int index = -1;
bool operator!=(const LayerId& other) const { return other.type != type || other.index != index; }
operator uint() const { return (type << 8) | index; }
operator uint() const { return (type << 12) | (index & 0xFFF); }
QString readable() const;
};
@ -112,10 +112,6 @@ private:
ColorPicker m_backdropPicker;
QColor m_overrideBackdrop;
#ifdef M_CORE_GBA
uint16_t m_gbaDispcnt;
#endif
std::shared_ptr<bool> m_callbackLocker{std::make_shared<bool>(true)};
};

View File

@ -207,6 +207,9 @@ void MemoryView::setIndex(int index) {
mCore* core = m_controller->thread()->core;
const mCoreMemoryBlock* blocks;
size_t nBlocks = core->listMemoryBlocks(core, &blocks);
if (index < 0 || static_cast<size_t>(index) >= nBlocks) {
return;
}
const mCoreMemoryBlock& info = blocks[index];
m_region = qMakePair(info.start, info.end);
@ -221,7 +224,11 @@ void MemoryView::setSegment(int segment) {
mCore* core = m_controller->thread()->core;
const mCoreMemoryBlock* blocks;
size_t nBlocks = core->listMemoryBlocks(core, &blocks);
const mCoreMemoryBlock& info = blocks[m_ui.regions->currentIndex()];
int index = m_ui.regions->currentIndex();
if (index < 0 || static_cast<size_t>(index) >= nBlocks) {
return;
}
const mCoreMemoryBlock& info = blocks[index];
m_ui.hexfield->setSegment(info.maxSegment < segment ? info.maxSegment : segment);
}

View File

@ -58,11 +58,16 @@ void VideoProxy::deinit() {
bool VideoProxy::writeData(const void* data, size_t length) {
while (!RingFIFOWrite(&m_dirtyQueue, data, length)) {
emit dataAvailable();
m_mutex.lock();
m_toThreadCond.wakeAll();
m_fromThreadCond.wait(&m_mutex);
m_mutex.unlock();
if (QThread::currentThread() == thread()) {
// We're on the main thread
mVideoLoggerRendererRun(&m_logger.d, false);
} else {
emit dataAvailable();
m_mutex.lock();
m_toThreadCond.wakeAll();
m_fromThreadCond.wait(&m_mutex);
m_mutex.unlock();
}
}
return true;
}
@ -112,9 +117,14 @@ void VideoProxy::unlock() {
void VideoProxy::wait() {
m_mutex.lock();
while (RingFIFOSize(&m_dirtyQueue)) {
emit dataAvailable();
m_toThreadCond.wakeAll();
m_fromThreadCond.wait(&m_mutex, 1);
if (QThread::currentThread() == thread()) {
// We're on the main thread
mVideoLoggerRendererRun(&m_logger.d, false);
} else {
emit dataAvailable();
m_toThreadCond.wakeAll();
m_fromThreadCond.wait(&m_mutex, 1);
}
}
m_mutex.unlock();
}

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,6 @@ list(APPEND GUI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c)
include_directories(AFTER ${OPENGLES3_INCLUDE_DIR} ${OPENGL_EGL_INCLUDE_DIR})
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/wii/wii-*.c)
if(${CMAKE_BUILD_TYPE} STREQUAL Debug OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDebInfo)
find_library(NOUVEAU_LIBRARY drm_nouveaud REQUIRED)
list(APPEND OS_LIB nxd)
@ -20,7 +19,6 @@ else()
endif()
set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE)
set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE)
set(OS_SRC ${OS_SRC} PARENT_SCOPE)
set(OS_LIB ${OS_LIB} PARENT_SCOPE)
if(BUILD_PERF)

View File

@ -8,9 +8,7 @@ list(APPEND CORE_VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-file.c ${CMAKE_SOU
include_directories(${CMAKE_CURRENT_BINARY_DIR})
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/wii/wii-*.c)
list(APPEND OS_LIB wiiuse bte fat ogc)
set(OS_SRC ${OS_SRC} PARENT_SCOPE)
set(OS_LIB ${OS_LIB} PARENT_SCOPE)
source_group("Wii-specific code" FILES ${OS_SRC})
set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE)

View File

@ -1,15 +0,0 @@
/* Copyright (c) 2013-2015 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 <mgba-util/memory.h>
void* anonymousMemoryMap(size_t size) {
return malloc(size);
}
void mappedMemoryFree(void* memory, size_t size) {
UNUSED(size);
free(memory);
}

View File

@ -30,10 +30,15 @@ set(TEST_FILES
test/text-codec.c
test/vfs.c)
if(NOT DEFINED OS_SRC)
set(OS_FILES memory.c)
export_directory(OS OS_FILES)
endif()
source_group("Utilities" FILES ${SOURCE_FILES})
source_group("GUI source" FILES ${GUI_FILES})
source_group("Utilities tests" FILES ${TEST_FILES})
export_directory(UTIL SOURCE_FILES)
export_directory(GUI GUI_FILES)
export_directory(UTIL_TEST TEST_FILES)
export_directory(UTIL_TEST TEST_FILES)

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2018 Jeffrey Pfau
/* Copyright (c) 2013-2020 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
@ -6,7 +6,7 @@
#include <mgba-util/memory.h>
void* anonymousMemoryMap(size_t size) {
return malloc(size);
return calloc(1, size);
}
void mappedMemoryFree(void* memory, size_t size) {