From a672b823a8d48c179f525b740cc9522a552b82fb Mon Sep 17 00:00:00 2001 From: angelosa Date: Sun, 5 Jan 2025 19:03:15 +0100 Subject: amiga/amiga_v.cpp: move sprite DMA triggers to X defined slots --- src/mame/amiga/amiga.h | 4 +- src/mame/amiga/amiga_v.cpp | 116 ++++++++++++++++++++++------------------ src/mame/amiga/amigaaga.cpp | 127 ++++++++++++++++++++++++-------------------- src/mame/amiga/amigaaga.h | 2 - 4 files changed, 135 insertions(+), 114 deletions(-) diff --git a/src/mame/amiga/amiga.h b/src/mame/amiga/amiga.h index 0f6c6d1e307..5a0f2323bca 100644 --- a/src/mame/amiga/amiga.h +++ b/src/mame/amiga/amiga.h @@ -641,7 +641,7 @@ private: 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); @@ -655,7 +655,7 @@ private: 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); diff --git a/src/mame/amiga/amiga_v.cpp b/src/mame/amiga/amiga_v.cpp index d61c7746f6d..fd9f04b0597 100644 --- a/src/mame/amiga/amiga_v.cpp +++ b/src/mame/amiga/amiga_v.cpp @@ -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); } } @@ -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; @@ -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; @@ -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; @@ -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) { diff --git a/src/mame/amiga/amigaaga.cpp b/src/mame/amiga/amigaaga.cpp index d7697827121..a6956a7d51d 100644 --- a/src/mame/amiga/amigaaga.cpp +++ b/src/mame/amiga/amigaaga.cpp @@ -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]; @@ -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); } } @@ -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; @@ -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)); @@ -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] = diff --git a/src/mame/amiga/amigaaga.h b/src/mame/amiga/amigaaga.h index 3baeca8cf9b..0e864480ad3 100644 --- a/src/mame/amiga/amigaaga.h +++ b/src/mame/amiga/amigaaga.h @@ -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 -- cgit v1.2.3