mirror of
https://github.com/holub/mame
synced 2025-10-05 16:50:57 +03:00
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:
parent
42c0ce0343
commit
2210be04f2
@ -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")
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user