Skip to content

Commit

Permalink
amiga/amiga_v.cpp: move sprite DMA triggers to X defined slots
Browse files Browse the repository at this point in the history
  • Loading branch information
angelosa committed Jan 5, 2025
1 parent a44c48b commit a672b82
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 114 deletions.
4 changes: 2 additions & 2 deletions src/mame/amiga/amiga.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ class amiga_state : public driver_device
void sprite_dma_reset(int which);
void sprite_enable_comparitor(int which, int enable);
void fetch_sprite_data(int scanline, int sprite);
void update_sprite_dma(int scanline);
void update_sprite_dma(int scanline, int num);
uint32_t interleave_sprite_data(uint16_t lobits, uint16_t hibits);
int get_sprite_pixel(int x);
uint8_t assemble_odd_bitplanes(int planes, int ebitoffs);
Expand All @@ -655,7 +655,7 @@ class amiga_state : public driver_device
void aga_palette_write(int color_reg, uint16_t data);
void aga_fetch_sprite_data(int scanline, int sprite);
void aga_render_scanline(bitmap_rgb32 &bitmap, int scanline);
void aga_update_sprite_dma(int scanline);
void aga_update_sprite_dma(int scanline, int num);
int aga_get_sprite_pixel(int x);
uint8_t aga_assemble_odd_bitplanes(int planes, int obitoffs);
uint8_t aga_assemble_even_bitplanes(int planes, int ebitoffs);
Expand Down
116 changes: 65 additions & 51 deletions src/mame/amiga/amiga_v.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,63 +190,62 @@ void amiga_state::fetch_sprite_data(int scanline, int sprite)
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d fetch: data=%04X-%04X\n", scanline, sprite, CUSTOM_REG(REG_SPR0DATA + 4 * sprite), CUSTOM_REG(REG_SPR0DATB + 4 * sprite));
}

void amiga_state::update_sprite_dma(int scanline)
void amiga_state::update_sprite_dma(int scanline, int num)
{
int dmaenable = (CUSTOM_REG(REG_DMACON) & (DMACON_SPREN | DMACON_DMAEN)) == (DMACON_SPREN | DMACON_DMAEN);
int num, maxdma;
int maxdma;

/* channels are limited by DDFSTART */
maxdma = (CUSTOM_REG(REG_DDFSTRT) - 0x14) / 4;
if (maxdma > 8)
maxdma = 8;

/* loop over sprite channels */
for (num = 0; num < maxdma; num++)
{
int bitmask = 1 << num;
int vstart, vstop;
if (num >= maxdma)
return;

/* if we are == VSTOP, fetch new control words */
if (dmaenable && (m_sprite_dma_live_mask & bitmask) && (m_sprite_dma_reload_mask & bitmask))
{
/* disable the sprite */
m_sprite_comparitor_enable_mask &= ~bitmask;
m_sprite_dma_reload_mask &= ~bitmask;

/* fetch data into the control words */
CUSTOM_REG(REG_SPR0POS + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0);
CUSTOM_REG(REG_SPR0CTL + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d fetch: pos=%04X ctl=%04X\n", scanline, num, CUSTOM_REG(REG_SPR0POS + 4 * num), CUSTOM_REG(REG_SPR0CTL + 4 * num));
}
int bitmask = 1 << num;
int vstart, vstop;

/* compute vstart/vstop */
vstart = (CUSTOM_REG(REG_SPR0POS + 4 * num) >> 8) | ((CUSTOM_REG(REG_SPR0CTL + 4 * num) << 6) & 0x100);
vstop = (CUSTOM_REG(REG_SPR0CTL + 4 * num) >> 8) | ((CUSTOM_REG(REG_SPR0CTL + 4 * num) << 7) & 0x100);
/* if we are == VSTOP, fetch new control words */
if (dmaenable && (m_sprite_dma_live_mask & bitmask) && (m_sprite_dma_reload_mask & bitmask))
{
/* disable the sprite */
m_sprite_comparitor_enable_mask &= ~bitmask;
m_sprite_dma_reload_mask &= ~bitmask;

/* fetch data into the control words */
CUSTOM_REG(REG_SPR0POS + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0);
CUSTOM_REG(REG_SPR0CTL + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d fetch: pos=%04X ctl=%04X\n", scanline, num, CUSTOM_REG(REG_SPR0POS + 4 * num), CUSTOM_REG(REG_SPR0CTL + 4 * num));
}

/* if we hit vstart, enable the comparitor */
if (scanline == vstart)
{
m_sprite_comparitor_enable_mask |= 1 << num;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d comparitor enable\n", scanline, num);
}
/* compute vstart/vstop */
vstart = (CUSTOM_REG(REG_SPR0POS + 4 * num) >> 8) | ((CUSTOM_REG(REG_SPR0CTL + 4 * num) << 6) & 0x100);
vstop = (CUSTOM_REG(REG_SPR0CTL + 4 * num) >> 8) | ((CUSTOM_REG(REG_SPR0CTL + 4 * num) << 7) & 0x100);

/* if we hit vstop, disable the comparitor and trigger a reload for the next scanline */
if (scanline == vstop)
{
m_sprite_ctl_written &= ~bitmask;
m_sprite_comparitor_enable_mask &= ~bitmask;
m_sprite_dma_reload_mask |= 1 << num;
CUSTOM_REG(REG_SPR0DATA + 4 * num) = 0; /* just a guess */
CUSTOM_REG(REG_SPR0DATB + 4 * num) = 0;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num);
}
/* if we hit vstart, enable the comparitor */
if (scanline == vstart)
{
m_sprite_comparitor_enable_mask |= 1 << num;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d comparitor enable\n", scanline, num);
}

/* fetch data if this sprite is enabled */
if (dmaenable && (m_sprite_dma_live_mask & bitmask) && (m_sprite_comparitor_enable_mask & bitmask))
{
fetch_sprite_data(scanline, num);
}
/* if we hit vstop, disable the comparitor and trigger a reload for the next scanline */
if (scanline == vstop)
{
m_sprite_ctl_written &= ~bitmask;
m_sprite_comparitor_enable_mask &= ~bitmask;
m_sprite_dma_reload_mask |= 1 << num;
CUSTOM_REG(REG_SPR0DATA + 4 * num) = 0; /* just a guess */
CUSTOM_REG(REG_SPR0DATB + 4 * num) = 0;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num);
}

/* fetch data if this sprite is enabled */
if (dmaenable && (m_sprite_dma_live_mask & bitmask) && (m_sprite_comparitor_enable_mask & bitmask))
{
fetch_sprite_data(scanline, num);
}
}

Expand Down Expand Up @@ -471,6 +470,7 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
int hires = 0, dualpf = 0, ham = 0;
int pf1pri = 0, pf2pri = 0;
int planes = 0;
int raw_scanline = 0;

uint32_t *dst = nullptr;
int ebitoffs = 0, obitoffs = 0;
Expand Down Expand Up @@ -522,11 +522,7 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
}
}

/* update sprite data fetching */
// ensure this happens once every two scanlines for the RAM manipulation, kickoff cares
// this is also unaffected by LACE
if ((scanline & 1) == 0)
update_sprite_dma(scanline >> 1);
raw_scanline = scanline;

scanline /= 2;

Expand All @@ -549,8 +545,8 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
// - no separation of video and logic models;
// - the offsets we are applying to DDFSTRT and DDFSTOP, they mustn't be right (copper timings?);
// - ditto for DIW related values, they are offset in far too many places;
// - Twintris intro expects +11 on fast scrolling section (glitches at sides)
for (int x = 0; x < (amiga_state::SCREEN_WIDTH / 2) + 10; x++)
// - Twintris intro/suprfrog expects +11 on fast scrolling section (glitches at sides)
for (int x = 0; x < (amiga_state::SCREEN_WIDTH / 2) + 11; x++)
{
int sprpix;
const bool out_of_beam = x >= amiga_state::SCREEN_WIDTH / 2;
Expand Down Expand Up @@ -606,6 +602,24 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
ecolmask = (CUSTOM_REG(REG_CLXCON) >> 6) & 0x2a;
}

/* update sprite data fetching */
// ensure this happens once every two scanlines for the RAM manipulation, kickoff cares
// this is also unaffected by LACE
if ((raw_scanline & 1) == 0)
{
// TODO: refine
// Sprite DMA loads first two words at $14 + num * 4, other 2 words at $18 + num * 4
// NOTE: position $28 for sprite 4 has a typo on HRM diagram
// non-zero DMA fetches are required by:
// - beast gameplay, suprfrog player sprite, abreed (top left counter)
if (x >= 0x18 && x <= 0x34 && (x & 3) == 0)
{
int num = (x - 0x18) >> 2;
//printf("%d %02x\n", num, x);
update_sprite_dma(raw_scanline >> 1, num);
}
}

/* clear the target pixels to the background color as a starting point */
if (dst != nullptr && !out_of_beam)
{
Expand Down
127 changes: 68 additions & 59 deletions src/mame/amiga/amigaaga.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,10 @@ void amiga_state::aga_fetch_sprite_data(int scanline, int sprite)
m_aga_sprite_dma_used_words[sprite] = 0;
}

void amiga_state::aga_update_sprite_dma(int scanline)
void amiga_state::aga_update_sprite_dma(int scanline, int num)
{
int dmaenable = (CUSTOM_REG(REG_DMACON) & (DMACON_SPREN | DMACON_DMAEN)) == (DMACON_SPREN | DMACON_DMAEN);
int num, maxdma;
int maxdma;
const u16 sprctl_offs[4] = {2, 4, 4, 8};
const u16 spr_fmode_inc = sprctl_offs[(CUSTOM_REG(REG_FMODE) >> 2) & 0x03];

Expand All @@ -165,63 +165,62 @@ void amiga_state::aga_update_sprite_dma(int scanline)
if (maxdma > 8)
maxdma = 8;

/* loop over sprite channels */
for (num = 0; num < maxdma; num++)
{
int bitmask = 1 << num;
int vstart, vstop;
if (num >= maxdma)
return;

/* if we are == VSTOP, fetch new control words */
if (dmaenable && (m_sprite_dma_live_mask & bitmask) && (m_sprite_dma_reload_mask & bitmask) && !(m_sprite_ctl_written & bitmask))
{
/* disable the sprite */
m_sprite_comparitor_enable_mask &= ~bitmask;
m_sprite_dma_reload_mask &= ~bitmask;

/* fetch data into the control words */
CUSTOM_REG(REG_SPR0POS + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0);
// diggers AGA suggests that the fmode increments with ctl are interleaved,
// otherwise no sprites are drawn.
// (it enables sprite 0 only, and +8 for the vstop values)
CUSTOM_REG(REG_SPR0CTL + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + spr_fmode_inc);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 2 * spr_fmode_inc;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d fetch: pos=%04X ctl=%04X\n", scanline, num, CUSTOM_REG(REG_SPR0POS + 4 * num), CUSTOM_REG(REG_SPR0CTL + 4 * num));
}
int bitmask = 1 << num;
int vstart, vstop;

u16 spr0ctl = CUSTOM_REG(REG_SPR0CTL + 4 * num);
/* compute vstart/vstop */
// bits 6 and 5 are respectively vstart bit 9 and vstop bit 9
// TODO: do they disable with non-AGA modes?
vstart = (CUSTOM_REG(REG_SPR0POS + 4 * num) >> 8);
vstart |= (spr0ctl & 0x04) ? 0x100 : 0;
vstart |= (spr0ctl & 0x40) ? 0x200 : 0;
vstop = (spr0ctl >> 8);
vstop |= (spr0ctl & 0x02) ? 0x100 : 0;
vstop |= (spr0ctl & 0x20) ? 0x200 : 0;

/* if we hit vstart, enable the comparitor */
if (scanline == vstart)
{
m_sprite_comparitor_enable_mask |= 1 << num;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d comparitor enable\n", scanline, num);
}
/* if we are == VSTOP, fetch new control words */
if (dmaenable && (m_sprite_dma_live_mask & bitmask) && (m_sprite_dma_reload_mask & bitmask) && !(m_sprite_ctl_written & bitmask))
{
/* disable the sprite */
m_sprite_comparitor_enable_mask &= ~bitmask;
m_sprite_dma_reload_mask &= ~bitmask;

/* fetch data into the control words */
CUSTOM_REG(REG_SPR0POS + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0);
// diggers AGA suggests that the fmode increments with ctl are interleaved,
// otherwise no sprites are drawn.
// (it enables sprite 0 only, and +8 for the vstop values)
CUSTOM_REG(REG_SPR0CTL + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + spr_fmode_inc);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 2 * spr_fmode_inc;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d fetch: pos=%04X ctl=%04X\n", scanline, num, CUSTOM_REG(REG_SPR0POS + 4 * num), CUSTOM_REG(REG_SPR0CTL + 4 * num));
}

/* if we hit vstop, disable the comparitor and trigger a reload for the next scanline */
if (scanline == vstop)
{
m_sprite_ctl_written &= ~bitmask;
m_sprite_comparitor_enable_mask &= ~bitmask;
m_sprite_dma_reload_mask |= 1 << num;
CUSTOM_REG(REG_SPR0DATA + 4 * num) = 0; /* just a guess */
CUSTOM_REG(REG_SPR0DATB + 4 * num) = 0;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num);
}
u16 spr0ctl = CUSTOM_REG(REG_SPR0CTL + 4 * num);
/* compute vstart/vstop */
// bits 6 and 5 are respectively vstart bit 9 and vstop bit 9
// TODO: do they disable with non-AGA modes?
vstart = (CUSTOM_REG(REG_SPR0POS + 4 * num) >> 8);
vstart |= (spr0ctl & 0x04) ? 0x100 : 0;
vstart |= (spr0ctl & 0x40) ? 0x200 : 0;
vstop = (spr0ctl >> 8);
vstop |= (spr0ctl & 0x02) ? 0x100 : 0;
vstop |= (spr0ctl & 0x20) ? 0x200 : 0;

/* if we hit vstart, enable the comparitor */
if (scanline == vstart)
{
m_sprite_comparitor_enable_mask |= 1 << num;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d comparitor enable\n", scanline, num);
}

/* fetch data if this sprite is enabled */
if (dmaenable && (m_sprite_dma_live_mask & bitmask) && (m_sprite_comparitor_enable_mask & bitmask))
{
aga_fetch_sprite_data(scanline, num);
}
/* if we hit vstop, disable the comparitor and trigger a reload for the next scanline */
if (scanline == vstop)
{
m_sprite_ctl_written &= ~bitmask;
m_sprite_comparitor_enable_mask &= ~bitmask;
m_sprite_dma_reload_mask |= 1 << num;
CUSTOM_REG(REG_SPR0DATA + 4 * num) = 0; /* just a guess */
CUSTOM_REG(REG_SPR0DATB + 4 * num) = 0;
LOGMASKED(LOG_SPRITE_DMA, "%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num);
}

/* fetch data if this sprite is enabled */
if (dmaenable && (m_sprite_dma_live_mask & bitmask) && (m_sprite_comparitor_enable_mask & bitmask))
{
aga_fetch_sprite_data(scanline, num);
}
}

Expand Down Expand Up @@ -462,6 +461,7 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
int hires = 0, dualpf = 0, ham = 0, ehb = 0;
int pf1pri = 0, pf2pri = 0;
int planes = 0;
int raw_scanline = 0;

uint32_t *dst = nullptr;
int ebitoffs = 0, obitoffs = 0;
Expand Down Expand Up @@ -513,14 +513,12 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
}
}

raw_scanline = scanline;

scanline /= 2;

m_last_scanline = scanline;

/* update sprite data fetching */
// FIXME: verify and apply same logic as per OCS
aga_update_sprite_dma(scanline);

/* all sprites off at the start of the line */
memset(m_sprite_remain, 0, sizeof(m_sprite_remain));

Expand Down Expand Up @@ -623,6 +621,17 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
ecolmask = (CUSTOM_REG(REG_CLXCON) >> 6) & 0x2a;
}

if ((raw_scanline & 1) == 0)
{
// TODO: refine, merge with OCS version
if (x >= 0x18 && x <= 0x34 && (x & 3) == 0)
{
int num = (x - 0x18) >> 2;
//printf("%d %02x\n", num, x);
aga_update_sprite_dma(raw_scanline >> 1, num);
}
}

/* clear the target pixels to the background color as a starting point */
if (dst != nullptr && !out_of_beam)
dst[x*2+0] =
Expand Down
2 changes: 0 additions & 2 deletions src/mame/amiga/amigaaga.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@

#pragma once

void amiga_aga_palette_write(running_machine &machine, int color_reg, uint16_t data);

#endif // MAME_AMIGA_AMIGAAGA_H

0 comments on commit a672b82

Please sign in to comment.