summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame
diff options
context:
space:
mode:
author David Haywood <mamehaze@users.noreply.github.com>2014-05-15 15:46:21 +0000
committer David Haywood <mamehaze@users.noreply.github.com>2014-05-15 15:46:21 +0000
commit1a9ed9ebe857c3df11176a7509ebd389df863d99 (patch)
tree237d2763c564a38205262c351d3c6ba81c651c4f /src/mame
parent36ad612f608726a3981bdc3d8f85db27a3304e26 (diff)
short whatsnew: fixed some gfx bugs in midas.c "livequiz"
long wn: started converting neogeo video / sprite system to a device_reset created base device + number of derived classes NEOGEO_SPRITE_REGULAR is an reference implementation, drawing direct from NEOGEO_SPRITE_OPTIMZIED is a version with predecoded gfx (as we use now) this is the default used by the driver NEOGEO_SPRITE_MIDAS is a version supporting the changes needed by the MIDAS games (mainly 8bpp instead of 4bpp)
Diffstat (limited to 'src/mame')
-rw-r--r--src/mame/drivers/midas.c269
-rw-r--r--src/mame/drivers/neogeo.c80
-rw-r--r--src/mame/includes/neogeo.h71
-rw-r--r--src/mame/mame.mak1
-rw-r--r--src/mame/video/neogeo.c654
-rw-r--r--src/mame/video/neogeo_spr.c838
-rw-r--r--src/mame/video/neogeo_spr.h143
7 files changed, 1179 insertions, 877 deletions
diff --git a/src/mame/drivers/midas.c b/src/mame/drivers/midas.c
index 9cb74910895..1654252de6b 100644
--- a/src/mame/drivers/midas.c
+++ b/src/mame/drivers/midas.c
@@ -7,7 +7,6 @@
a reengineered Neo-Geo, with a few differences: no Z80, better sound chip, serial eeprom and 256 color tiles.
Plus a PIC12C508A microcontroller, probably for the protection checks (I've patched them out for now).
- This driver should be merged with neogeo.c
Hardware description:
http://web.archive.org/web/20041018094226/http://www.andamiro.com/kor/business/hard_05.html
@@ -17,7 +16,7 @@
VRAM 256kbyte (4Display/Access bank)
PaletteRAM 96kbyte
-
+
Display 320(x)*224(y)
Sprite 16(x)*240(y(max))*380(max) (96 sprite/line(max))
@@ -55,22 +54,22 @@
#include "sound/ymz280b.h"
#include "machine/eepromser.h"
#include "machine/ticket.h"
-
+#include "includes/neogeo.h"
class midas_state : public driver_device
{
public:
midas_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
- m_gfxregs(*this, "gfxregs"),
m_maincpu(*this, "maincpu"),
m_eeprom(*this, "eeprom"),
m_gfxdecode(*this, "gfxdecode"),
- m_palette(*this, "palette") { }
+ m_palette(*this, "palette"),
+ m_sprgen(*this, "spritegen"),
+ m_screen(*this, "screen"),
+ m_zoomram(*this, "zoomtable")
+ { }
- UINT16 *m_gfxram;
- required_shared_ptr<UINT16> m_gfxregs;
- tilemap_t *m_tmap;
DECLARE_READ16_MEMBER(ret_ffff);
DECLARE_WRITE16_MEMBER(midas_gfxregs_w);
DECLARE_WRITE16_MEMBER(livequiz_coin_w);
@@ -79,139 +78,44 @@ public:
DECLARE_WRITE16_MEMBER(hammer_motor_w);
DECLARE_WRITE16_MEMBER(hammer_led_w);
DECLARE_WRITE16_MEMBER(midas_eeprom_w);
+ DECLARE_WRITE16_MEMBER(midas_zoomtable_w);
DECLARE_DRIVER_INIT(livequiz);
- TILE_GET_INFO_MEMBER(get_tile_info);
virtual void video_start();
- UINT32 screen_update_midas(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
- void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
+ virtual void machine_start();
+ virtual void machine_reset();
+
+
+ UINT32 screen_update_midas(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(livequiz_irqhandler);
required_device<cpu_device> m_maincpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
-};
+ required_device<neosprite_midas_device> m_sprgen;
+ required_device<screen_device> m_screen;
+ required_shared_ptr<UINT16> m_zoomram;
+ void screen_eof_midas(screen_device &screen, bool state);
+
+};
-TILE_GET_INFO_MEMBER(midas_state::get_tile_info)
-{
- UINT16 code = m_gfxram[ tile_index + 0x7000 ];
- SET_TILE_INFO_MEMBER(1, code & 0xfff, (code >> 12) & 0xf, TILE_FLIPXY( 0 ));
-}
void midas_state::video_start()
{
- m_gfxram = auto_alloc_array(machine(), UINT16, 0x20000/2);
-
- m_tmap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(midas_state::get_tile_info),this), TILEMAP_SCAN_COLS,8,8,0x80,0x20);
-
- m_tmap->set_transparent_pen(0);
}
-void midas_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
+UINT32 midas_state::screen_update_midas(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- UINT16 *s = m_gfxram + 0x8000;
- UINT16 *codes = m_gfxram;
-
- int sx_old = 0, sy_old = 0, ynum_old = 0, xzoom_old = 0;
- int xdim, ydim, xscale, yscale;
- int i,y;
-
- for (i = 0; i < 0x180; i++,s++,codes+=0x40)
- {
- int zoom = s[0x000];
- int sy = s[0x200];
- int sx = s[0x400];
-
- int xzoom = ((zoom >> 8) & 0x0f) + 1;
- int yzoom = ((zoom >> 0) & 0x7f) + 1;
+ // fill with background color first
+ bitmap.fill(0x0, cliprect);
- int ynum;
+ m_sprgen->draw_sprites(bitmap, cliprect.min_y);
- if (sy & 0x40)
- {
- ynum = ynum_old;
-
- sx = sx_old + xzoom_old;
- sy = sy_old;
-
- if (sx >= 0x1f0)
- sx -= 0x200;
- }
- else
- {
- ynum = sy & 0x3f;
-
- sx = (sx >> 7);
- sy = 0x200 - (sy >> 7);
-
- if (sx >= 0x1f0)
- sx -= 0x200;
-
- if (ynum > 0x20)
- ynum = 0x20;
- }
-
- ynum_old = ynum;
- sx_old = sx;
- sy_old = sy;
- xzoom_old = xzoom;
-
- // Use fixed point values (16.16), for accuracy
-
- sx <<= 16;
- sy <<= 16;
-
- xdim = ( xzoom << 16 ) * 16 / 16;
- ydim = ( yzoom << 16 ) * 16 / 0x80;
-
- xscale = xdim / 16;
- yscale = ydim / 16;
-
- // Let's approximate to the nearest greater integer value
- // to avoid holes in between tiles
-
- if (xscale & 0xffff) xscale += (1<<16) / 16;
- if (yscale & 0xffff) yscale += (1<<16) / 16;
-
- // Draw the tiles
-
- for (y = 0; y < ynum; y++)
- {
- UINT16 code = codes[y*2];
- UINT16 attr = codes[y*2+1];
-
- m_gfxdecode->gfx(0)->zoom_transpen(bitmap,cliprect,
- code,
- attr >> 8,
- attr & 1, attr & 2,
- sx / 0x10000, ((sy + y * ydim) / 0x10000)&0x1ff,
- xscale, yscale, 0 );
- }
- }
-}
-
-UINT32 midas_state::screen_update_midas(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- int layers_ctrl = -1;
-
-#ifdef MAME_DEBUG
- if ( machine().input().code_pressed(KEYCODE_Z) )
- {
- int msk = 0;
- if (machine().input().code_pressed(KEYCODE_Q)) msk |= 1 << 0; // for m_tmap
- if (machine().input().code_pressed(KEYCODE_A)) msk |= 1 << 1; // for sprites
- if (msk != 0) layers_ctrl &= msk;
- }
-#endif
-
- bitmap.fill(4095, cliprect);
-
- if (layers_ctrl & 2) draw_sprites(bitmap,cliprect);
- if (layers_ctrl & 1) m_tmap->draw(screen, bitmap, cliprect, 0, 0);
+ m_sprgen->draw_fixed_layer(bitmap, cliprect.min_y);
return 0;
}
@@ -238,23 +142,34 @@ READ16_MEMBER(midas_state::ret_ffff)
WRITE16_MEMBER(midas_state::midas_gfxregs_w)
{
- COMBINE_DATA( m_gfxregs + offset );
-
- switch( offset )
+ /* accessing the LSB only is not mapped */
+ if (mem_mask != 0x00ff)
{
- case 1:
- {
- UINT16 addr = m_gfxregs[0];
- m_gfxram[addr] = data;
- m_gfxregs[0] += m_gfxregs[2];
-
- if ( addr >= 0x7000 && addr <= 0x7fff ) m_tmap->mark_tile_dirty(addr - 0x7000);
+ /* accessing the MSB only stores same data in MSB and LSB */
+ if (mem_mask == 0xff00)
+ data = (data & 0xff00) | (data >> 8);
- break;
+ switch (offset)
+ {
+ case 0x00: m_sprgen->set_videoram_offset(data); break;
+ case 0x01: m_sprgen->set_videoram_data(data); break;
+ case 0x02: m_sprgen->set_videoram_modulo(data); break;
}
}
}
+WRITE16_MEMBER(midas_state::midas_zoomtable_w)
+{
+ COMBINE_DATA(&m_zoomram[offset]);
+ UINT8 *rgn = memregion("zoomy")->base();
+
+ if (ACCESSING_BITS_0_7)
+ {
+ rgn[offset+0x00000] = data & 0xff;
+ rgn[offset+0x10000] = data & 0xff;
+ }
+
+}
/***************************************************************************************
Live Quiz Show
***************************************************************************************/
@@ -297,7 +212,7 @@ static ADDRESS_MAP_START( livequiz_map, AS_PROGRAM, 16, midas_state )
AM_RANGE(0xba0000, 0xba0001) AM_READ_PORT("START3")
AM_RANGE(0xbc0000, 0xbc0001) AM_READ_PORT("PLAYER3")
- AM_RANGE(0xd00000, 0xd1ffff) AM_RAM // zoom table?
+ AM_RANGE(0xd00000, 0xd1ffff) AM_RAM_WRITE(midas_zoomtable_w) AM_SHARE("zoomtable") // zoom table?
AM_RANGE(0xe00000, 0xe3ffff) AM_RAM
ADDRESS_MAP_END
@@ -361,7 +276,7 @@ static ADDRESS_MAP_START( hammer_map, AS_PROGRAM, 16, midas_state )
AM_RANGE(0x9a0000, 0x9a0001) AM_WRITE(midas_eeprom_w )
- AM_RANGE(0x9c0000, 0x9c0005) AM_WRITE(midas_gfxregs_w ) AM_SHARE("gfxregs")
+ AM_RANGE(0x9c0000, 0x9c0005) AM_WRITE(midas_gfxregs_w )
AM_RANGE(0xa00000, 0xa3ffff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
AM_RANGE(0xa40000, 0xa7ffff) AM_RAM
@@ -380,7 +295,7 @@ static ADDRESS_MAP_START( hammer_map, AS_PROGRAM, 16, midas_state )
AM_RANGE(0xbc0004, 0xbc0005) AM_READ(hammer_sensor_r )
- AM_RANGE(0xd00000, 0xd1ffff) AM_RAM // zoom table?
+ AM_RANGE(0xd00000, 0xd1ffff) AM_RAM_WRITE(midas_zoomtable_w) AM_SHARE("zoomtable") // zoom table?
AM_RANGE(0xe00000, 0xe3ffff) AM_RAM
ADDRESS_MAP_END
@@ -389,17 +304,14 @@ ADDRESS_MAP_END
static const gfx_layout layout16x16x8 =
{
16,16,
- RGN_FRAC(1,4),
+ RGN_FRAC(1,1),
8,
{
- RGN_FRAC(3,4)+8,RGN_FRAC(3,4)+0,
- RGN_FRAC(2,4)+8,RGN_FRAC(2,4)+0,
- RGN_FRAC(1,4)+8,RGN_FRAC(1,4)+0,
- RGN_FRAC(0,4)+8,RGN_FRAC(0,4)+0
+ 56,48,40,32,24,16,8,0
},
- { STEP8(8*16*2+7,-1), STEP8(7,-1) },
- { STEP16(0,8*2) },
- 16*16*2
+ { 0,1,2,3,4,5,6,7, 16*64+0, 6*64+1, 6*64+2, 6*64+3, 6*64+4, 6*64+5, 6*64+6, 6*64+7, },
+ { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64, 8*64, 9*64, 10*64, 11*64, 12*64, 13*64, 14*64, 15*64 },
+ 16*128
};
static const gfx_layout layout8x8x8_2 =
@@ -692,12 +604,35 @@ static INPUT_PORTS_START( hammer )
INPUT_PORTS_END
+void midas_state::machine_start()
+{
+ m_sprgen->set_pens((pen_t*)m_palette->pens());
+ m_sprgen->set_screen(m_screen);
+ m_sprgen->set_sprite_region(memregion("sprites"));
+ m_sprgen->set_fixed_regions(memregion("tiles"), memregion("tiles"));
+}
+
+void midas_state::machine_reset()
+{
+
+}
+
+
+
WRITE_LINE_MEMBER(midas_state::livequiz_irqhandler)
{
logerror("YMZ280 is generating an interrupt. State=%08x\n",state);
}
+
+void midas_state::screen_eof_midas(screen_device &screen, bool state)
+{
+ m_sprgen->buffer_vram();
+}
+
+
+
static MACHINE_CONFIG_START( livequiz, midas_state )
/* basic machine hardware */
@@ -709,12 +644,11 @@ static MACHINE_CONFIG_START( livequiz, midas_state )
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
- MCFG_SCREEN_REFRESH_RATE(60)
- MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
- MCFG_SCREEN_SIZE(320, 256)
- MCFG_SCREEN_VISIBLE_AREA(0, 320-1, 16, 256-16-1)
+ MCFG_SCREEN_RAW_PARAMS(NEOGEO_PIXEL_CLOCK, NEOGEO_HTOTAL, NEOGEO_HBEND, NEOGEO_HBSTART, NEOGEO_VTOTAL, NEOGEO_VBEND, NEOGEO_VBSTART)
MCFG_SCREEN_UPDATE_DRIVER(midas_state, screen_update_midas)
- MCFG_SCREEN_PALETTE("palette")
+ MCFG_SCREEN_VBLANK_DRIVER(midas_state, screen_eof_midas)
+
+ MCFG_DEVICE_ADD("spritegen", NEOGEO_SPRITE_MIDAS, 0)
MCFG_GFXDECODE_ADD("gfxdecode", "palette", midas)
MCFG_PALETTE_ADD("palette", 0x10000)
@@ -743,12 +677,11 @@ static MACHINE_CONFIG_START( hammer, midas_state )
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
- MCFG_SCREEN_REFRESH_RATE(60)
- MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
- MCFG_SCREEN_SIZE(320, 256)
- MCFG_SCREEN_VISIBLE_AREA(0, 320-1, 16, 256-16-1)
+ MCFG_SCREEN_RAW_PARAMS(NEOGEO_PIXEL_CLOCK, NEOGEO_HTOTAL, NEOGEO_HBEND, NEOGEO_HBSTART, NEOGEO_VTOTAL, NEOGEO_VBEND, NEOGEO_VBSTART)
MCFG_SCREEN_UPDATE_DRIVER(midas_state, screen_update_midas)
- MCFG_SCREEN_PALETTE("palette")
+ MCFG_SCREEN_VBLANK_DRIVER(midas_state, screen_eof_midas)
+
+ MCFG_DEVICE_ADD("spritegen", NEOGEO_SPRITE_MIDAS, 0)
MCFG_GFXDECODE_ADD("gfxdecode", "palette", midas)
MCFG_PALETTE_ADD("palette", 0x10000)
@@ -861,16 +794,19 @@ ROM_START( livequiz )
ROM_LOAD( "sub_pic12c508a.u4", 0x000000, 0x000400, CRC(e52ebdc4) SHA1(0f3af66b5ea184e49188e74a873699324a3930f1) )
ROM_REGION( 0x800000, "sprites", 0 )
- ROM_LOAD( "flash.u15", 0x000000, 0x200000, CRC(d6eb56f1) SHA1(52d67bb25dd968c79eccb05159a578516b27e557) )
- ROM_LOAD( "flash.u19", 0x200000, 0x200000, CRC(daa81532) SHA1(9e66bb4639b92c3d76b7918535f55883f22f24b2) )
- ROM_LOAD( "flash.u16", 0x400000, 0x200000, CRC(4c9fd873) SHA1(6e185304ce29771265d3c48b0ef0e840d8bed02d) )
- ROM_LOAD( "flash.u20", 0x600000, 0x200000, CRC(b540a8c7) SHA1(25b9b30c7d5ff1e410ea30580017e45590542561) )
+ ROM_LOAD32_BYTE( "flash.u15", 0x000000, 0x200000, CRC(d6eb56f1) SHA1(52d67bb25dd968c79eccb05159a578516b27e557) )
+ ROM_LOAD32_BYTE( "flash.u19", 0x000001, 0x200000, CRC(daa81532) SHA1(9e66bb4639b92c3d76b7918535f55883f22f24b2) )
+ ROM_LOAD32_BYTE( "flash.u16", 0x000002, 0x200000, CRC(4c9fd873) SHA1(6e185304ce29771265d3c48b0ef0e840d8bed02d) )
+ ROM_LOAD32_BYTE( "flash.u20", 0x000003, 0x200000, CRC(b540a8c7) SHA1(25b9b30c7d5ff1e410ea30580017e45590542561) )
ROM_REGION( 0x080000, "tiles", 0 )
ROM_LOAD( "27c4096.u23", 0x000000, 0x080000, CRC(25121de8) SHA1(edf24d87551639b871baf3243b452a4e2ba84107) )
ROM_REGION( 0x200000, "ymz", 0 )
ROM_LOAD( "flash.u5", 0x000000, 0x200000, CRC(dc062792) SHA1(ec415c918c47ce9d181f014cde317af5717600e4) )
+
+ ROM_REGION( 0x20000, "zoomy", ROMREGION_ERASE00 )
+ /* uploaded */
ROM_END
DRIVER_INIT_MEMBER(midas_state,livequiz)
@@ -944,17 +880,17 @@ ROM_START( hammer )
ROM_LOAD16_WORD_SWAP( "p.u22", 0x000000, 0x200000, CRC(687f1596) SHA1(3dc5fb0af1e8c4f3a42ce4aad39635b1111831d8) )
ROM_REGION( 0x1000000, "sprites", 0 )
- ROM_LOAD( "a0l.u44", 0x000000, 0x200000, CRC(b9cafd81) SHA1(24698970d1aea0907e2963c872ce61077f44c3af) )
- ROM_LOAD( "a0h.u46", 0x200000, 0x200000, CRC(f60f188b) SHA1(486f26c473b46efb402662b2f374e361cd7b4284) )
+ ROM_LOAD32_BYTE( "a0l.u44", 0x000000, 0x200000, CRC(b9cafd81) SHA1(24698970d1aea0907e2963c872ce61077f44c3af) )
+ ROM_LOAD32_BYTE( "a0h.u46", 0x800000, 0x200000, CRC(f60f188b) SHA1(486f26c473b46efb402662b2f374e361cd7b4284) )
- ROM_LOAD( "a1l.u48", 0x400000, 0x200000, CRC(82129cf9) SHA1(6d68e943854bc9e8ea555bf03107dc9e836ca4d9) )
- ROM_LOAD( "a1h.u50", 0x600000, 0x200000, CRC(76897c90) SHA1(aded60d3db834598cd54ad9140eee7be4129cb27) )
+ ROM_LOAD32_BYTE( "a1l.u48", 0x000001, 0x200000, CRC(82129cf9) SHA1(6d68e943854bc9e8ea555bf03107dc9e836ca4d9) )
+ ROM_LOAD32_BYTE( "a1h.u50", 0x800001, 0x200000, CRC(76897c90) SHA1(aded60d3db834598cd54ad9140eee7be4129cb27) )
- ROM_LOAD( "a2l.u45", 0x800000, 0x200000, CRC(d8086ee5) SHA1(9d5f2b3a0f903a69cfd1108ddf5ea61b571c3fe3) )
- ROM_LOAD( "a2h.u47", 0xa00000, 0x200000, CRC(a64aa2df) SHA1(7e4eb049cd6a5971a455488a484f225763921614) )
+ ROM_LOAD32_BYTE( "a2l.u45", 0x000002, 0x200000, CRC(d8086ee5) SHA1(9d5f2b3a0f903a69cfd1108ddf5ea61b571c3fe3) )
+ ROM_LOAD32_BYTE( "a2h.u47", 0x800002, 0x200000, CRC(a64aa2df) SHA1(7e4eb049cd6a5971a455488a484f225763921614) )
- ROM_LOAD( "a3l.u49", 0xc00000, 0x200000, CRC(4e83cf00) SHA1(e66a0b4eae0f46bf36126be3795cfac3ad3d4282) )
- ROM_LOAD( "a3h.u51", 0xe00000, 0x200000, CRC(834de39f) SHA1(6e9867180ca20e64f60bad5cad82674ce8f45b7b) )
+ ROM_LOAD32_BYTE( "a3l.u49", 0x000003, 0x200000, CRC(4e83cf00) SHA1(e66a0b4eae0f46bf36126be3795cfac3ad3d4282) )
+ ROM_LOAD32_BYTE( "a3h.u51", 0x800003, 0x200000, CRC(834de39f) SHA1(6e9867180ca20e64f60bad5cad82674ce8f45b7b) )
ROM_REGION( 0x080000, "tiles", ROMREGION_ERASE )
// Use the tiles rom from livequiz (not present in this set) to show some debug text
@@ -963,7 +899,10 @@ ROM_START( hammer )
ROM_REGION( 0x400000, "ymz", 0 )
ROM_LOAD( "s0.u25", 0x000000, 0x200000, CRC(c049a3e0) SHA1(0c7016c3128c170a84ad3f92fad1165775210e3d) )
ROM_LOAD( "s1.u26", 0x200000, 0x200000, CRC(9cc4b3ec) SHA1(b91a8747074a1032eb7f70a015d394fe8e896d7e) )
+
+ ROM_REGION( 0x20000, "zoomy", ROMREGION_ERASE00 )
+ /* uploaded */
ROM_END
-GAME( 1999, livequiz, 0, livequiz, livequiz, midas_state, livequiz, ROT0, "Andamiro", "Live Quiz Show", GAME_IMPERFECT_GRAPHICS )
+GAME( 1999, livequiz, 0, livequiz, livequiz, midas_state, livequiz, ROT0, "Andamiro", "Live Quiz Show", 0 )
GAME( 2000, hammer, 0, hammer, hammer, driver_device, 0, ROT0, "Andamiro", "Hammer", 0 )
diff --git a/src/mame/drivers/neogeo.c b/src/mame/drivers/neogeo.c
index 348185dc6b1..e4c71fd2c35 100644
--- a/src/mame/drivers/neogeo.c
+++ b/src/mame/drivers/neogeo.c
@@ -457,9 +457,7 @@
*
*************************************/
-// On scanline 224, /VBLANK goes low 56 mclks (14 pixels) from the rising edge of /HSYNC.
-// Two mclks after /VBLANK goes low, the hardware sets a pending IRQ1 flip-flop.
-#define NEOGEO_VBLANK_IRQ_HTIM (attotime::from_ticks(56+2, NEOGEO_MASTER_CLOCK))
+
// The display counter is automatically reloaded with the load register contents on scanline 224,
// 1146 mclks from the rising edge of /HSYNC.
@@ -999,7 +997,7 @@ WRITE8_MEMBER(neogeo_state::system_control_w)
case 0x05:
if (m_type == NEOGEO_MVS)
{
- neogeo_set_fixed_layer_source(bit);
+ m_sprgen->neogeo_set_fixed_layer_source(bit);
m_bank_audio_main->set_entry(bit);
}
break;
@@ -1088,7 +1086,7 @@ void neogeo_state::set_output_data( UINT8 data )
DRIVER_INIT_MEMBER(neogeo_state,neogeo)
{
- m_fixed_layer_bank_type = 0;
+ m_sprgen->m_fixed_layer_bank_type = 0;
}
@@ -1143,6 +1141,12 @@ void neogeo_state::machine_start()
save_item(NAME(m_led2_value));
machine().save().register_postload(save_prepost_delegate(FUNC(neogeo_state::neogeo_postload), this));
+
+
+ m_sprgen->set_screen(m_screen);
+ m_sprgen->set_sprite_region(m_region_sprites);
+ m_sprgen->set_fixed_regions(m_region_fixed, m_region_fixedbios);
+
}
@@ -1787,6 +1791,8 @@ MACHINE_CONFIG_START( neogeo_base, neogeo_state )
MCFG_SCREEN_RAW_PARAMS(NEOGEO_PIXEL_CLOCK, NEOGEO_HTOTAL, NEOGEO_HBEND, NEOGEO_HBSTART, NEOGEO_VTOTAL, NEOGEO_VBEND, NEOGEO_VBSTART)
MCFG_SCREEN_UPDATE_DRIVER(neogeo_state, screen_update_neogeo)
+ MCFG_DEVICE_ADD("spritegen", NEOGEO_SPRITE_OPTIMZIED, 0)
+
/* audio hardware */
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
@@ -10208,7 +10214,7 @@ DRIVER_INIT_MEMBER(neogeo_state,fatfury2)
DRIVER_INIT_MEMBER(neogeo_state,zupapa)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0xbd);
}
@@ -10229,7 +10235,7 @@ DRIVER_INIT_MEMBER(neogeo_state,kof99)
{
DRIVER_INIT_CALL(neogeo);
kof99_decrypt_68k();
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0x00);
kof99_install_protection();
}
@@ -10237,7 +10243,7 @@ DRIVER_INIT_MEMBER(neogeo_state,kof99)
DRIVER_INIT_MEMBER(neogeo_state,kof99k)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0x00);
}
@@ -10245,7 +10251,7 @@ DRIVER_INIT_MEMBER(neogeo_state,garou)
{
DRIVER_INIT_CALL(neogeo);
garou_decrypt_68k();
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0x06);
garou_install_protection();
}
@@ -10254,7 +10260,7 @@ DRIVER_INIT_MEMBER(neogeo_state,garouh)
{
DRIVER_INIT_CALL(neogeo);
garouh_decrypt_68k();
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0x06);
garouh_install_protection();
}
@@ -10270,7 +10276,7 @@ DRIVER_INIT_MEMBER(neogeo_state,mslug3)
{
DRIVER_INIT_CALL(neogeo);
mslug3_decrypt_68k();
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0xad);
mslug3_install_protection();
}
@@ -10278,7 +10284,7 @@ DRIVER_INIT_MEMBER(neogeo_state,mslug3)
DRIVER_INIT_MEMBER(neogeo_state,mslug3h)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0xad);
}
@@ -10293,7 +10299,7 @@ DRIVER_INIT_MEMBER(neogeo_state,kof2000)
{
DRIVER_INIT_CALL(neogeo);
kof2000_decrypt_68k();
- m_fixed_layer_bank_type = 2;
+ m_sprgen->m_fixed_layer_bank_type = 2;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x00);
kof2000_install_protection();
@@ -10302,7 +10308,7 @@ DRIVER_INIT_MEMBER(neogeo_state,kof2000)
DRIVER_INIT_MEMBER(neogeo_state,kof2000n)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 2;
+ m_sprgen->m_fixed_layer_bank_type = 2;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x00);
}
@@ -10310,7 +10316,7 @@ DRIVER_INIT_MEMBER(neogeo_state,kof2000n)
DRIVER_INIT_MEMBER(neogeo_state,kof2001)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof2000_neogeo_gfx_decrypt(0x1e);
neogeo_cmc50_m1_decrypt();
}
@@ -10339,7 +10345,7 @@ DRIVER_INIT_MEMBER(neogeo_state,ct2k3sa)
DRIVER_INIT_MEMBER(neogeo_state,mslug4)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1; /* USA violent content screen is wrong -- not a bug, confirmed on real hardware! */
+ m_sprgen->m_fixed_layer_bank_type = 1; /* USA violent content screen is wrong -- not a bug, confirmed on real hardware! */
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x31);
neo_pcm2_snk_1999(8);
@@ -10356,42 +10362,42 @@ DRIVER_INIT_MEMBER(neogeo_state,ms4plus)
DRIVER_INIT_MEMBER(neogeo_state,ganryu)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0x07);
}
DRIVER_INIT_MEMBER(neogeo_state,s1945p)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0x05);
}
DRIVER_INIT_MEMBER(neogeo_state,preisle2)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0x9f);
}
DRIVER_INIT_MEMBER(neogeo_state,bangbead)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0xf8);
}
DRIVER_INIT_MEMBER(neogeo_state,nitd)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0xff);
}
DRIVER_INIT_MEMBER(neogeo_state,sengoku3)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
kof99_neogeo_gfx_decrypt(0xfe);
}
@@ -10399,7 +10405,7 @@ DRIVER_INIT_MEMBER(neogeo_state,rotd)
{
DRIVER_INIT_CALL(neogeo);
neo_pcm2_snk_1999(16);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x3f);
}
@@ -10483,7 +10489,7 @@ DRIVER_INIT_MEMBER(neogeo_state,matrim)
DRIVER_INIT_CALL(neogeo);
matrim_decrypt_68k();
neo_pcm2_swap(1);
- m_fixed_layer_bank_type = 2;
+ m_sprgen->m_fixed_layer_bank_type = 2;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x6a);
}
@@ -10492,7 +10498,7 @@ DRIVER_INIT_MEMBER(neogeo_state,matrimbl)
{
DRIVER_INIT_CALL(neogeo);
matrim_decrypt_68k();
- m_fixed_layer_bank_type = 2;
+ m_sprgen->m_fixed_layer_bank_type = 2;
matrimbl_decrypt();
neogeo_sfix_decrypt(); /* required for text layer */
}
@@ -10501,7 +10507,7 @@ DRIVER_INIT_MEMBER(neogeo_state,pnyaa)
{
DRIVER_INIT_CALL(neogeo);
neo_pcm2_snk_1999(4);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x2e);
}
@@ -10511,7 +10517,7 @@ DRIVER_INIT_MEMBER(neogeo_state,mslug5)
DRIVER_INIT_CALL(neogeo);
mslug5_decrypt_68k();
neo_pcm2_swap(2);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x19);
install_pvc_protection();
@@ -10537,7 +10543,7 @@ DRIVER_INIT_MEMBER(neogeo_state,ms5pcb)
svcpcb_gfx_decrypt();
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x19);
- m_fixed_layer_bank_type = 2;
+ m_sprgen->m_fixed_layer_bank_type = 2;
svcpcb_s1data_decrypt();
neo_pcm2_swap(2);
install_pvc_protection();
@@ -10550,7 +10556,7 @@ DRIVER_INIT_MEMBER(neogeo_state,ms5plus)
cmc50_neogeo_gfx_decrypt(0x19);
neo_pcm2_swap(2);
neogeo_bootleg_sx_decrypt(1);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
neogeo_cmc50_m1_decrypt();
install_ms5plus_protection();
}
@@ -10565,7 +10571,7 @@ DRIVER_INIT_MEMBER(neogeo_state,svcpcb)
kof2000_neogeo_gfx_decrypt(0x57);
svcpcb_s1data_decrypt();
neo_pcm2_swap(3);
- m_fixed_layer_bank_type = 2;
+ m_sprgen->m_fixed_layer_bank_type = 2;
install_pvc_protection();
install_banked_bios();
}
@@ -10575,7 +10581,7 @@ DRIVER_INIT_MEMBER(neogeo_state,svc)
DRIVER_INIT_CALL(neogeo);
svc_px_decrypt();
neo_pcm2_swap(3);
- m_fixed_layer_bank_type = 2;
+ m_sprgen->m_fixed_layer_bank_type = 2;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x57);
install_pvc_protection();
@@ -10621,7 +10627,7 @@ DRIVER_INIT_MEMBER(neogeo_state,samsho5)
DRIVER_INIT_CALL(neogeo);
samsho5_decrypt_68k();
neo_pcm2_swap(4);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x0f);
}
@@ -10658,7 +10664,7 @@ DRIVER_INIT_MEMBER(neogeo_state,kf2k3pcb)
kof2000_neogeo_gfx_decrypt(0x9d);
kf2k3pcb_decrypt_s1data();
neo_pcm2_swap(5);
- m_fixed_layer_bank_type = 2;
+ m_sprgen->m_fixed_layer_bank_type = 2;
install_pvc_protection();
m_maincpu->space(AS_PROGRAM).install_rom(0xc00000, 0xc7ffff, 0, 0x080000, memregion("mainbios")->base()); // 512k bios
}
@@ -10668,7 +10674,7 @@ DRIVER_INIT_MEMBER(neogeo_state,kof2003)
DRIVER_INIT_CALL(neogeo);
kof2003_decrypt_68k();
neo_pcm2_swap(5);
- m_fixed_layer_bank_type = 2;
+ m_sprgen->m_fixed_layer_bank_type = 2;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x9d);
install_pvc_protection();
@@ -10679,7 +10685,7 @@ DRIVER_INIT_MEMBER(neogeo_state,kof2003h)
DRIVER_INIT_CALL(neogeo);
kof2003h_decrypt_68k();
neo_pcm2_swap(5);
- m_fixed_layer_bank_type = 2;
+ m_sprgen->m_fixed_layer_bank_type = 2;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x9d);
install_pvc_protection();
@@ -10719,7 +10725,7 @@ DRIVER_INIT_MEMBER(neogeo_state,samsh5sp)
DRIVER_INIT_CALL(neogeo);
samsh5sp_decrypt_68k();
neo_pcm2_swap(6);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0x0d);
}
@@ -10727,7 +10733,7 @@ DRIVER_INIT_MEMBER(neogeo_state,samsh5sp)
DRIVER_INIT_MEMBER(neogeo_state,jockeygp)
{
DRIVER_INIT_CALL(neogeo);
- m_fixed_layer_bank_type = 1;
+ m_sprgen->m_fixed_layer_bank_type = 1;
neogeo_cmc50_m1_decrypt();
kof2000_neogeo_gfx_decrypt(0xac);
diff --git a/src/mame/includes/neogeo.h b/src/mame/includes/neogeo.h
index 16493c8132a..2d92f25df8a 100644
--- a/src/mame/includes/neogeo.h
+++ b/src/mame/includes/neogeo.h
@@ -6,19 +6,11 @@
#include "machine/upd1990a.h"
#include "machine/ng_memcard.h"
+#include "video/neogeo_spr.h"
-#define NEOGEO_MASTER_CLOCK (24000000)
-#define NEOGEO_MAIN_CPU_CLOCK (NEOGEO_MASTER_CLOCK / 2)
-#define NEOGEO_AUDIO_CPU_CLOCK (NEOGEO_MASTER_CLOCK / 6)
-#define NEOGEO_YM2610_CLOCK (NEOGEO_MASTER_CLOCK / 3)
-#define NEOGEO_PIXEL_CLOCK (NEOGEO_MASTER_CLOCK / 4)
-#define NEOGEO_HTOTAL (0x180)
-#define NEOGEO_HBEND (0x01e) /* this should really be 29.5 */
-#define NEOGEO_HBSTART (0x15e) /* this should really be 349.5 */
-#define NEOGEO_VTOTAL (0x108)
-#define NEOGEO_VBEND (0x010)
-#define NEOGEO_VBSTART (0x0f0)
-#define NEOGEO_VSSTART (0x100)
+// On scanline 224, /VBLANK goes low 56 mclks (14 pixels) from the rising edge of /HSYNC.
+// Two mclks after /VBLANK goes low, the hardware sets a pending IRQ1 flip-flop.
+#define NEOGEO_VBLANK_IRQ_HTIM (attotime::from_ticks(56+2, NEOGEO_MASTER_CLOCK))
class neogeo_state : public driver_device
@@ -39,7 +31,8 @@ public:
m_save_ram(*this, "saveram"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
- m_memcard(*this, "memcard")
+ m_memcard(*this, "memcard"),
+ m_sprgen(*this, "spritegen")
{ }
DECLARE_WRITE8_MEMBER(io_control_w);
@@ -130,8 +123,7 @@ public:
TIMER_CALLBACK_MEMBER(display_position_interrupt_callback);
TIMER_CALLBACK_MEMBER(display_position_vblank_callback);
TIMER_CALLBACK_MEMBER(vblank_interrupt_callback);
- TIMER_CALLBACK_MEMBER(auto_animation_timer_callback);
- TIMER_CALLBACK_MEMBER(sprite_line_timer_callback);
+
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(neo_cartridge);
// MVS-specific
@@ -158,31 +150,17 @@ protected:
void neogeo_set_display_counter_msb(UINT16 data);
void neogeo_set_display_counter_lsb(UINT16 data);
void set_video_control( UINT16 data );
- void optimize_sprite_data();
- void draw_fixed_layer( bitmap_rgb32 &bitmap, int scanline );
- void set_videoram_offset( UINT16 data );
- UINT16 get_videoram_data( );
- void set_videoram_data( UINT16 data);
- void set_videoram_modulo( UINT16 data);
- UINT16 get_videoram_modulo( );
+
+
+
+
+
void compute_rgb_weights( );
void regenerate_pens();
pen_t get_pen( UINT16 data );
void neogeo_set_palette_bank( UINT8 data );
void neogeo_set_screen_dark( UINT8 data );
- void set_auto_animation_speed( UINT8 data);
- void set_auto_animation_disabled( UINT8 data);
- UINT8 neogeo_get_auto_animation_counter( );
- void create_auto_animation_timer( );
- void start_auto_animation_timer( );
- void neogeo_set_fixed_layer_source( UINT8 data );
- inline int rows_to_height(int rows);
- inline int sprite_on_scanline(int scanline, int y, int rows);
- void draw_sprites( bitmap_rgb32 &bitmap, int scanline );
- void parse_sprites( int scanline );
- void create_sprite_line_timer( );
- void start_sprite_line_timer( );
- UINT16 get_video_control( );
+
void audio_cpu_check_nmi();
void select_controller( UINT8 data );
void set_save_ram_unlock( UINT8 data );
@@ -359,8 +337,6 @@ protected:
emu_timer *m_display_position_interrupt_timer;
emu_timer *m_display_position_vblank_timer;
emu_timer *m_vblank_interrupt_timer;
- emu_timer *m_auto_animation_timer;
- emu_timer *m_sprite_line_timer;
UINT32 m_display_counter;
UINT8 m_vblank_interrupt_pending;
UINT8 m_display_position_interrupt_pending;
@@ -369,23 +345,8 @@ protected:
UINT8 m_vblank_level;
UINT8 m_raster_level;
- UINT16 *m_videoram;
- UINT16 m_vram_offset;
- UINT16 m_vram_read_buffer;
- UINT16 m_vram_modulo;
-
- const UINT8 *m_region_zoomy;
-
- dynamic_array<UINT8> m_sprite_gfx;
- UINT32 m_sprite_gfx_address_mask;
-
- UINT8 m_auto_animation_speed;
- UINT8 m_auto_animation_disabled;
- UINT8 m_auto_animation_counter;
- UINT8 m_auto_animation_frame_counter;
-
- UINT8 m_fixed_layer_source;
- UINT8 m_fixed_layer_bank_type;
+ required_device<neosprite_optimized_device> m_sprgen;
+ UINT16 get_video_control( );
// color/palette related
// TODO: disentangle from the rest of the video emulation
@@ -416,6 +377,8 @@ protected:
const UINT8 *address_0_7_xor;
UINT16 m_cartridge_ram[0x1000];
+
+
};
diff --git a/src/mame/mame.mak b/src/mame/mame.mak
index b8c40855ba5..878934c76c6 100644
--- a/src/mame/mame.mak
+++ b/src/mame/mame.mak
@@ -1524,6 +1524,7 @@ $(MAMEOBJ)/nasco.a: \
$(MAMEOBJ)/neogeo.a: \
$(DRIVERS)/neogeo.o $(VIDEO)/neogeo.o \
+ $(VIDEO)/neogeo_spr.o \
$(MACHINE)/neoboot.o \
$(MACHINE)/neocrypt.o \
$(MACHINE)/neoprot.o \
diff --git a/src/mame/video/neogeo.c b/src/mame/video/neogeo.c
index de52629bc34..1c9cd8cb2ab 100644
--- a/src/mame/video/neogeo.c
+++ b/src/mame/video/neogeo.c
@@ -10,48 +10,6 @@
#define NUM_PENS (0x1000)
-#define VERBOSE (0)
-
-/*************************************
- *
- * Video RAM access
- *
- *************************************/
-
-void neogeo_state::set_videoram_offset( UINT16 data )
-{
- m_vram_offset = (data & 0x8000 ? data & 0x87ff : data);
-
- /* the read happens right away */
- m_vram_read_buffer = m_videoram[m_vram_offset];
-}
-
-
-UINT16 neogeo_state::get_videoram_data( )
-{
- return m_vram_read_buffer;
-}
-
-
-void neogeo_state::set_videoram_data( UINT16 data)
-{
- m_videoram[m_vram_offset] = data;
-
- /* auto increment/decrement the current offset - A15 is NOT affected */
- set_videoram_offset((m_vram_offset & 0x8000) | ((m_vram_offset + m_vram_modulo) & 0x7fff));
-}
-
-
-void neogeo_state::set_videoram_modulo( UINT16 data)
-{
- m_vram_modulo = data;
-}
-
-
-UINT16 neogeo_state::get_videoram_modulo( )
-{
- return m_vram_modulo;
-}
@@ -185,519 +143,63 @@ WRITE16_MEMBER(neogeo_state::neogeo_paletteram_w)
/*************************************
*
- * Auto animation
+ * Video system start
*
*************************************/
-void neogeo_state::set_auto_animation_speed( UINT8 data)
-{
- m_auto_animation_speed = data;
-}
-
-
-void neogeo_state::set_auto_animation_disabled( UINT8 data)
-{
- m_auto_animation_disabled = data;
-}
-
-
-UINT8 neogeo_state::neogeo_get_auto_animation_counter( )
-{
- return m_auto_animation_counter;
-}
-
-
-TIMER_CALLBACK_MEMBER(neogeo_state::auto_animation_timer_callback)
+void neogeo_state::video_start()
{
- if (m_auto_animation_frame_counter == 0)
- {
- m_auto_animation_frame_counter = m_auto_animation_speed;
- m_auto_animation_counter += 1;
- }
- else
- m_auto_animation_frame_counter = m_auto_animation_frame_counter - 1;
-
- m_auto_animation_timer->adjust(m_screen->time_until_pos(NEOGEO_VSSTART));
-}
+ /* allocate memory not directly mapped */
+ m_palettes[0] = auto_alloc_array(machine(), UINT16, NUM_PENS);
+ m_palettes[1] = auto_alloc_array(machine(), UINT16, NUM_PENS);
+ m_pens = auto_alloc_array(machine(), pen_t, NUM_PENS);
+ compute_rgb_weights();
-void neogeo_state::create_auto_animation_timer( )
-{
- m_auto_animation_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(neogeo_state::auto_animation_timer_callback),this));
-}
+ memset(m_palettes[0], 0x00, NUM_PENS * sizeof(UINT16));
+ memset(m_palettes[1], 0x00, NUM_PENS * sizeof(UINT16));
+ memset(m_pens, 0x00, NUM_PENS * sizeof(pen_t));
+ save_pointer(NAME(m_palettes[0]), NUM_PENS);
+ save_pointer(NAME(m_palettes[1]), NUM_PENS);
+ save_item(NAME(m_screen_dark));
+ save_item(NAME(m_palette_bank));
+ machine().save().register_postload(save_prepost_delegate(FUNC(neogeo_state::regenerate_pens), this));
-void neogeo_state::start_auto_animation_timer( )
-{
- m_auto_animation_timer->adjust(m_screen->time_until_pos(NEOGEO_VSSTART));
+ m_sprgen->set_pens(m_pens);
}
/*************************************
*
- * Fixed layer
+ * Video system reset
*
*************************************/
-void neogeo_state::neogeo_set_fixed_layer_source( UINT8 data )
-{
- m_fixed_layer_source = data;
-}
-
-
-void neogeo_state::draw_fixed_layer( bitmap_rgb32 &bitmap, int scanline )
+void neogeo_state::video_reset()
{
- int x;
-
- UINT8* gfx_base = m_fixed_layer_source ? m_region_fixed->base() : m_region_fixedbios->base();
- UINT32 addr_mask = ( m_fixed_layer_source ? m_region_fixed->bytes() : m_region_fixedbios->bytes() ) - 1;
- UINT16 *video_data = &m_videoram[0x7000 | (scanline >> 3)];
- UINT32 *pixel_addr = &bitmap.pix32(scanline, NEOGEO_HBEND);
-
- int garouoffsets[32];
- int banked = m_fixed_layer_source && (addr_mask > 0x1ffff);
-
- /* thanks to Mr K for the garou & kof2000 banking info */
- /* Build line banking table for Garou & MS3 before starting render */
- if (banked && m_fixed_layer_bank_type == 1)
- {
- int garoubank = 0;
- int k = 0;
- int y = 0;
- while (y < 32)
- {
- if (m_videoram[0x7500 + k] == 0x0200 && (m_videoram[0x7580 + k] & 0xff00) == 0xff00)
- {
- garoubank = m_videoram[0x7580 + k] & 3;
- garouoffsets[y++] = garoubank;
- }
- garouoffsets[y++] = garoubank;
- k += 2;
- }
- }
-
- for (x = 0; x < 40; x++)
- {
- UINT16 code_and_palette = *video_data;
- UINT16 code = code_and_palette & 0x0fff;
-
- if (banked)
- {
- int y = scanline >> 3;
- switch (m_fixed_layer_bank_type)
- {
- case 1:
- /* Garou, MSlug 3 */
- code += 0x1000 * (garouoffsets[(y - 2) & 31] ^ 3);
- break;
- case 2:
- code += 0x1000 * (((m_videoram[0x7500 + ((y - 1) & 31) + 32 * (x / 6)] >> (5 - (x % 6)) * 2) & 3) ^ 3);
- break;
- }
- }
-
- {
- UINT8 data;
- int i;
-
- UINT8 *gfx = &gfx_base[((code << 5) | (scanline & 0x07)) & addr_mask];
- pen_t *char_pens = &m_pens[code_and_palette >> 12 << 4];
-
- for (i = 0; i < 4; i++)
- {
- static const UINT32 pix_offsets[] = { 0x10, 0x18, 0x00, 0x08 };
-
- data = gfx[pix_offsets[i]];
-
- if (data & 0x0f)
- *pixel_addr = char_pens[data & 0x0f];
- pixel_addr++;
-
- if (data & 0xf0)
- *pixel_addr = char_pens[(data & 0xf0) >> 4];
- pixel_addr++;
- }
- }
- video_data = video_data + 0x20;
- }
}
/*************************************
*
- * Sprite hardware
+ * Video update
*
*************************************/
-#define MAX_SPRITES_PER_SCREEN (381)
-#define MAX_SPRITES_PER_LINE (96)
-
-
-/* horizontal zoom table - verified on real hardware */
-static const int zoom_x_tables[][16] =
-{
- { 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0 },
- { 0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0 },
- { 0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0 },
- { 0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0 },
- { 0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0 },
- { 0,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0 },
- { 0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0 },
- { 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0 },
- { 1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0 },
- { 1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0 },
- { 1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1 },
- { 1,0,1,1,1,0,1,1,1,1,1,0,1,0,1,1 },
- { 1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1 },
- { 1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1 },
- { 1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1 },
- { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }
-};
-
-
-inline int neogeo_state::rows_to_height(int rows)
-{
- if ((rows == 0) || (rows > 0x20))
- rows = 0x20;
-
- return rows * 0x10;
-}
-
-
-inline int neogeo_state::sprite_on_scanline(int scanline, int y, int rows)
-{
- /* check if the current scanline falls inside this sprite,
- two possible scenerios, wrap around or not */
- int max_y = (y + rows_to_height(rows) - 1) & 0x1ff;
-
- return (((max_y >= y) && (scanline >= y) && (scanline <= max_y)) ||
- ((max_y < y) && ((scanline >= y) || (scanline <= max_y))));
-}
-
-
-void neogeo_state::draw_sprites( bitmap_rgb32 &bitmap, int scanline )
-{
- int sprite_index;
- int max_sprite_index;
-
- int y = 0;
- int x = 0;
- int rows = 0;
- int zoom_y = 0;
- int zoom_x = 0;
- UINT16 *sprite_list;
-
- /* select the active list */
- if (scanline & 0x01)
- sprite_list = &m_videoram[0x8680];
- else
- sprite_list = &m_videoram[0x8600];
-
- /* optimization -- find last non-zero entry and only draw that many +1
- sprite. This is not 100% correct as the hardware will keep drawing
- the #0 sprite over and over, but we need the speed */
- for (max_sprite_index = (MAX_SPRITES_PER_LINE - 1); max_sprite_index >= 0; max_sprite_index--)
- {
- if (sprite_list[max_sprite_index] != 0)
- break;
- }
-
- /* add the +1 now, just in case the 0 at the end is real sprite */
- if (max_sprite_index != (MAX_SPRITES_PER_LINE - 1))
- max_sprite_index = max_sprite_index + 1;
-
- for (sprite_index = 0; sprite_index <= max_sprite_index; sprite_index++)
- {
- UINT16 sprite_number = sprite_list[sprite_index] & 0x01ff;
- UINT16 y_control = m_videoram[0x8200 | sprite_number];
- UINT16 zoom_control = m_videoram[0x8000 | sprite_number];
-
- /* if chained, go to next X coordinate and get new X zoom */
- if (y_control & 0x40)
- {
- x = (x + zoom_x + 1) & 0x01ff;
- zoom_x = (zoom_control >> 8) & 0x0f;
- }
- /* new block */
- else
- {
- y = 0x200 - (y_control >> 7);
- x = m_videoram[0x8400 | sprite_number] >> 7;
- zoom_y = zoom_control & 0xff;
- zoom_x = (zoom_control >> 8) & 0x0f;
- rows = y_control & 0x3f;
- }
-
- /* skip if falls completely outside the screen */
- if ((x >= 0x140) && (x <= 0x1f0))
- continue;
-
- /* double check the Y coordinate, in case somebody modified the sprite coordinate
- since we buffered it */
- if (sprite_on_scanline(scanline, y, rows))
- {
- int sprite_y;
- int tile;
- UINT8 sprite_y_and_tile;
- offs_t attr_and_code_offs;
- UINT16 attr;
- UINT32 code;
- const int *zoom_x_table;
- UINT8 *gfx;
- pen_t *line_pens;
- int x_inc;
-
- int sprite_line = (scanline - y) & 0x1ff;
- int zoom_line = sprite_line & 0xff;
- int invert = sprite_line & 0x100;
-
- if (invert)
- zoom_line ^= 0xff;
-
- if (rows > 0x20)
- {
- zoom_line = zoom_line % ((zoom_y + 1) << 1);
-
- if (zoom_line > zoom_y)
- {
- zoom_line = ((zoom_y + 1) << 1) - 1 - zoom_line;
- invert = !invert;
- }
- }
-
- sprite_y_and_tile = m_region_zoomy[(zoom_y << 8) | zoom_line];
- sprite_y = sprite_y_and_tile & 0x0f;
- tile = sprite_y_and_tile >> 4;
-
- if (invert)
- {
- sprite_y ^= 0x0f;
- tile ^= 0x1f;
- }
-
- attr_and_code_offs = (sprite_number << 6) | (tile << 1);
- attr = m_videoram[attr_and_code_offs + 1];
- code = ((attr << 12) & 0x70000) | m_videoram[attr_and_code_offs];
-
- /* substitute auto animation bits */
- if (!m_auto_animation_disabled)
- {
- if (attr & 0x0008)
- code = (code & ~0x07) | (m_auto_animation_counter & 0x07);
- else if (attr & 0x0004)
- code = (code & ~0x03) | (m_auto_animation_counter & 0x03);
- }
-
- /* vertical flip? */
- if (attr & 0x0002)
- sprite_y ^= 0x0f;
-
- zoom_x_table = zoom_x_tables[zoom_x];
-
- /* compute offset in gfx ROM and mask it to the number of bits available */
- gfx = &m_sprite_gfx[((code << 8) | (sprite_y << 4)) & m_sprite_gfx_address_mask];
-
- line_pens = &m_pens[attr >> 8 << 4];
-
- /* horizontal flip? */
- if (attr & 0x0001)
- {
- gfx = gfx + 0x0f;
- x_inc = -1;
- }
- else
- x_inc = 1;
-
- /* draw the line - no wrap-around */
- if (x <= 0x01f0)
- {
- int i;
-
- UINT32 *pixel_addr = &bitmap.pix32(scanline, x + NEOGEO_HBEND);
-
- for (i = 0; i < 0x10; i++)
- {
- if (*zoom_x_table)
- {
- if (*gfx)
- *pixel_addr = line_pens[*gfx];
-
- pixel_addr++;
- }
-
- zoom_x_table++;
- gfx += x_inc;
- }
- }
- /* wrap-around */
- else
- {
- int i;
-
- int x_save = x;
- UINT32 *pixel_addr = &bitmap.pix32(scanline, NEOGEO_HBEND);
-
- for (i = 0; i < 0x10; i++)
- {
- if (*zoom_x_table)
- {
- if (x >= 0x200)
- {
- if (*gfx)
- *pixel_addr = line_pens[*gfx];
-
- pixel_addr++;
- }
-
- x++;
- }
-
- zoom_x_table++;
- gfx += x_inc;
- }
-
- x = x_save;
- }
- }
- }
-}
-
-
-void neogeo_state::parse_sprites( int scanline )
-{
- UINT16 sprite_number;
- int y = 0;
- int rows = 0;
- UINT16 *sprite_list;
-
- int active_sprite_count = 0;
-
- /* select the active list */
- if (scanline & 0x01)
- sprite_list = &m_videoram[0x8680];
- else
- sprite_list = &m_videoram[0x8600];
-
- /* scan all sprites */
- for (sprite_number = 0; sprite_number < MAX_SPRITES_PER_SCREEN; sprite_number++)
- {
- UINT16 y_control = m_videoram[0x8200 | sprite_number];
-
- /* if not chained, get Y position and height, otherwise use previous values */
- if (~y_control & 0x40)
- {
- y = 0x200 - (y_control >> 7);
- rows = y_control & 0x3f;
- }
-
- /* skip sprites with 0 rows */
- if (rows == 0)
- continue;
-
- if (!sprite_on_scanline(scanline, y, rows))
- continue;
-
- /* sprite is on this scanline, add it to active list */
- *sprite_list = sprite_number;
-
- sprite_list++;
-
- /* increment sprite count, and if we reached the max, bail out */
- active_sprite_count++;
-
- if (active_sprite_count == MAX_SPRITES_PER_LINE)
- break;
- }
-
- /* fill the rest of the sprite list with 0, including one extra entry */
- memset(sprite_list, 0, sizeof(sprite_list[0]) * (MAX_SPRITES_PER_LINE - active_sprite_count + 1));
-}
-
-
-TIMER_CALLBACK_MEMBER(neogeo_state::sprite_line_timer_callback)
-{
- int scanline = param;
-
- /* we are at the beginning of a scanline -
- we need to draw the previous scanline and parse the sprites on the current one */
- if (scanline != 0)
- m_screen->update_partial(scanline - 1);
-
- parse_sprites(scanline);
-
- /* let's come back at the beginning of the next line */
- scanline = (scanline + 1) % NEOGEO_VTOTAL;
-
- m_sprite_line_timer->adjust(m_screen->time_until_pos(scanline), scanline);
-}
-
-
-void neogeo_state::create_sprite_line_timer( )
-{
- m_sprite_line_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(neogeo_state::sprite_line_timer_callback),this));
-}
-
-
-void neogeo_state::start_sprite_line_timer( )
-{
- m_sprite_line_timer->adjust(m_screen->time_until_pos(0));
-}
-
-
-void neogeo_state::optimize_sprite_data()
+UINT32 neogeo_state::screen_update_neogeo(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- /* convert the sprite graphics data into a format that
- allows faster blitting */
- UINT8 *src;
- UINT8 *dest;
- UINT32 mask;
- UINT32 len;
- UINT32 bit;
-
- /* get mask based on the length rounded up to the nearest
- power of 2 */
- mask = 0xffffffff;
-
- len = m_region_sprites->bytes();
-
- for (bit = 0x80000000; bit != 0; bit >>= 1)
- {
- if ((len * 2 - 1) & bit)
- break;
-
- mask >>= 1;
- }
+ // fill with background color first
+ bitmap.fill(m_pens[0x0fff], cliprect);
- m_sprite_gfx.resize(mask + 1);
- m_sprite_gfx_address_mask = mask;
+ m_sprgen->draw_sprites(bitmap, cliprect.min_y);
- src = m_region_sprites->base();
- dest = m_sprite_gfx;
+ m_sprgen->draw_fixed_layer(bitmap, cliprect.min_y);
- for (unsigned i = 0; i < len; i += 0x80, src += 0x80)
- {
- for (unsigned y = 0; y < 0x10; y++)
- {
- for (unsigned x = 0; x < 8; x++)
- {
- *(dest++) = (((src[0x43 | (y << 2)] >> x) & 0x01) << 3) |
- (((src[0x41 | (y << 2)] >> x) & 0x01) << 2) |
- (((src[0x42 | (y << 2)] >> x) & 0x01) << 1) |
- (((src[0x40 | (y << 2)] >> x) & 0x01) << 0);
- }
-
- for (unsigned x = 0; x < 8; x++)
- {
- *(dest++) = (((src[0x03 | (y << 2)] >> x) & 0x01) << 3) |
- (((src[0x01 | (y << 2)] >> x) & 0x01) << 2) |
- (((src[0x02 | (y << 2)] >> x) & 0x01) << 1) |
- (((src[0x00 | (y << 2)] >> x) & 0x01) << 0);
- }
- }
- }
+ return 0;
}
@@ -740,7 +242,7 @@ UINT16 neogeo_state::get_video_control( )
if (v_counter >= 0x200)
v_counter = v_counter - NEOGEO_VTOTAL;
- ret = (v_counter << 7) | (neogeo_get_auto_animation_counter() & 0x0007);
+ ret = (v_counter << 7) | (m_sprgen->neogeo_get_auto_animation_counter() & 0x0007);
if (VERBOSE) logerror("%s: video_control read (%04x)\n", machine().describe_context(), ret);
@@ -752,8 +254,8 @@ void neogeo_state::set_video_control( UINT16 data )
{
if (VERBOSE) logerror("%s: video control write %04x\n", machine().describe_context(), data);
- set_auto_animation_speed(data >> 8);
- set_auto_animation_disabled(data & 0x0008);
+ m_sprgen->set_auto_animation_speed(data >> 8);
+ m_sprgen->set_auto_animation_disabled(data & 0x0008);
neogeo_set_display_position_interrupt_control(data & 0x00f0);
}
@@ -772,8 +274,8 @@ READ16_MEMBER(neogeo_state::neogeo_video_register_r)
{
default:
case 0x00:
- case 0x01: ret = get_videoram_data(); break;
- case 0x02: ret = get_videoram_modulo(); break;
+ case 0x01: ret = m_sprgen->get_videoram_data(); break;
+ case 0x02: ret = m_sprgen->get_videoram_modulo(); break;
case 0x03: ret = get_video_control(); break;
}
}
@@ -793,9 +295,9 @@ WRITE16_MEMBER(neogeo_state::neogeo_video_register_w)
switch (offset)
{
- case 0x00: set_videoram_offset(data); break;
- case 0x01: set_videoram_data(data); break;
- case 0x02: set_videoram_modulo(data); break;
+ case 0x00: m_sprgen->set_videoram_offset(data); break;
+ case 0x01: m_sprgen->set_videoram_data(data); break;
+ case 0x02: m_sprgen->set_videoram_modulo(data); break;
case 0x03: set_video_control(data); break;
case 0x04: neogeo_set_display_counter_msb(data); break;
case 0x05: neogeo_set_display_counter_lsb(data); break;
@@ -806,93 +308,3 @@ WRITE16_MEMBER(neogeo_state::neogeo_video_register_w)
}
-
-/*************************************
- *
- * Video system start
- *
- *************************************/
-
-void neogeo_state::video_start()
-{
- /* allocate memory not directly mapped */
- m_palettes[0] = auto_alloc_array(machine(), UINT16, NUM_PENS);
- m_palettes[1] = auto_alloc_array(machine(), UINT16, NUM_PENS);
- m_pens = auto_alloc_array(machine(), pen_t, NUM_PENS);
- m_videoram = auto_alloc_array(machine(), UINT16, 0x8000 + 0x800);
-
- /* clear allocated memory */
- memset(m_palettes[0], 0x00, NUM_PENS * sizeof(UINT16));
- memset(m_palettes[1], 0x00, NUM_PENS * sizeof(UINT16));
- memset(m_pens, 0x00, NUM_PENS * sizeof(pen_t));
- memset(m_videoram, 0x00, (0x8000 + 0x800) * sizeof(UINT16));
-
- compute_rgb_weights();
- create_sprite_line_timer();
- create_auto_animation_timer();
-
- m_sprite_gfx_address_mask = 0;
- optimize_sprite_data();
-
- /* initialize values that are not modified on a reset */
- m_vram_offset = 0;
- m_vram_read_buffer = 0;
- m_vram_modulo = 0;
- m_auto_animation_speed = 0;
- m_auto_animation_disabled = 0;
- m_auto_animation_counter = 0;
- m_auto_animation_frame_counter = 0;
-
- /* register for state saving */
- save_pointer(NAME(m_palettes[0]), NUM_PENS);
- save_pointer(NAME(m_palettes[1]), NUM_PENS);
- save_pointer(NAME(m_videoram), 0x8000 + 0x800);
- save_item(NAME(m_vram_offset));
- save_item(NAME(m_vram_read_buffer));
- save_item(NAME(m_vram_modulo));
- save_item(NAME(m_fixed_layer_source));
- save_item(NAME(m_screen_dark));
- save_item(NAME(m_palette_bank));
- save_item(NAME(m_auto_animation_speed));
- save_item(NAME(m_auto_animation_disabled));
- save_item(NAME(m_auto_animation_counter));
- save_item(NAME(m_auto_animation_frame_counter));
-
- machine().save().register_postload(save_prepost_delegate(FUNC(neogeo_state::regenerate_pens), this));
-
- m_region_zoomy = memregion("zoomy")->base();
-}
-
-
-
-/*************************************
- *
- * Video system reset
- *
- *************************************/
-
-void neogeo_state::video_reset()
-{
- start_sprite_line_timer();
- start_auto_animation_timer();
-}
-
-
-
-/*************************************
- *
- * Video update
- *
- *************************************/
-
-UINT32 neogeo_state::screen_update_neogeo(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- // fill with background color first
- bitmap.fill(m_pens[0x0fff], cliprect);
-
- draw_sprites(bitmap, cliprect.min_y);
-
- draw_fixed_layer(bitmap, cliprect.min_y);
-
- return 0;
-}
diff --git a/src/mame/video/neogeo_spr.c b/src/mame/video/neogeo_spr.c
new file mode 100644
index 00000000000..1c6453633ca
--- /dev/null
+++ b/src/mame/video/neogeo_spr.c
@@ -0,0 +1,838 @@
+/* NeoGeo sprites (and fixed text layer) */
+
+#include "emu.h"
+#include "neogeo_spr.h"
+
+
+// pure virtual functions
+//const device_type NEOGEO_SPRITE_BASE = &device_creator<neosprite_base_device>;
+
+/*
+neosprite_base_device::neosprite_base_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, NEOGEO_SPRITE_BASE, "Neogeo Sprites", tag, owner, clock, "neospritebase", __FILE__),
+ m_bppshift(4)
+{
+
+}
+*/
+
+neosprite_base_device::neosprite_base_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock, device_type type)
+ : device_t(mconfig, type, "Neogeo Sprites", tag, owner, clock, "neosprite", __FILE__),
+ m_bppshift(4)
+{
+
+}
+
+void neosprite_base_device::device_start()
+{
+
+ m_videoram = auto_alloc_array(machine(), UINT16, 0x8000 + 0x800);
+ m_videoram_drawsource = m_videoram;
+
+ /* clear allocated memory */
+ memset(m_videoram, 0x00, (0x8000 + 0x800) * sizeof(UINT16));
+
+ create_sprite_line_timer();
+ create_auto_animation_timer();
+
+
+
+ /* initialize values that are not modified on a reset */
+ m_vram_offset = 0;
+ m_vram_read_buffer = 0;
+ m_vram_modulo = 0;
+ m_auto_animation_speed = 0;
+ m_auto_animation_disabled = 0;
+ m_auto_animation_counter = 0;
+ m_auto_animation_frame_counter = 0;
+
+ /* register for state saving */
+ save_pointer(NAME(m_videoram), 0x8000 + 0x800);
+ save_item(NAME(m_vram_offset));
+ save_item(NAME(m_vram_read_buffer));
+ save_item(NAME(m_vram_modulo));
+ save_item(NAME(m_fixed_layer_source));
+
+ save_item(NAME(m_auto_animation_speed));
+ save_item(NAME(m_auto_animation_disabled));
+ save_item(NAME(m_auto_animation_counter));
+ save_item(NAME(m_auto_animation_frame_counter));
+
+
+ m_region_zoomy = memregion(":zoomy")->base();
+}
+
+void neosprite_base_device::device_reset()
+{
+ //m_sprite_gfx_address_mask = 0;
+ optimize_sprite_data();
+
+ start_sprite_line_timer();
+ start_auto_animation_timer();
+}
+
+
+
+/*************************************
+ *
+ * Video RAM access
+ *
+ *************************************/
+
+void neosprite_base_device::set_videoram_offset( UINT16 data )
+{
+ m_vram_offset = (data & 0x8000 ? data & 0x87ff : data);
+
+ /* the read happens right away */
+ m_vram_read_buffer = m_videoram[m_vram_offset];
+}
+
+
+UINT16 neosprite_base_device::get_videoram_data( )
+{
+ return m_vram_read_buffer;
+}
+
+
+void neosprite_base_device::set_videoram_data( UINT16 data)
+{
+ m_videoram[m_vram_offset] = data;
+
+ /* auto increment/decrement the current offset - A15 is NOT affected */
+ set_videoram_offset((m_vram_offset & 0x8000) | ((m_vram_offset + m_vram_modulo) & 0x7fff));
+}
+
+
+void neosprite_base_device::set_videoram_modulo( UINT16 data)
+{
+ m_vram_modulo = data;
+}
+
+
+UINT16 neosprite_base_device::get_videoram_modulo( )
+{
+ return m_vram_modulo;
+}
+
+
+
+/*************************************
+ *
+ * Auto animation
+ *
+ *************************************/
+
+void neosprite_base_device::set_auto_animation_speed( UINT8 data)
+{
+ m_auto_animation_speed = data;
+}
+
+
+void neosprite_base_device::set_auto_animation_disabled( UINT8 data)
+{
+ m_auto_animation_disabled = data;
+}
+
+
+UINT8 neosprite_base_device::neogeo_get_auto_animation_counter( )
+{
+ return m_auto_animation_counter;
+}
+
+
+TIMER_CALLBACK_MEMBER(neosprite_base_device::auto_animation_timer_callback)
+{
+ if (m_auto_animation_frame_counter == 0)
+ {
+ m_auto_animation_frame_counter = m_auto_animation_speed;
+ m_auto_animation_counter += 1;
+ }
+ else
+ m_auto_animation_frame_counter = m_auto_animation_frame_counter - 1;
+
+ m_auto_animation_timer->adjust(m_screen->time_until_pos(NEOGEO_VSSTART));
+}
+
+
+void neosprite_base_device::create_auto_animation_timer( )
+{
+ m_auto_animation_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(neosprite_base_device::auto_animation_timer_callback),this));
+}
+
+
+void neosprite_base_device::start_auto_animation_timer( )
+{
+ m_auto_animation_timer->adjust(m_screen->time_until_pos(NEOGEO_VSSTART));
+}
+
+
+
+/*************************************
+ *
+ * Fixed layer
+ *
+ *************************************/
+
+void neosprite_base_device::neogeo_set_fixed_layer_source( UINT8 data )
+{
+ m_fixed_layer_source = data;
+}
+
+
+void neosprite_base_device::draw_fixed_layer( bitmap_rgb32 &bitmap, int scanline )
+{
+ int x;
+
+ UINT8* gfx_base = m_fixed_layer_source ? m_region_fixed->base() : m_region_fixedbios->base();
+ UINT32 addr_mask = ( m_fixed_layer_source ? m_region_fixed->bytes() : m_region_fixedbios->bytes() ) - 1;
+ UINT16 *video_data = &m_videoram_drawsource[0x7000 | (scanline >> 3)];
+ UINT32 *pixel_addr = &bitmap.pix32(scanline, NEOGEO_HBEND);
+
+ int garouoffsets[32];
+ int banked = m_fixed_layer_source && (addr_mask > 0x1ffff);
+
+ /* thanks to Mr K for the garou & kof2000 banking info */
+ /* Build line banking table for Garou & MS3 before starting render */
+ if (banked && m_fixed_layer_bank_type == 1)
+ {
+ int garoubank = 0;
+ int k = 0;
+ int y = 0;
+ while (y < 32)
+ {
+ if (m_videoram_drawsource[0x7500 + k] == 0x0200 && (m_videoram_drawsource[0x7580 + k] & 0xff00) == 0xff00)
+ {
+ garoubank = m_videoram_drawsource[0x7580 + k] & 3;
+ garouoffsets[y++] = garoubank;
+ }
+ garouoffsets[y++] = garoubank;
+ k += 2;
+ }
+ }
+
+ for (x = 0; x < 40; x++)
+ {
+ UINT16 code_and_palette = *video_data;
+ UINT16 code = code_and_palette & 0x0fff;
+
+ if (banked)
+ {
+ int y = scanline >> 3;
+ switch (m_fixed_layer_bank_type)
+ {
+ case 1:
+ /* Garou, MSlug 3 */
+ code += 0x1000 * (garouoffsets[(y - 2) & 31] ^ 3);
+ break;
+ case 2:
+ code += 0x1000 * (((m_videoram_drawsource[0x7500 + ((y - 1) & 31) + 32 * (x / 6)] >> (5 - (x % 6)) * 2) & 3) ^ 3);
+ break;
+ }
+ }
+
+ {
+ int i;
+ int gfx_offset = ((code << 5) | (scanline & 0x07)) & addr_mask;
+
+ pen_t *char_pens;
+
+ char_pens = &m_pens[code_and_palette >> 12 << m_bppshift];
+
+
+ static const UINT32 pix_offsets[] = { 0x10, 0x18, 0x00, 0x08 };
+
+ for (i = 0; i < 4; i++)
+ {
+ draw_fixed_layer_2pixels(pixel_addr, gfx_offset + pix_offsets[i], gfx_base, char_pens);
+ }
+ }
+
+ video_data = video_data + 0x20;
+ }
+}
+
+
+inline void neosprite_base_device::draw_fixed_layer_2pixels(UINT32*&pixel_addr, int offset, UINT8* gfx_base, pen_t* char_pens)
+{
+ UINT8 data = gfx_base[offset];
+
+ if (data & 0x0f)
+ *pixel_addr = char_pens[data & 0x0f];
+ pixel_addr++;
+
+ if (data & 0xf0)
+ *pixel_addr = char_pens[(data & 0xf0) >> 4];
+ pixel_addr++;
+
+}
+
+/*************************************
+ *
+ * Sprite hardware
+ *
+ *************************************/
+
+#define MAX_SPRITES_PER_SCREEN (381)
+#define MAX_SPRITES_PER_LINE (96)
+
+
+/* horizontal zoom table - verified on real hardware */
+static const int zoom_x_tables[][16] =
+{
+ { 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0 },
+ { 0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0 },
+ { 0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0 },
+ { 0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0 },
+ { 0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0 },
+ { 0,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0 },
+ { 0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0 },
+ { 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0 },
+ { 1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0 },
+ { 1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0 },
+ { 1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1 },
+ { 1,0,1,1,1,0,1,1,1,1,1,0,1,0,1,1 },
+ { 1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1 },
+ { 1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1 },
+ { 1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1 },
+ { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }
+};
+
+
+inline int neosprite_base_device::rows_to_height(int rows)
+{
+ if ((rows == 0) || (rows > 0x20))
+ rows = 0x20;
+
+ return rows * 0x10;
+}
+
+
+inline int neosprite_base_device::sprite_on_scanline(int scanline, int y, int rows)
+{
+ /* check if the current scanline falls inside this sprite,
+ two possible scenerios, wrap around or not */
+ int max_y = (y + rows_to_height(rows) - 1) & 0x1ff;
+
+ return (((max_y >= y) && (scanline >= y) && (scanline <= max_y)) ||
+ ((max_y < y) && ((scanline >= y) || (scanline <= max_y))));
+}
+
+
+
+
+void neosprite_base_device::draw_sprites( bitmap_rgb32 &bitmap, int scanline )
+{
+ int sprite_index;
+ int max_sprite_index;
+
+ int y = 0;
+ int x = 0;
+ int rows = 0;
+ int zoom_y = 0;
+ int zoom_x = 0;
+ UINT16 *sprite_list;
+
+ /* select the active list */
+ if (scanline & 0x01)
+ sprite_list = &m_videoram_drawsource[0x8680];
+ else
+ sprite_list = &m_videoram_drawsource[0x8600];
+
+ /* optimization -- find last non-zero entry and only draw that many +1
+ sprite. This is not 100% correct as the hardware will keep drawing
+ the #0 sprite over and over, but we need the speed */
+ for (max_sprite_index = (MAX_SPRITES_PER_LINE - 1); max_sprite_index >= 0; max_sprite_index--)
+ {
+ if (sprite_list[max_sprite_index] != 0)
+ break;
+ }
+
+ /* add the +1 now, just in case the 0 at the end is real sprite */
+ if (max_sprite_index != (MAX_SPRITES_PER_LINE - 1))
+ max_sprite_index = max_sprite_index + 1;
+
+ for (sprite_index = 0; sprite_index <= max_sprite_index; sprite_index++)
+ {
+ UINT16 sprite_number = sprite_list[sprite_index] & 0x01ff;
+ UINT16 y_control = m_videoram_drawsource[0x8200 | sprite_number];
+ UINT16 zoom_control = m_videoram_drawsource[0x8000 | sprite_number];
+
+ /* if chained, go to next X coordinate and get new X zoom */
+ if (y_control & 0x40)
+ {
+ x = (x + zoom_x + 1) & 0x01ff;
+ zoom_x = (zoom_control >> 8) & 0x0f;
+ }
+ /* new block */
+ else
+ {
+ y = 0x200 - (y_control >> 7);
+ x = m_videoram_drawsource[0x8400 | sprite_number] >> 7;
+
+ zoom_y = (zoom_control & 0xff);
+
+ zoom_x = (zoom_control >> 8) & 0x0f;
+ rows = y_control & 0x3f;
+ }
+
+ /* skip if falls completely outside the screen */
+ if ((x >= 0x140) && (x <= 0x1f0))
+ continue;
+
+ /* double check the Y coordinate, in case somebody modified the sprite coordinate
+ since we buffered it */
+ if (sprite_on_scanline(scanline, y, rows))
+ {
+ int sprite_y;
+ int tile;
+ UINT8 sprite_y_and_tile;
+ offs_t attr_and_code_offs;
+ UINT16 attr;
+ UINT32 code;
+ const int *zoom_x_table;
+ pen_t *line_pens;
+ int x_inc;
+
+ int sprite_line = (scanline - y) & 0x1ff;
+ int zoom_line = sprite_line & 0xff;
+ int invert = sprite_line & 0x100;
+
+ if (invert)
+ zoom_line ^= 0xff;
+
+ if (rows > 0x20)
+ {
+ zoom_line = zoom_line % ((zoom_y + 1) << 1);
+
+ if (zoom_line > zoom_y)
+ {
+ zoom_line = ((zoom_y + 1) << 1) - 1 - zoom_line;
+ invert = !invert;
+ }
+ }
+
+ sprite_y_and_tile = m_region_zoomy[(zoom_y << 8) | zoom_line];
+
+ sprite_y = sprite_y_and_tile & 0x0f;
+ tile = sprite_y_and_tile >> 4;
+
+ if (invert)
+ {
+ sprite_y ^= 0x0f;
+ tile ^= 0x1f;
+ }
+
+ attr_and_code_offs = (sprite_number << 6) | (tile << 1);
+ attr = m_videoram_drawsource[attr_and_code_offs + 1];
+ code = ((attr << 12) & 0x70000) | m_videoram_drawsource[attr_and_code_offs];
+
+ /* substitute auto animation bits */
+ if (!m_auto_animation_disabled)
+ {
+ if (attr & 0x0008)
+ code = (code & ~0x07) | (m_auto_animation_counter & 0x07);
+ else if (attr & 0x0004)
+ code = (code & ~0x03) | (m_auto_animation_counter & 0x03);
+ }
+
+ /* vertical flip? */
+ if (attr & 0x0002)
+ sprite_y ^= 0x0f;
+
+ zoom_x_table = zoom_x_tables[zoom_x];
+
+ /* compute offset in gfx ROM and mask it to the number of bits available */
+ int gfx_base = ((code << 8) | (sprite_y << 4)) & m_sprite_gfx_address_mask;
+
+
+ line_pens = &m_pens[attr >> 8 << m_bppshift];
+
+
+ /* horizontal flip? */
+ if (attr & 0x0001)
+ {
+ gfx_base = gfx_base + 0x0f;
+ x_inc = -1;
+ }
+ else
+ x_inc = 1;
+
+ /* draw the line - no wrap-around */
+ if (x <= 0x01f0)
+ {
+ int i;
+
+ UINT32 *pixel_addr = &bitmap.pix32(scanline, x + NEOGEO_HBEND);
+
+ for (i = 0; i < 0x10; i++)
+ {
+ if (*zoom_x_table)
+ {
+ draw_pixel(gfx_base, pixel_addr, line_pens);
+
+ pixel_addr++;
+ }
+
+ zoom_x_table++;
+ gfx_base += x_inc;
+ }
+ }
+ /* wrap-around */
+ else
+ {
+ int i;
+
+ int x_save = x;
+ UINT32 *pixel_addr = &bitmap.pix32(scanline, NEOGEO_HBEND);
+
+ for (i = 0; i < 0x10; i++)
+ {
+ if (*zoom_x_table)
+ {
+ if (x >= 0x200)
+ {
+ draw_pixel(gfx_base, pixel_addr, line_pens);
+
+ pixel_addr++;
+ }
+
+ x++;
+ }
+
+ zoom_x_table++;
+ gfx_base += x_inc;
+ }
+
+ x = x_save;
+ }
+ }
+ }
+}
+
+
+void neosprite_base_device::parse_sprites( int scanline )
+{
+ UINT16 sprite_number;
+ int y = 0;
+ int rows = 0;
+ UINT16 *sprite_list;
+
+ int active_sprite_count = 0;
+
+ /* select the active list */
+ if (scanline & 0x01)
+ sprite_list = &m_videoram_drawsource[0x8680];
+ else
+ sprite_list = &m_videoram_drawsource[0x8600];
+
+ /* scan all sprites */
+ for (sprite_number = 0; sprite_number < MAX_SPRITES_PER_SCREEN; sprite_number++)
+ {
+ UINT16 y_control = m_videoram_drawsource[0x8200 | sprite_number];
+
+ /* if not chained, get Y position and height, otherwise use previous values */
+ if (~y_control & 0x40)
+ {
+ y = 0x200 - (y_control >> 7);
+ rows = y_control & 0x3f;
+ }
+
+ /* skip sprites with 0 rows */
+ if (rows == 0)
+ continue;
+
+ if (!sprite_on_scanline(scanline, y, rows))
+ continue;
+
+ /* sprite is on this scanline, add it to active list */
+ *sprite_list = sprite_number;
+
+ sprite_list++;
+
+ /* increment sprite count, and if we reached the max, bail out */
+ active_sprite_count++;
+
+ if (active_sprite_count == MAX_SPRITES_PER_LINE)
+ break;
+ }
+
+ /* fill the rest of the sprite list with 0, including one extra entry */
+ memset(sprite_list, 0, sizeof(sprite_list[0]) * (MAX_SPRITES_PER_LINE - active_sprite_count + 1));
+}
+
+
+TIMER_CALLBACK_MEMBER(neosprite_base_device::sprite_line_timer_callback)
+{
+ int scanline = param;
+
+ /* we are at the beginning of a scanline -
+ we need to draw the previous scanline and parse the sprites on the current one */
+ if (scanline != 0)
+ m_screen->update_partial(scanline - 1);
+
+ parse_sprites(scanline);
+
+ /* let's come back at the beginning of the next line */
+ scanline = (scanline + 1) % NEOGEO_VTOTAL;
+
+ m_sprite_line_timer->adjust(m_screen->time_until_pos(scanline), scanline);
+}
+
+
+void neosprite_base_device::create_sprite_line_timer( )
+{
+ m_sprite_line_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(neosprite_base_device::sprite_line_timer_callback),this));
+}
+
+
+void neosprite_base_device::start_sprite_line_timer( )
+{
+ m_sprite_line_timer->adjust(m_screen->time_until_pos(0));
+}
+
+
+UINT32 neosprite_base_device::get_region_mask(memory_region* rgn)
+{
+ /* convert the sprite graphics data into a format that
+ allows faster blitting */
+ UINT32 mask;
+ UINT32 len;
+ UINT32 bit;
+
+ /* get mask based on the length rounded up to the nearest
+ power of 2 */
+ mask = 0xffffffff;
+
+ len = rgn->bytes();
+
+ for (bit = 0x80000000; bit != 0; bit >>= 1)
+ {
+ if ((len * 2 - 1) & bit)
+ break;
+
+ mask >>= 1;
+ }
+
+ return mask;
+}
+
+void neosprite_base_device::optimize_sprite_data()
+{
+ // this does nothing in this implementation, it's used by neosprite_optimized_device
+ // m_sprite_gfx_address_mask gets set when the GFX region is assigned
+ return;
+}
+
+// these are for passing in pointers from the main system
+void neosprite_base_device::set_sprite_region(memory_region* region_sprites)
+{
+ m_region_sprites = region_sprites;
+}
+
+void neosprite_base_device::set_fixed_regions(memory_region* fix_cart, memory_region* fix_bios)
+{
+ m_region_fixed = fix_cart;
+ m_region_fixedbios = fix_bios;
+}
+
+void neosprite_base_device::set_screen(screen_device* screen)
+{
+ m_screen = screen;
+}
+
+void neosprite_base_device::set_pens(pen_t* pens)
+{
+ m_pens = pens;
+}
+
+
+
+/*********************************************************************************************************************************/
+/* Regular NeoGeo sprite handling - drawing directly from ROM (or RAM on NeoCD) */
+/* */
+/* note, we don't currently use this implementation, reference only */
+/* if we do it will be important to ensure that all sprite regions are ^2 sizes - the optimized routine automatically allocates */
+/* ^2 sized regions when pre-decoding, but obviously we don't here, so if we want to be safe we'll have to adjust the actual */
+/* regions (alternatively I could add an additional size check in the draw routine, but that would be slower) */
+/*********************************************************************************************************************************/
+
+const device_type NEOGEO_SPRITE_REGULAR = &device_creator<neosprite_regular_device>;
+
+neosprite_regular_device::neosprite_regular_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : neosprite_base_device(mconfig, tag, owner, clock, NEOGEO_SPRITE_REGULAR)
+{
+
+}
+
+
+
+void neosprite_regular_device::set_sprite_region(memory_region* region_sprites)
+{
+ m_region_sprites = region_sprites;
+
+ UINT32 mask = get_region_mask(m_region_sprites);
+ UINT32 proper_size = (mask + 1) >>1;
+
+ printf("lengths %08x %08x m_region_sprites", m_region_sprites->bytes(), proper_size);
+
+ if (m_region_sprites->bytes() != proper_size)
+ {
+ fatalerror("please use power of 2 region sizes with neosprite_base_device to ensure masking works correctly");
+ }
+
+ m_sprite_gfx_address_mask = mask;
+}
+
+inline void neosprite_regular_device::draw_pixel(int romaddr, UINT32* dst, pen_t *line_pens)
+{
+ const UINT8* src = m_region_sprites->base() + (((romaddr &~0xff)>>1) | (((romaddr&0x8)^0x8)<<3) | ((romaddr & 0xf0) >> 2));
+ const int x = romaddr & 0x7;
+
+ const UINT8 gfx = (((src[0x3] >> x) & 0x01) << 3) |
+ (((src[0x1] >> x) & 0x01) << 2) |
+ (((src[0x2] >> x) & 0x01) << 1) |
+ (((src[0x0] >> x) & 0x01) << 0);
+
+ if (gfx)
+ *dst = line_pens[gfx];
+}
+
+
+
+/*********************************************************************************************************************************/
+/* Regular NeoGeo sprite handling with pre-decode optimization */
+/* */
+/* this is closer to the old MAME implementation where the 4bpp graphics have been expanded to an easier to draw 8bpp format */
+/* for additional speed */
+/*********************************************************************************************************************************/
+
+const device_type NEOGEO_SPRITE_OPTIMZIED = &device_creator<neosprite_optimized_device>;
+
+neosprite_optimized_device::neosprite_optimized_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : neosprite_base_device(mconfig, tag, owner, clock, NEOGEO_SPRITE_OPTIMZIED)
+{
+}
+
+
+void neosprite_optimized_device::optimize_sprite_data()
+{
+ /* convert the sprite graphics data into a format that
+ allows faster blitting */
+ UINT8 *src;
+ UINT8 *dest;
+
+ UINT32 mask = get_region_mask(m_region_sprites);
+
+ m_sprite_gfx.resize(mask + 1);
+ m_sprite_gfx_address_mask = mask;
+
+ src = m_region_sprites->base();
+ dest = m_sprite_gfx;
+
+ for (unsigned i = 0; i < m_region_sprites->bytes(); i += 0x80, src += 0x80)
+ {
+ for (unsigned y = 0; y < 0x10; y++)
+ {
+ for (unsigned x = 0; x < 8; x++)
+ {
+ *(dest++) = (((src[0x43 | (y << 2)] >> x) & 0x01) << 3) |
+ (((src[0x41 | (y << 2)] >> x) & 0x01) << 2) |
+ (((src[0x42 | (y << 2)] >> x) & 0x01) << 1) |
+ (((src[0x40 | (y << 2)] >> x) & 0x01) << 0);
+ }
+
+ for (unsigned x = 0; x < 8; x++)
+ {
+ *(dest++) = (((src[0x03 | (y << 2)] >> x) & 0x01) << 3) |
+ (((src[0x01 | (y << 2)] >> x) & 0x01) << 2) |
+ (((src[0x02 | (y << 2)] >> x) & 0x01) << 1) |
+ (((src[0x00 | (y << 2)] >> x) & 0x01) << 0);
+ }
+ }
+ }
+}
+
+inline void neosprite_optimized_device::draw_pixel(int romaddr, UINT32* dst, pen_t *line_pens)
+{
+ const UINT8 gfx = m_sprite_gfx[romaddr];
+
+ if (gfx)
+ *dst = line_pens[gfx];
+}
+
+
+/*********************************************************************************************************************************/
+/* MIDAS specific sprite handling */
+/* */
+/* this is used by the midas.c hardware which is a reengineered NeoGeo, it has 8bbp tiles instead of 4bpp tiles */
+/* and uploads the zoom table. The additional videoram buffering is a guess because 'hammer' is very glitchy without it */
+/*********************************************************************************************************************************/
+
+const device_type NEOGEO_SPRITE_MIDAS = &device_creator<neosprite_midas_device>;
+
+
+neosprite_midas_device::neosprite_midas_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : neosprite_base_device(mconfig, tag, owner, clock, NEOGEO_SPRITE_MIDAS)
+{
+ m_bppshift = 8;
+}
+
+
+inline void neosprite_midas_device::draw_pixel(int romaddr, UINT32* dst, pen_t *line_pens)
+{
+ const UINT8* src = m_region_sprites->base() + (((romaddr &~0xff)) | (((romaddr&0x8)^0x8)<<4) | ((romaddr & 0xf0) >> 1));
+ const int x = romaddr & 0x7;
+
+ const UINT8 gfx =
+ (((src[0x7] >> x) & 0x01) << 7) |
+ (((src[0x3] >> x) & 0x01) << 6) |
+ (((src[0x6] >> x) & 0x01) << 5) |
+ (((src[0x2] >> x) & 0x01) << 4) |
+ (((src[0x5] >> x) & 0x01) << 3) |
+ (((src[0x1] >> x) & 0x01) << 2) |
+ (((src[0x4] >> x) & 0x01) << 1) |
+ (((src[0x0] >> x) & 0x01) << 0);
+
+ if (gfx)
+ *dst = line_pens[gfx];
+}
+
+
+void neosprite_midas_device::device_start()
+{
+ neosprite_base_device::device_start();
+
+ m_videoram_buffer = auto_alloc_array(machine(), UINT16, 0x8000 + 0x800);
+ m_videoram_drawsource = m_videoram_buffer;
+
+ memset(m_videoram_buffer, 0x00, (0x8000 + 0x800) * sizeof(UINT16));
+
+}
+
+void neosprite_midas_device::buffer_vram()
+{
+ memcpy(m_videoram_buffer, m_videoram, (0x8000 + 0x800) * sizeof(UINT16));
+}
+
+inline void neosprite_midas_device::draw_fixed_layer_2pixels(UINT32*&pixel_addr, int offset, UINT8* gfx_base, pen_t* char_pens)
+{
+ UINT8 data;
+
+ data = ((gfx_base[(offset * 2)+0] & 0x0f)<<0) | ((gfx_base[(offset * 2)+1] & 0x0f)<<4);
+ if (data)
+ *pixel_addr = char_pens[data];
+ pixel_addr++;
+
+ data = ((gfx_base[(offset * 2)+0] & 0xf0)>>4) | ((gfx_base[(offset * 2)+1] & 0xf0)<<0);
+ if (data)
+ *pixel_addr = char_pens[data];
+ pixel_addr++;
+}
+
+void neosprite_midas_device::set_sprite_region(memory_region* region_sprites)
+{
+ m_region_sprites = region_sprites;
+ UINT32 mask = get_region_mask(m_region_sprites);
+ m_sprite_gfx_address_mask = mask;
+}
+
diff --git a/src/mame/video/neogeo_spr.h b/src/mame/video/neogeo_spr.h
new file mode 100644
index 00000000000..48dbead11bf
--- /dev/null
+++ b/src/mame/video/neogeo_spr.h
@@ -0,0 +1,143 @@
+
+#define VERBOSE (0)
+
+// todo, move these back, currently the sprite code needs some of the values tho
+#define NEOGEO_MASTER_CLOCK (24000000)
+#define NEOGEO_MAIN_CPU_CLOCK (NEOGEO_MASTER_CLOCK / 2)
+#define NEOGEO_AUDIO_CPU_CLOCK (NEOGEO_MASTER_CLOCK / 6)
+#define NEOGEO_YM2610_CLOCK (NEOGEO_MASTER_CLOCK / 3)
+#define NEOGEO_PIXEL_CLOCK (NEOGEO_MASTER_CLOCK / 4)
+#define NEOGEO_HTOTAL (0x180)
+#define NEOGEO_HBEND (0x01e) /* this should really be 29.5 */
+#define NEOGEO_HBSTART (0x15e) /* this should really be 349.5 */
+#define NEOGEO_VTOTAL (0x108)
+#define NEOGEO_VBEND (0x010)
+#define NEOGEO_VBSTART (0x0f0)
+#define NEOGEO_VSSTART (0x100)
+
+// todo, sort out what needs to be public and make the rest private/protected
+class neosprite_base_device : public device_t
+{
+public:
+ neosprite_base_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock, device_type type);
+// neosprite_base_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual void optimize_sprite_data();
+ virtual void draw_fixed_layer_2pixels(UINT32*&pixel_addr, int offset, UINT8* gfx_base, pen_t* char_pens);
+ void draw_fixed_layer( bitmap_rgb32 &bitmap, int scanline );
+ void set_videoram_offset( UINT16 data );
+ UINT16 get_videoram_data( );
+ void set_videoram_data( UINT16 data);
+ void set_videoram_modulo( UINT16 data);
+ UINT16 get_videoram_modulo( );
+ void set_auto_animation_speed( UINT8 data);
+ void set_auto_animation_disabled( UINT8 data);
+ UINT8 neogeo_get_auto_animation_counter( );
+ void create_auto_animation_timer( );
+ void start_auto_animation_timer( );
+ void neogeo_set_fixed_layer_source( UINT8 data );
+ inline int rows_to_height(int rows);
+ inline int sprite_on_scanline(int scanline, int y, int rows);
+ virtual void draw_pixel(int romaddr, UINT32* dst, pen_t *line_pens) = 0;
+ void draw_sprites( bitmap_rgb32 &bitmap, int scanline );
+ void parse_sprites( int scanline );
+ void create_sprite_line_timer( );
+ void start_sprite_line_timer( );
+ virtual void set_sprite_region(memory_region* region_sprites);
+ void set_fixed_regions(memory_region* fix_cart, memory_region* fix_bios);
+ void set_screen(screen_device* screen);
+ void set_pens(pen_t* pens);
+
+ UINT16 *m_videoram;
+ UINT16 *m_videoram_drawsource;
+
+ UINT16 m_vram_offset;
+ UINT16 m_vram_read_buffer;
+ UINT16 m_vram_modulo;
+
+ const UINT8 *m_region_zoomy;
+
+ UINT32 m_sprite_gfx_address_mask;
+
+ UINT8 m_auto_animation_speed;
+ UINT8 m_auto_animation_disabled;
+ UINT8 m_auto_animation_counter;
+ UINT8 m_auto_animation_frame_counter;
+
+ UINT8 m_fixed_layer_source;
+ UINT8 m_fixed_layer_bank_type;
+
+ emu_timer *m_auto_animation_timer;
+ emu_timer *m_sprite_line_timer;
+
+ TIMER_CALLBACK_MEMBER(auto_animation_timer_callback);
+ TIMER_CALLBACK_MEMBER(sprite_line_timer_callback);
+
+
+ int m_bppshift; // 4 for 4bpp gfx (NeoGeo) 8 for 8bpp gfx (Midas)
+
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+ UINT32 get_region_mask(memory_region* rgn);
+ memory_region* m_region_sprites;
+ memory_region* m_region_fixed;
+ memory_region* m_region_fixedbios;
+ screen_device* m_screen;
+ pen_t *m_pens;
+
+private:
+
+};
+
+//extern const device_type NEOGEO_SPRITE_BASE;
+
+
+class neosprite_regular_device : public neosprite_base_device
+{
+public:
+ neosprite_regular_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual void draw_pixel(int romaddr, UINT32* dst, pen_t *line_pens);
+ virtual void set_sprite_region(memory_region* region_sprites);
+
+};
+
+extern const device_type NEOGEO_SPRITE_REGULAR;
+
+
+class neosprite_optimized_device : public neosprite_base_device
+{
+public:
+ neosprite_optimized_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual void optimize_sprite_data();
+ virtual void draw_pixel(int romaddr, UINT32* dst, pen_t *line_pens);
+ dynamic_array<UINT8> m_sprite_gfx;
+
+};
+
+extern const device_type NEOGEO_SPRITE_OPTIMZIED;
+
+
+
+
+
+class neosprite_midas_device : public neosprite_base_device
+{
+public:
+ neosprite_midas_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual void draw_pixel(int romaddr, UINT32* dst, pen_t *line_pens);
+
+ UINT16* m_videoram_buffer;
+ void buffer_vram();
+ virtual void draw_fixed_layer_2pixels(UINT32*&pixel_addr, int offset, UINT8* gfx_base, pen_t* char_pens);
+ virtual void set_sprite_region(memory_region* region_sprites);
+
+ protected:
+ virtual void device_start();
+
+};
+
+extern const device_type NEOGEO_SPRITE_MIDAS;
+
+