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)
This commit is contained in:
David Haywood 2018-12-04 18:16:18 +00:00 committed by ajrhacker
parent 42c0ce0343
commit 2210be04f2
3 changed files with 295 additions and 173 deletions

View File

@ -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")

View File

@ -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);
@ -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;
};

View File

@ -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,6 +113,16 @@
***************************************************************************/
/***************************************************************************
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
@ -130,32 +142,102 @@ WRITE16_MEMBER(seta2_state::vregs_w)
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,6 +373,9 @@ void seta2_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
// Number of single-sprites
num = (num & 0x00ff) + 1;
// all sprites, except invalid ones should have a pointer <0x3000 in the reformatted list
if ((sprite&0x7fff) < 0x3000 / 2 / 4)
{
for (; num > 0; num--, s2 += 4)
{
if (s2 >= end) break;
@ -299,8 +394,12 @@ void seta2_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
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;
@ -313,6 +412,8 @@ void seta2_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
scrollx &= 0x3ff;
scrolly &= 0x1ff;
scrolly += global_yoffset;
rectangle clip;
// sprite clipping region (x)
clip.min_x = (sx + xoffs) & 0x3ff;
@ -325,7 +426,11 @@ void seta2_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
if (clip.max_x > cliprect.max_x) clip.max_x = cliprect.max_x;
// sprite clipping region (y)
clip.min_y = ((sy + yoffs) & 0x1ff);
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;
@ -342,7 +447,8 @@ void seta2_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
for (int x = 0; x < 0x40; x++)
{
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?!
// 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);
int line = is_16x16 ? (sourceline & 0x0f) : (sourceline & 0x07);
@ -385,8 +491,14 @@ void seta2_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
sx = (sx & 0x1ff) - (sx & 0x200);
sy += global_yoffset;
sy &= 0x1ff;
if (sy & 0x100)
sy -= 0x200;
int basecode = code &= ~((sizex + 1) * (sizey + 1) - 1); // see myangel, myangel2 and grdians
int firstline = sy;
@ -409,8 +521,7 @@ void seta2_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
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());
}
}