diff options
author | David Haywood <mamehaze@gmail.com> | 2018-12-04 18:16:18 +0000 |
---|---|---|
committer | ajrhacker <ajrhacker@users.noreply.github.com> | 2018-12-04 13:16:18 -0500 |
commit | 2210be04f216e9c188a7beac5f32e5a9e89964b3 (patch) | |
tree | fcc3c3f6287102f356c0d8cd74ebfe246490c1ac | |
parent | 42c0ce03435574420bae5891ebb9b8a1fe7ab939 (diff) |
seta2: improve screen size / visible area / offset handling, preliminary raster effects (#4369)
* seta2: document raster effect findings so far, it's about as illogical as the rest (nw)
* improvements, some stuff still broken by yofset change tho (nw)
* fixup problem in previous (nw)
* preliminary raster type stuff (nw)
* refactor and fix silly mistake (nw)
* not really happy with this, but not much evidence to go on at the moment (nw)
-rw-r--r-- | src/mame/drivers/seta2.cpp | 45 | ||||
-rw-r--r-- | src/mame/includes/seta2.h | 16 | ||||
-rw-r--r-- | src/mame/video/seta2.cpp | 397 |
3 files changed, 290 insertions, 168 deletions
diff --git a/src/mame/drivers/seta2.cpp b/src/mame/drivers/seta2.cpp index cf1194459fe..56326c2bf64 100644 --- a/src/mame/drivers/seta2.cpp +++ b/src/mame/drivers/seta2.cpp @@ -82,7 +82,7 @@ grdians: has the shadow bit set, and has become invisible after implementing it. penbros/ablast: -- Zooming is used briefly. +- Zooming is used briefly (between scenes, stage exit, stage introduction) deerhunt,wschamp: - offset tilemap sprite during demo. In deerhunt intro, the hunter should zoom @@ -94,18 +94,12 @@ wschampb: original release? Is that why the next bug fix release is v1.01? IE: such a a minor increase in the version number. -trophyh: -- mame hangs for around 15 seconds every now and then, at scene changes. - This is probably due to a couple of frames with an odd or corrupt sprites list, - taking a long time to render. - funcube series: - Hacked to run, as they use a ColdFire CPU. - Pay-out key causes "unknown error" after coin count reaches 0. reelquak: - Needs an x offset for tilemap sprites. -- There are one frame glitches in the reels scroll. ***************************************************************************/ @@ -200,7 +194,7 @@ void seta2_state::grdians_map(address_map &map) map(0x70000c, 0x70000d).r("watchdog", FUNC(watchdog_timer_device::reset16_r)); map(0x800000, 0x800001).w(FUNC(seta2_state::grdians_lockout_w)); map(0xb00000, 0xb03fff).rw("x1snd", FUNC(x1_010_device::word_r), FUNC(x1_010_device::word_w)); // Sound - map(0xc00000, 0xc3ffff).ram().share("spriteram"); // Sprites + map(0xc00000, 0xc3ffff).ram().w(FUNC(seta2_state::spriteram_w)).share("spriteram"); // Sprites map(0xc40000, 0xc4ffff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); // Palette map(0xc50000, 0xc5ffff).ram(); // cleared map(0xc60000, 0xc6003f).w(FUNC(seta2_state::vregs_w)).share("vregs"); // Video Registers @@ -2394,12 +2388,13 @@ MACHINE_CONFIG_START(seta2_state::seta2) // video hardware MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(60) - MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) - MCFG_SCREEN_SIZE(0x200, 0x200) - MCFG_SCREEN_VISIBLE_AREA(0x40, 0x1c0-1, 0x80, 0x170-1) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) + MCFG_SCREEN_SIZE(0x200, 0x100) + MCFG_SCREEN_VISIBLE_AREA(0x40, 0x1c0-1, 0x00, 0xf0-1) MCFG_SCREEN_UPDATE_DRIVER(seta2_state, screen_update) MCFG_SCREEN_VBLANK_CALLBACK(WRITELINE(*this, seta2_state, screen_vblank)) MCFG_SCREEN_PALETTE("palette") + //MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_UPDATE_SCANLINE) MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_seta2) MCFG_PALETTE_ADD("palette", 0x8000+0xf0) // extra 0xf0 because we might draw 256-color object with 16-color granularity @@ -2426,7 +2421,7 @@ MACHINE_CONFIG_START(seta2_state::gundamex) // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0x00, 0x180-1, 0x100, 0x1e0-1) + MCFG_SCREEN_VISIBLE_AREA(0x00, 0x180-1, 0x000, 0x0e0-1) MACHINE_CONFIG_END @@ -2437,7 +2432,7 @@ MACHINE_CONFIG_START(seta2_state::grdians) // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0x80, 0x80 + 0x130 -1, 0x80, 0x80 + 0xe8 -1) + MCFG_SCREEN_VISIBLE_AREA(0x80, 0x80 + 0x130 -1, 0x00, 0x00 + 0xe8 -1) MACHINE_CONFIG_END @@ -2448,7 +2443,7 @@ MACHINE_CONFIG_START(seta2_state::myangel) // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0, 0x178-1, 0x10, 0x100-1) + MCFG_SCREEN_VISIBLE_AREA(0, 0x178-1, 0x00, 0xf0-1) MACHINE_CONFIG_END @@ -2459,7 +2454,7 @@ MACHINE_CONFIG_START(seta2_state::myangel2) // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0, 0x178-1, 0x10, 0x100-1) + MCFG_SCREEN_VISIBLE_AREA(0, 0x178-1, 0x00, 0xf0-1) MACHINE_CONFIG_END @@ -2470,7 +2465,7 @@ MACHINE_CONFIG_START(seta2_state::pzlbowl) // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0x10, 0x190-1, 0x100, 0x1f0-1) + MCFG_SCREEN_VISIBLE_AREA(0x10, 0x190-1, 0x00, 0xf0-1) MACHINE_CONFIG_END @@ -2481,7 +2476,7 @@ MACHINE_CONFIG_START(seta2_state::penbros) // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0, 0x140-1, 0x80, 0x160-1) + MCFG_SCREEN_VISIBLE_AREA(0, 0x140-1, 0x00, 0xe0-1) MACHINE_CONFIG_END MACHINE_CONFIG_START(seta2_state::ablastb) @@ -2505,7 +2500,7 @@ MACHINE_CONFIG_START(seta2_state::reelquak) // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0x40, 0x180-1, 0x80, 0x170-1) + MCFG_SCREEN_VISIBLE_AREA(0x40, 0x180-1, 0x00, 0xf0-1) MCFG_VIDEO_START_OVERRIDE(seta2_state,xoffset) MACHINE_CONFIG_END @@ -2523,7 +2518,7 @@ MACHINE_CONFIG_START(seta2_state::samshoot) // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0x40, 0x180-1, 0x40, 0x130-1) + MCFG_SCREEN_VISIBLE_AREA(0x40, 0x180-1, 0x00, 0xf0-1) MACHINE_CONFIG_END @@ -2538,7 +2533,7 @@ MACHINE_CONFIG_START(staraudi_state::staraudi) // video hardware MCFG_SCREEN_MODIFY("screen") MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // not accurate - MCFG_SCREEN_VISIBLE_AREA(0x10, 0x150-1, 0x100, 0x1f0-1) + MCFG_SCREEN_VISIBLE_AREA(0x10, 0x150-1, 0x00, 0x0f0-1) MCFG_GFXDECODE_MODIFY("gfxdecode", gfx_seta2) MACHINE_CONFIG_END @@ -2558,7 +2553,7 @@ MACHINE_CONFIG_START(seta2_state::telpacfl) // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0x0, 0x180-1, 0xff, 0x1ef-1) + MCFG_SCREEN_VISIBLE_AREA(0x0, 0x180-1, 0x00, 0xf0-1) MCFG_VIDEO_START_OVERRIDE(seta2_state,xoffset1) MACHINE_CONFIG_END @@ -2614,7 +2609,7 @@ MACHINE_CONFIG_START(funcube_state::funcube) MCFG_SCREEN_REFRESH_RATE(60) MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // not accurate MCFG_SCREEN_SIZE(0x200, 0x200) - MCFG_SCREEN_VISIBLE_AREA(0x0+1, 0x140-1+1, 0x80, 0x170-1) + MCFG_SCREEN_VISIBLE_AREA(0x0+1, 0x140-1+1, 0x00, 0xf0-1) MCFG_SCREEN_UPDATE_DRIVER(seta2_state, screen_update) MCFG_SCREEN_VBLANK_CALLBACK(WRITELINE(*this, seta2_state, screen_vblank)) MCFG_SCREEN_PALETTE("palette") @@ -2643,7 +2638,7 @@ MACHINE_CONFIG_START(funcube_state::funcube2) // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0x0, 0x140-1, 0x80, 0x170-1) + MCFG_SCREEN_VISIBLE_AREA(0x0, 0x140-1, 0x00, 0xf0-1) MACHINE_CONFIG_END @@ -2651,7 +2646,7 @@ MACHINE_CONFIG_START(funcube_state::funcube3) funcube2(config); // video hardware MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_VISIBLE_AREA(0x0, 0x140-1, 0x80-0x40, 0x170-1-0x40) + MCFG_SCREEN_VISIBLE_AREA(0x0, 0x140-1, 0x00, 0xf0-1) MACHINE_CONFIG_END @@ -2669,7 +2664,7 @@ MACHINE_CONFIG_START(seta2_state::namcostr) MCFG_SCREEN_REFRESH_RATE(60) MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) MCFG_SCREEN_SIZE(0x200, 0x200) - MCFG_SCREEN_VISIBLE_AREA(0x40, 0x1c0-1, 0x80, 0x170-1) + MCFG_SCREEN_VISIBLE_AREA(0x40, 0x1c0-1, 0x00, 0xf0-1) MCFG_SCREEN_UPDATE_DRIVER(seta2_state, screen_update) MCFG_SCREEN_VBLANK_CALLBACK(WRITELINE(*this, seta2_state, screen_vblank)) MCFG_SCREEN_PALETTE("palette") diff --git a/src/mame/includes/seta2.h b/src/mame/includes/seta2.h index c90ee1c4b0c..82a69b5f274 100644 --- a/src/mame/includes/seta2.h +++ b/src/mame/includes/seta2.h @@ -22,8 +22,8 @@ class seta2_state : public driver_device public: seta2_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), - m_maincpu(*this,"maincpu"), - m_sub(*this,"sub"), + m_maincpu(*this, "maincpu"), + m_sub(*this, "sub"), m_gfxdecode(*this, "gfxdecode"), m_screen(*this, "screen"), m_palette(*this, "palette"), @@ -34,7 +34,7 @@ public: m_flash(*this, "flash"), m_dispenser(*this, "dispenser"), - m_x1_bank(*this,"x1_bank_%u", 1U), + m_x1_bank(*this, "x1_bank_%u", 1U), m_nvram(*this, "nvram"), m_spriteram(*this, "spriteram", 0), m_tileram(*this, "tileram", 0), @@ -93,10 +93,12 @@ protected: DECLARE_READ16_MEMBER(gundamex_eeprom_r); DECLARE_WRITE16_MEMBER(gundamex_eeprom_w); + DECLARE_WRITE16_MEMBER(spriteram_w); + DECLARE_VIDEO_START(xoffset); DECLARE_VIDEO_START(xoffset1); - void draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); INTERRUPT_GEN_MEMBER(seta2_interrupt); INTERRUPT_GEN_MEMBER(samshoot_interrupt); @@ -130,7 +132,7 @@ protected: optional_device<eeprom_serial_93cxx_device> m_eeprom; optional_device<intelfsh16_device> m_flash; optional_device<ticket_dispenser_device> m_dispenser; - + optional_memory_bank_array<8> m_x1_bank; optional_shared_ptr<uint16_t> m_nvram; optional_shared_ptr<uint16_t> m_spriteram; @@ -143,6 +145,9 @@ protected: int m_keyboard_row; std::unique_ptr<uint16_t[]> m_buffered_spriteram; + uint16_t m_private_spriteram[0x1000 / 2]; + + private: void drawgfx_line(bitmap_ind16 &bitmap, const rectangle &cliprect, int gfx, const uint8_t* const addr, const uint32_t realcolor, int flipx, int flipy, int base_sx, int shadow, int realline, int line, int opaque); inline void get_tile(uint16_t* spriteram, int is_16x16, int x, int y, int page, int& code, int& attr, int& flipx, int& flipy, int& color); @@ -154,7 +159,6 @@ private: uint16_t m_rasterenabled; TIMER_CALLBACK_MEMBER(raster_timer_done); emu_timer *m_raster_timer; - }; diff --git a/src/mame/video/seta2.cpp b/src/mame/video/seta2.cpp index 28e098a9226..be5f59e7009 100644 --- a/src/mame/video/seta2.cpp +++ b/src/mame/video/seta2.cpp @@ -17,7 +17,7 @@ Offset: Bits: Value: 0.w f--- ---- ---- ---- Last sprite - -e-- ---- ---- ---- ? + -e-- ---- ---- ---- ? (ignore global offsets, zooming etc. used on frame of map in grdians) --d- ---- ---- ---- Opaque ---c ---- ---- ---- 0 = Each sprite specifies its size, 1 = Use the global size (following words) ---- b--- ---- ---- Shadow @@ -99,7 +99,9 @@ 1c Zoom Y? low bits 1e Zoom Y? high bits * + 24 1->0 in funcube3 and staraudi 26 1->0 during INT0, before writing sprites + (probably creates a custom format sprite list at 0x0000 by processing the list at 0x3000) 30 fedc ba98 7654 321- ---- ---- ---- ---0 Disable video @@ -111,51 +113,131 @@ ***************************************************************************/ +/*************************************************************************** + + NON-BUGS + + grdians : After the fire rowscroll effect in the intro there is a small artifact + left scrolling at the top of the screen when the next image is displayed + See 4:24 in https://www.youtube.com/watch?v=cvHGFEsB_cM + +***************************************************************************/ + WRITE16_MEMBER(seta2_state::vregs_w) { /* 02/04 = horizontal display start/end - mj4simai = 0065/01E5 (0180 visible area) - myangel = 005D/01D5 (0178 visible area) - pzlbowl = 0058/01D8 (0180 visible area) - penbros = 0065/01A5 (0140 visible area) - grdians = 0059/0188 (012f visible area) + mj4simai = 0065/01E5 (0180 visible area) + myangel = 005D/01D5 (0178 visible area) + pzlbowl = 0058/01D8 (0180 visible area) + penbros = 0065/01A5 (0140 visible area) + grdians = 0059/0188 (012f visible area) 06 = horizontal total? - mj4simai = 0204 - myangel = 0200 - pzlbowl = 0204 - penbros = 01c0 - grdians = 019a + mj4simai = 0204 + myangel = 0200 + pzlbowl = 0204 + penbros = 01c0 + grdians = 019a */ uint16_t olddata = m_vregs[offset]; COMBINE_DATA(&m_vregs[offset]); - if ( m_vregs[offset] != olddata ) - logerror("CPU #0 PC %06X: Video Reg %02X <- %04X\n",m_maincpu->pc(),offset*2,data); + if (m_vregs[offset] != olddata) + logerror("CPU #0 PC %06X: Video Reg %02X <- %04X\n", m_maincpu->pc(), offset * 2, data); - switch( offset*2 ) + switch (offset * 2) { + case 0x1a: + logerror("%s: Register 1a write (vertical offset?) %04X (%04x)\n", machine().describe_context(), data, mem_mask); + break; + case 0x1c: // FLIP SCREEN (myangel) <- this is actually zoom - flip_screen_set(data & 1 ); - if (data & ~1) logerror("CPU #0 PC %06X: flip screen unknown bits %04X\n",m_maincpu->pc(),data); + flip_screen_set(data & 1); + if (data & ~1) logerror("CPU #0 PC %06X: flip screen unknown bits %04X\n", m_maincpu->pc(), data); break; case 0x2a: // FLIP X (pzlbowl) - flip_screen_x_set(data & 1 ); - if (data & ~1) logerror("CPU #0 PC %06X: flipx unknown bits %04X\n",m_maincpu->pc(),data); + flip_screen_x_set(data & 1); + if (data & ~1) logerror("CPU #0 PC %06X: flipx unknown bits %04X\n", m_maincpu->pc(), data); break; case 0x2c: // FLIP Y (pzlbowl) - flip_screen_y_set(data & 1 ); - if (data & ~1) logerror("CPU #0 PC %06X: flipy unknown bits %04X\n",m_maincpu->pc(),data); + flip_screen_y_set(data & 1); + if (data & ~1) logerror("CPU #0 PC %06X: flipy unknown bits %04X\n", m_maincpu->pc(), data); break; case 0x30: // BLANK SCREEN (pzlbowl, myangel) - if (data & ~1) logerror("CPU #0 PC %06X: blank unknown bits %04X\n",m_maincpu->pc(),data); + if (data & ~1) logerror("CPU #0 PC %06X: blank unknown bits %04X\n", m_maincpu->pc(), data); + break; + + case 0x24: // funcube3 and staraudi write here instead, why? mirror or different meaning? + case 0x26: // something display list related? buffering control? + if (data) + { + // Buffer sprites by 1 frame + //memcpy(m_buffered_spriteram.get(), m_spriteram, m_spriteram.bytes()); + + /* copy the base spritelist to a private (non-CPU visible buffer) + copy the indexed sprites to 0 in spriteram, adjusting pointers in base sprite list as appropriate + this at least gets the sprite data in the right place for the grdians raster effect to write the + changed scroll values to the correct sprites, but is still nothing more than a guess + */ + int current_sprite_entry = 0; + + for (int i = 0; i < 0x1000 / 2; i += 4) + { + uint16_t num = m_private_spriteram[i + 0] = m_spriteram[(0x3000 / 2) + i + 0]; + m_private_spriteram[i + 1] = m_spriteram[(0x3000 / 2) + i + 1]; + m_private_spriteram[i + 2] = m_spriteram[(0x3000 / 2) + i + 2]; + + int sprite = m_spriteram[(0x3000 / 2) + i + 3]; + m_private_spriteram[i + 3] = ((current_sprite_entry / 4) & 0x7fff) | (sprite & 0x8000); + + int list2addr = (sprite & 0x7fff) * 4; + + num &=0xff; + + for (int j = 0; j <= num; j++) + { + if (current_sprite_entry < 0x3000 / 2) + { + m_spriteram[current_sprite_entry + 0] = m_spriteram[(list2addr + (j * 4) + 0) & 0x1ffff]; + m_spriteram[current_sprite_entry + 1] = m_spriteram[(list2addr + (j * 4) + 1) & 0x1ffff]; + m_spriteram[current_sprite_entry + 2] = m_spriteram[(list2addr + (j * 4) + 2) & 0x1ffff]; + m_spriteram[current_sprite_entry + 3] = m_spriteram[(list2addr + (j * 4) + 3) & 0x1ffff]; + current_sprite_entry += 4; + } + } + + if (m_private_spriteram[i + 0] & 0x8000) // end of list marker, mj4simai must draw the sprite this covers for the company logo, title screen etc. + { + // HACK: however penbros has a dummy sprite entry there which points to 0x0000 as the tile source, and causes garbage with the rearranged format, + // so change it to something that's invalid where we can filter it later. This strongly indicates that the current approach is incorrect however. + if (sprite == 0x00) + { + m_private_spriteram[i + 3] |= 0x4000; + } + + break; + } + } + + } break; case 0x3c: // Raster IRQ related - //logerror("%s: Register 3c write (raster enable?) %04X (%04x)\n",machine().describe_context(),data, mem_mask); + //logerror("%s: Register 3c write (raster enable?) current vpos is %d : %04X (%04x)\n",machine().describe_context(),m_screen->vpos(), data, mem_mask); COMBINE_DATA(&m_rasterenabled); - if (m_rasterenabled & 1) m_raster_timer->adjust(m_screen->time_until_pos((m_rasterposition&0x1ff)+0x80, 0), 0); + + //if (m_rasterenabled & 1) + { + int hpos = 0; + int vpos = m_rasterposition; + + // in the vblank it specifies line 0, the first raster interrupt then specifies line 0 again before the subsequent ones use the real line numbers? + // It seems more likely the the raster IRQ stays asserted for the entire line, thus triggering a second interrupt unless the line number is changed? + if (m_rasterposition == m_screen->vpos()) hpos = m_screen->hpos() + 0x100; + //logerror("setting raster to %d %d\n", vpos, hpos); + m_raster_timer->adjust(m_screen->time_until_pos(vpos, hpos), 0); + } break; case 0x3e: // Raster IRQ related @@ -165,6 +247,11 @@ WRITE16_MEMBER(seta2_state::vregs_w) } } +WRITE16_MEMBER(seta2_state::spriteram_w) +{ + COMBINE_DATA(&m_spriteram[offset]); +} + /*************************************************************************** @@ -249,23 +336,28 @@ inline void seta2_state::get_tile(uint16_t* spriteram, int is_16x16, int x, int void seta2_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) { // Sprites list + uint16_t *spriteram = m_spriteram; + int global_yoffset = (m_vregs[0x1a/2] & 0x7ff); + if (global_yoffset & 0x400) + global_yoffset -= 0x800; + + global_yoffset += 1; + + uint16_t *s1 = m_private_spriteram; - // When debugging, use m_spriteram here, and run mame -update_in_pause, i.e.: -// uint16_t *buffered_spriteram16 = m_spriteram; - uint16_t *buffered_spriteram16 = m_buffered_spriteram.get(); - uint16_t *s1 = buffered_spriteram16 + 0x3000 / 2; - uint16_t *end = &buffered_spriteram16[m_spriteram.bytes() / 2]; // for ( ; s1 < end; s1+=4 ) - for (; s1 < buffered_spriteram16 + 0x4000 / 2; s1 += 4) // more reasonable (and it cures MAME lockup in e.g. funcube3 boot) + for (; s1 < m_private_spriteram + 0x1000 / 2; s1 += 4) // more reasonable (and it cures MAME lockup in e.g. funcube3 boot) { int num = s1[0]; + int xoffs = s1[1]; int yoffs = s1[2]; int sprite = s1[3]; // Single-sprite address - uint16_t *s2 = &buffered_spriteram16[(sprite & 0x7fff) * 4]; + uint16_t *s2 = &spriteram[(sprite & 0x7fff) * 4]; + uint16_t *end = &spriteram[m_spriteram.bytes() / 2]; // Single-sprite size int global_sizex = xoffs & 0xfc00; @@ -281,136 +373,155 @@ void seta2_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) // Number of single-sprites num = (num & 0x00ff) + 1; - for (; num > 0; num--, s2 += 4) + // all sprites, except invalid ones should have a pointer <0x3000 in the reformatted list + if ((sprite&0x7fff) < 0x3000 / 2 / 4) { - if (s2 >= end) break; - - if (sprite & 0x8000) + for (; num > 0; num--, s2 += 4) { - // "floating tilemap" sprite - // the 'floating tilemap sprites' are just a window into the tilemap, the position of the sprite does not change the scroll values - - int sx = s2[0]; - int sy = s2[1]; - int scrollx = s2[2]; - int scrolly = s2[3]; - int is_16x16 = (scrollx & 0x8000) >> 15; - int page = (scrollx & 0x7c00) >> 10; - int local_sizex = sx & 0xfc00; - int local_sizey = sy & 0xfc00; - sx &= 0x3ff; - sy &= 0x1ff; - - int width = use_global_size ? global_sizex : local_sizex; - int height = use_global_size ? global_sizey : local_sizey; - - height = ((height & 0xfc00) >> 10) + 1; - width = ((width & 0xfc00) >> 10)/* + 1*/; // reelquak reels - if (!width) - continue; - - scrollx += m_xoffset; - scrollx &= 0x3ff; - scrolly &= 0x1ff; - - rectangle clip; - // sprite clipping region (x) - clip.min_x = (sx + xoffs) & 0x3ff; - clip.min_x = (clip.min_x & 0x1ff) - (clip.min_x & 0x200); - clip.max_x = clip.min_x + width * 0x10 - 1; - - if (clip.min_x > cliprect.max_x) continue; - if (clip.max_x < cliprect.min_x) continue; - if (clip.min_x < cliprect.min_x) clip.min_x = cliprect.min_x; - if (clip.max_x > cliprect.max_x) clip.max_x = cliprect.max_x; - - // sprite clipping region (y) - clip.min_y = ((sy + yoffs) & 0x1ff); - clip.max_y = clip.min_y + height * 0x10 - 1; - - if (clip.min_y > cliprect.max_y) continue; - if (clip.max_y < cliprect.min_y) continue; - if (clip.min_y < cliprect.min_y) clip.min_y = cliprect.min_y; - if (clip.max_y > cliprect.max_y) clip.max_y = cliprect.max_y; - - for (int realline = clip.min_y; realline <= clip.max_y; realline++) - { - int sourceline = (realline - scrolly) & 0x1ff; - - int y = sourceline >> (is_16x16 ? 4 : 3); + if (s2 >= end) break; - for (int x = 0; x < 0x40; x++) + if (sprite & 0x8000) + { + // "floating tilemap" sprite + // the 'floating tilemap sprites' are just a window into the tilemap, the position of the sprite does not change the scroll values + + int sx = s2[0]; + int sy = s2[1]; + int scrollx = s2[2]; + int scrolly = s2[3]; + int is_16x16 = (scrollx & 0x8000) >> 15; + int page = (scrollx & 0x7c00) >> 10; + int local_sizex = sx & 0xfc00; + int local_sizey = sy & 0xfc00; + sx &= 0x3ff; + sy += global_yoffset; + sy &= 0x1ff; + + if (sy & 0x100) + sy -= 0x200; + + int width = use_global_size ? global_sizex : local_sizex; + int height = use_global_size ? global_sizey : local_sizey; + + height = ((height & 0xfc00) >> 10) + 1; + width = ((width & 0xfc00) >> 10)/* + 1*/; // reelquak reels + if (!width) + continue; + + scrollx += m_xoffset; + scrollx &= 0x3ff; + scrolly &= 0x1ff; + + scrolly += global_yoffset; + + rectangle clip; + // sprite clipping region (x) + clip.min_x = (sx + xoffs) & 0x3ff; + clip.min_x = (clip.min_x & 0x1ff) - (clip.min_x & 0x200); + clip.max_x = clip.min_x + width * 0x10 - 1; + + if (clip.min_x > cliprect.max_x) continue; + if (clip.max_x < cliprect.min_x) continue; + if (clip.min_x < cliprect.min_x) clip.min_x = cliprect.min_x; + if (clip.max_x > cliprect.max_x) clip.max_x = cliprect.max_x; + + // sprite clipping region (y) + + int basey = (sy + yoffs) & 0x1ff; + if (basey & 0x100) basey -= 0x200; + + clip.min_y = basey; + clip.max_y = clip.min_y + height * 0x10 - 1; + + if (clip.min_y > cliprect.max_y) continue; + if (clip.max_y < cliprect.min_y) continue; + if (clip.min_y < cliprect.min_y) clip.min_y = cliprect.min_y; + if (clip.max_y > cliprect.max_y) clip.max_y = cliprect.max_y; + + for (int realline = clip.min_y; realline <= clip.max_y; realline++) { - int code, attr, flipx, flipy, color; - get_tile(buffered_spriteram16, is_16x16, x, y ^ 0x1f, page, code, attr, flipx, flipy, color); // yes the tilemap in RAM is flipped?! + int sourceline = (realline - scrolly) & 0x1ff; - int line = is_16x16 ? (sourceline & 0x0f) : (sourceline & 0x07); + int y = sourceline >> (is_16x16 ? 4 : 3); - int ty = (line >> 3) & 1; - line &= 0x7; - for (int tx = 0; tx <= is_16x16; tx++) + for (int x = 0; x < 0x40; x++) { - int dx = sx + (scrollx & 0x3ff) + xoffs + 0x10; - int px = ((dx + x * (8 << is_16x16) + 0x10) & 0x3ff) - 0x10; - int dst_x = (px + (flipx ? is_16x16 - tx : tx) * 8) & 0x3ff; - dst_x = (dst_x & 0x1ff) - (dst_x & 0x200); + int code, attr, flipx, flipy, color; + // tilemap data is NOT buffered? (and yes the tilemap in RAM is flipped?!) + get_tile(spriteram, is_16x16, x, y ^ 0x1f, page, code, attr, flipx, flipy, color); - if ((dst_x >= clip.min_x - 8) && (dst_x <= clip.max_x)) + int line = is_16x16 ? (sourceline & 0x0f) : (sourceline & 0x07); + + int ty = (line >> 3) & 1; + line &= 0x7; + for (int tx = 0; tx <= is_16x16; tx++) { - int realcode = code ^ tx ^ ((flipy ? is_16x16 - ty : ty) << 1); - drawgfx_line(bitmap, clip, which_gfx, m_spritegfx->get_data(m_realtilenumber[realcode]), color << 4, flipx, flipy, dst_x, use_shadow, realline, line, opaque); + int dx = sx + (scrollx & 0x3ff) + xoffs + 0x10; + int px = ((dx + x * (8 << is_16x16) + 0x10) & 0x3ff) - 0x10; + int dst_x = (px + (flipx ? is_16x16 - tx : tx) * 8) & 0x3ff; + dst_x = (dst_x & 0x1ff) - (dst_x & 0x200); + + if ((dst_x >= clip.min_x - 8) && (dst_x <= clip.max_x)) + { + int realcode = code ^ tx ^ ((flipy ? is_16x16 - ty : ty) << 1); + drawgfx_line(bitmap, clip, which_gfx, m_spritegfx->get_data(m_realtilenumber[realcode]), color << 4, flipx, flipy, dst_x, use_shadow, realline, line, opaque); + } } } } } - } - else - { - // "normal" sprite - int sx = s2[0]; - int sy = s2[1]; - int attr = s2[2]; - int code = s2[3] + ((attr & 0x0007) << 16); - int flipx = (attr & 0x0010); - int flipy = (attr & 0x0008); - int color = (attr & 0xffe0) >> 5; + else + { + // "normal" sprite + int sx = s2[0]; + int sy = s2[1]; + int attr = s2[2]; + int code = s2[3] + ((attr & 0x0007) << 16); + int flipx = (attr & 0x0010); + int flipy = (attr & 0x0008); + int color = (attr & 0xffe0) >> 5; - int sizex = use_global_size ? global_sizex : sx; - int sizey = use_global_size ? global_sizey : sy; - sizex = (1 << ((sizex & 0x0c00) >> 10)) - 1; - sizey = (1 << ((sizey & 0x0c00) >> 10)) - 1; + int sizex = use_global_size ? global_sizex : sx; + int sizey = use_global_size ? global_sizey : sy; + sizex = (1 << ((sizex & 0x0c00) >> 10)) - 1; + sizey = (1 << ((sizey & 0x0c00) >> 10)) - 1; - sx += xoffs; - sy += yoffs; + sx += xoffs; + sy += yoffs; - sx = (sx & 0x1ff) - (sx & 0x200); + sx = (sx & 0x1ff) - (sx & 0x200); - sy &= 0x1ff; + sy += global_yoffset; - int basecode = code &= ~((sizex + 1) * (sizey + 1) - 1); // see myangel, myangel2 and grdians + sy &= 0x1ff; - int firstline = sy; - int endline = (sy + (sizey + 1) * 8) - 1; + if (sy & 0x100) + sy -= 0x200; - int realfirstline = firstline; - if (firstline < cliprect.min_y) realfirstline = cliprect.min_y; - if (endline > cliprect.max_y) endline = cliprect.max_y; + int basecode = code &= ~((sizex + 1) * (sizey + 1) - 1); // see myangel, myangel2 and grdians - for (int realline = realfirstline; realline <= endline; realline++) - { - int line = realline - firstline; - int y = (line >> 3); - line &= 0x7; + int firstline = sy; + int endline = (sy + (sizey + 1) * 8) - 1; - for (int x = 0; x <= sizex; x++) + int realfirstline = firstline; + + if (firstline < cliprect.min_y) realfirstline = cliprect.min_y; + if (endline > cliprect.max_y) endline = cliprect.max_y; + + for (int realline = realfirstline; realline <= endline; realline++) { - int realcode = (basecode + (flipy ? sizey - y : y)*(sizex + 1)) + (flipx ? sizex - x : x); - drawgfx_line(bitmap, cliprect, which_gfx, m_spritegfx->get_data(m_realtilenumber[realcode]), color << 4, flipx, flipy, sx + x * 8, use_shadow, realline, line, opaque); + int line = realline - firstline; + int y = (line >> 3); + line &= 0x7; + + for (int x = 0; x <= sizex; x++) + { + int realcode = (basecode + (flipy ? sizey - y : y)*(sizex + 1)) + (flipx ? sizex - x : x); + drawgfx_line(bitmap, cliprect, which_gfx, m_spritegfx->get_data(m_realtilenumber[realcode]), color << 4, flipx, flipy, sx + x * 8, use_shadow, realline, line, opaque); + } } } - - } } if (s1[0] & 0x8000) break; // end of list marker @@ -420,9 +531,19 @@ void seta2_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) TIMER_CALLBACK_MEMBER(seta2_state::raster_timer_done) { - + if (m_tmp68301) + { + if (m_rasterenabled & 1) + { + m_tmp68301->external_interrupt_1(); + logerror("external int (vpos is %d)\n", m_screen->vpos()); + m_screen->update_partial(m_screen->vpos() - 1); + } + } } + + /*************************************************************************** @@ -449,6 +570,8 @@ void seta2_state::video_start() } m_raster_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(seta2_state::raster_timer_done), this)); + + save_item(NAME(m_private_spriteram)); } VIDEO_START_MEMBER(seta2_state,xoffset) @@ -488,8 +611,8 @@ WRITE_LINE_MEMBER(seta2_state::screen_vblank) // rising edge if (state) { - // Buffer sprites by 1 frame - memcpy(m_buffered_spriteram.get(), m_spriteram, m_spriteram.bytes()); + // Buffer sprites by 1 frame, moved to video register 0x26, improves grdians intro there + //memcpy(m_buffered_spriteram.get(), m_spriteram, m_spriteram.bytes()); } } |