Skip to content

Commit

Permalink
Ensure the video capture DMA can't be enabled/disabled mid-frame.
Browse files Browse the repository at this point in the history
Fix #30.
  • Loading branch information
Arignir committed Feb 18, 2024
1 parent b238817 commit 8d0b773
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
11 changes: 6 additions & 5 deletions include/gba/ppu.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,19 @@ union oam_entry {
static_assert(sizeof(union oam_entry) == 3 * sizeof(uint16_t));

struct ppu {
// The emulator's screen as it is being rendered.
/* The emulator's screen as it is being rendered. */
uint32_t framebuffer[GBA_SCREEN_WIDTH * GBA_SCREEN_HEIGHT];

// Internal registers used for affine backgrounds
/* Internal registers used for affine backgrounds */
int32_t internal_px[2];
int32_t internal_py[2];

// Set when the registers above must be reloaded at the next H-Draw.
bool reload_internal_affine_regs;
bool reload_internal_affine_regs; // Set when the registers above must be reloaded at the next H-Draw.

bool win_masks[2][GBA_SCREEN_WIDTH];
uint32_t win_masks_hash[2]; /* The min/max for that windows. Kept to avoid rebuilding the mask across scanlines. */
uint32_t win_masks_hash[2]; // The min/max for that windows. Kept to avoid rebuilding the mask across scanlines. */

bool video_capture_enabled; // Set when the DMA video capture is enabled
};

/* gba/ppu/background/bitmap.c */
Expand Down
7 changes: 6 additions & 1 deletion source/gba/memory/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,14 @@ mem_schedule_dma_transfers_for(
enum dma_timings timing
) {
struct dma_channel *channel;
bool enabled;

channel = &gba->io.dma[channel_idx];
if (channel->control.enable && channel->control.timing == timing) {

/* Bypass the usual enable check for DMA3's video mode */
enabled = (channel_idx == 3 && timing == DMA_TIMING_SPECIAL) ? gba->ppu.video_capture_enabled : channel->control.enable;

if (enabled && channel->control.timing == timing) {
channel->enable_event_handle = sched_add_event(
gba,
NEW_FIX_EVENT_ARGS(
Expand Down
13 changes: 12 additions & 1 deletion source/gba/ppu/ppu.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,20 @@ ppu_hblank(
mem_schedule_dma_transfers(gba, DMA_TIMING_HBLANK);
}

if (io->vcount.raw >= 2 && io->vcount.raw < GBA_SCREEN_HEIGHT + 2) {
if (gba->ppu.video_capture_enabled && io->vcount.raw >= 2 && io->vcount.raw < GBA_SCREEN_HEIGHT + 2) {
mem_schedule_dma_transfers_for(gba, 3, DMA_TIMING_SPECIAL); // Video DMA
}

/*
** Video mode is evaluated once at the beginning of the frame and can't be enabled/disabled mid-frame.
**
** Reference:
** - https://github.com/mgba-emu/mgba/issues/2017
** - https://github.com/skylersaleh/SkyEmu/issues/104
*/
if (io->vcount.raw == GBA_SCREEN_HEIGHT + 2) {
gba->ppu.video_capture_enabled = gba->io.dma[3].control.enable && gba->io.dma[3].control.timing == DMA_TIMING_SPECIAL;
}
}

/*
Expand Down

0 comments on commit 8d0b773

Please sign in to comment.