diff options
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 |
commit | 1a9ed9ebe857c3df11176a7509ebd389df863d99 (patch) | |
tree | 237d2763c564a38205262c351d3c6ba81c651c4f /src/mame | |
parent | 36ad612f608726a3981bdc3d8f85db27a3304e26 (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.c | 269 | ||||
-rw-r--r-- | src/mame/drivers/neogeo.c | 80 | ||||
-rw-r--r-- | src/mame/includes/neogeo.h | 71 | ||||
-rw-r--r-- | src/mame/mame.mak | 1 | ||||
-rw-r--r-- | src/mame/video/neogeo.c | 654 | ||||
-rw-r--r-- | src/mame/video/neogeo_spr.c | 838 | ||||
-rw-r--r-- | src/mame/video/neogeo_spr.h | 143 |
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; + + |