summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commit2210be04f216e9c188a7beac5f32e5a9e89964b3 (patch)
treefcc3c3f6287102f356c0d8cd74ebfe246490c1ac
parent42c0ce03435574420bae5891ebb9b8a1fe7ab939 (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.cpp45
-rw-r--r--src/mame/includes/seta2.h16
-rw-r--r--src/mame/video/seta2.cpp397
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());
}
}