Converted Desert Assault to use generic deco sprite implementation [David Haywood]

This commit is contained in:
Angelo Salese 2012-01-29 14:04:52 +00:00
parent 436a0164ac
commit 27ff7623c3
8 changed files with 123 additions and 220 deletions

View File

@ -88,6 +88,7 @@
#include "sound/okim6295.h"
#include "video/deco16ic.h"
#include "video/decocomn.h"
#include "video/decospr.h"
static ADDRESS_MAP_START( boogwing_map, AS_PROGRAM, 16 )
AM_RANGE(0x000000, 0x0fffff) AM_ROM
@ -361,11 +362,19 @@ static MACHINE_CONFIG_START( boogwing, boogwing_state )
MCFG_PALETTE_LENGTH(2048)
MCFG_GFXDECODE(boogwing)
MCFG_VIDEO_START(boogwing)
MCFG_DECOCOMN_ADD("deco_common", boogwing_decocomn_intf)
MCFG_DECO16IC_ADD("tilegen1", boogwing_deco16ic_tilegen1_intf)
MCFG_DECO16IC_ADD("tilegen2", boogwing_deco16ic_tilegen2_intf)
MCFG_DEVICE_ADD("spritegen1", DECO_SPRITE, 0)
decospr_device::set_gfx_region(*device, 3);
MCFG_DEVICE_ADD("spritegen2", DECO_SPRITE, 0)
decospr_device::set_gfx_region(*device, 4);
/* sound hardware */
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")

View File

@ -4,11 +4,6 @@
Desert Assault (c) 1991 Data East Corporation (USA 4 players)
Desert Assault (c) 1991 Data East Corporation (USA 2 players)
I'm not sure if one of the alpha blending effects is correct (mode 0x8000,
the usual mode 0x4000 should be correct). It may be some kind of orthogonal
priority effect where it should cut a hole in other higher priority sprites
to reveal a non-alpha'd hole, or alpha against a further back tilemap.
Emulation by Bryan McPhail, mish@tendril.co.uk
@ -130,6 +125,7 @@ Dip locations verified with US conversion kit manual.
#include "sound/okim6295.h"
#include "video/deco16ic.h"
#include "video/decocomn.h"
#include "video/decospr.h"
/**********************************************************************************/
@ -505,8 +501,8 @@ static GFXDECODE_START( dassault )
GFXDECODE_ENTRY( "gfx2", 0, charlayout, 0, 32 ) /* Characters 8x8 */
GFXDECODE_ENTRY( "gfx2", 0, tilelayout, 0, 32 ) /* Tiles 16x16 */
GFXDECODE_ENTRY( "gfx3", 0, tilelayout, 512, 32 ) /* Tiles 16x16 */
GFXDECODE_ENTRY( "gfx4", 0, tilelayout, 1024, 64 ) /* Sprites 16x16 */
GFXDECODE_ENTRY( "gfx5", 0, tilelayout, 2048, 64 ) /* Sprites 16x16 */
GFXDECODE_ENTRY( "gfx4", 0, tilelayout, 0/*1024*/, 64 ) /* Sprites 16x16 */
GFXDECODE_ENTRY( "gfx5", 0, tilelayout, 0/*2048*/, 64 ) /* Sprites 16x16 */
GFXDECODE_END
/**********************************************************************************/
@ -582,7 +578,8 @@ static MACHINE_CONFIG_START( dassault, dassault_state )
MCFG_CPU_ADD("audiocpu", H6280,32220000/8) /* Accurate */
MCFG_CPU_PROGRAM_MAP(sound_map)
MCFG_QUANTUM_TIME(attotime::from_hz(8400)) /* 140 CPU slices per frame */
// MCFG_QUANTUM_TIME(attotime::from_hz(8400)) /* 140 CPU slices per frame */
MCFG_QUANTUM_PERFECT_CPU("maincpu") // I was seeing random lockups.. let's see if this helps
/* video hardware */
MCFG_VIDEO_ATTRIBUTES(VIDEO_BUFFERS_SPRITERAM)
@ -594,6 +591,8 @@ static MACHINE_CONFIG_START( dassault, dassault_state )
MCFG_SCREEN_VISIBLE_AREA(0*8, 40*8-1, 1*8, 31*8-1)
MCFG_SCREEN_UPDATE_STATIC(dassault)
MCFG_VIDEO_START(dassault)
MCFG_GFXDECODE(dassault)
MCFG_PALETTE_LENGTH(4096)
@ -602,6 +601,13 @@ static MACHINE_CONFIG_START( dassault, dassault_state )
MCFG_DECO16IC_ADD("tilegen1", dassault_deco16ic_tilegen1_intf)
MCFG_DECO16IC_ADD("tilegen2", dassault_deco16ic_tilegen2_intf)
MCFG_DEVICE_ADD("spritegen1", DECO_SPRITE, 0)
decospr_device::set_gfx_region(*device, 3);
MCFG_DEVICE_ADD("spritegen2", DECO_SPRITE, 0)
decospr_device::set_gfx_region(*device, 4);
/* sound hardware */
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
@ -825,27 +831,6 @@ ROM_END
/**********************************************************************************/
static READ16_HANDLER( dassault_main_skip )
{
dassault_state *state = space->machine().driver_data<dassault_state>();
int ret = state->m_ram[0];
if (cpu_get_previouspc(&space->device()) == 0x1170 && ret & 0x8000)
device_spin_until_interrupt(&space->device());
return ret;
}
static READ16_HANDLER( thndzone_main_skip )
{
dassault_state *state = space->machine().driver_data<dassault_state>();
int ret = state->m_ram[0];
if (cpu_get_pc(&space->device()) == 0x114c && ret & 0x8000)
device_spin_until_interrupt(&space->device());
return ret;
}
static DRIVER_INIT( dassault )
{
@ -862,9 +847,6 @@ static DRIVER_INIT( dassault )
memcpy(dst + 0x110000, src + 0x10000, 0x10000);
auto_free(machine, tmp);
/* Save time waiting on vblank bit */
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x3f8000, 0x3f8001, FUNC(dassault_main_skip));
}
static DRIVER_INIT( thndzone )
@ -882,9 +864,6 @@ static DRIVER_INIT( thndzone )
memcpy(dst + 0x110000, src + 0x10000, 0x10000);
auto_free(machine, tmp);
/* Save time waiting on vblank bit */
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x3f8000, 0x3f8001, FUNC(thndzone_main_skip));
}
/**********************************************************************************/

View File

@ -40,5 +40,6 @@ public:
/*----------- defined in video/boogwing.c -----------*/
VIDEO_START( boogwing );
SCREEN_UPDATE_RGB32( boogwing );

View File

@ -42,4 +42,5 @@ public:
/*----------- defined in video/dassault.c -----------*/
VIDEO_START(dassault);
SCREEN_UPDATE_RGB32( dassault );

View File

@ -2,6 +2,7 @@
#include "includes/boogwing.h"
#include "video/deco16ic.h"
#include "video/decocomn.h"
#include "video/decospr.h"
static void draw_sprites( running_machine &machine, bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16* spriteram_base, int gfx_region )
{
@ -138,12 +139,21 @@ static void draw_sprites( running_machine &machine, bitmap_rgb32 &bitmap, const
}
}
VIDEO_START( boogwing )
{
machine.device<decospr_device>("spritegen1")->alloc_sprite_bitmap();
machine.device<decospr_device>("spritegen2")->alloc_sprite_bitmap();
}
SCREEN_UPDATE_RGB32( boogwing )
{
boogwing_state *state = screen.machine().driver_data<boogwing_state>();
UINT16 flip = deco16ic_pf_control_r(state->m_deco_tilegen1, 0, 0xffff);
UINT16 priority = decocomn_priority_r(state->m_decocomn, 0, 0xffff);
screen.machine().device<decospr_device>("spritegen2")->draw_sprites(bitmap, cliprect, screen.machine().generic.buffered_spriteram2.u16, 0x400, true);
screen.machine().device<decospr_device>("spritegen1")->draw_sprites(bitmap, cliprect, screen.machine().generic.buffered_spriteram.u16, 0x400, true);
flip_screen_set(screen.machine(), BIT(flip, 7));
deco16ic_pf_update(state->m_deco_tilegen1, state->m_pf1_rowscroll, state->m_pf2_rowscroll);
deco16ic_pf_update(state->m_deco_tilegen2, state->m_pf3_rowscroll, state->m_pf4_rowscroll);
@ -184,6 +194,8 @@ SCREEN_UPDATE_RGB32( boogwing )
draw_sprites(screen.machine(), bitmap, cliprect, screen.machine().generic.buffered_spriteram.u16, 3);
draw_sprites(screen.machine(), bitmap, cliprect, screen.machine().generic.buffered_spriteram2.u16, 4);
// screen.machine().device<decospr_device>("spritegen1")->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0000, 0x0000, 0x500, 0x1ff);
// screen.machine().device<decospr_device>("spritegen2")->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0000, 0x0000, 0x700, 0xff);
deco16ic_tilemap_1_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 0);
return 0;

View File

@ -2,190 +2,95 @@
Desert Assault Video emulation - Bryan McPhail, mish@tendril.co.uk
I'm not sure if one of the alpha blending effects is correct (mode 0x8000,
the usual mode 0x4000 should be correct). It may be some kind of orthogonal
priority effect where it should cut a hole in other higher priority sprites
to reveal a non-alpha'd hole, or alpha against a further back tilemap.
(is this the helicopter shadow at the end of lv.1 ?)
Also, some priorities are still a little questionable.
****************************************************************************/
#include "emu.h"
#include "video/deco16ic.h"
#include "includes/dassault.h"
#include "video/decocomn.h"
#include "video/decospr.h"
/******************************************************************************/
static void draw_sprites( running_machine& machine, bitmap_rgb32 &bitmap, const rectangle &cliprect, int pf_priority )
VIDEO_START(dassault)
{
dassault_state *state = machine.driver_data<dassault_state>();
UINT16 *buffered_spriteram = machine.generic.buffered_spriteram.u16;
int x, y, sprite, colour, multi, fx, fy, inc, flash, mult;
int offs, bank, gfxbank;
const UINT16 *spritebase;
machine.device<decospr_device>("spritegen1")->alloc_sprite_bitmap();
machine.device<decospr_device>("spritegen2")->alloc_sprite_bitmap();
}
/* Have to loop over the two sprite sources */
for (bank = 0; bank < 2; bank++)
static void mixdassaultlayer(running_machine &machine, bitmap_rgb32 &bitmap, bitmap_ind16* sprite_bitmap, const rectangle &cliprect, UINT16 pri, UINT16 primask, UINT16 penbase, UINT8 alpha)
{
int y, x;
const pen_t *paldata = machine.pens;
UINT16* srcline;
UINT32* dstline;
for (y=cliprect.min_y;y<=cliprect.max_y;y++)
{
for (offs = 0x800 - 4; offs >= 0; offs -= 4)
srcline=&sprite_bitmap->pix16(y,0);
dstline=&bitmap.pix32(y,0);
for (x=cliprect.min_x;x<=cliprect.max_x;x++)
{
int alpha = 0xff, pmask = 0;
UINT16 pix = srcline[x];
/* Draw the main spritebank after the other one */
if (bank == 0)
{
spritebase = buffered_spriteram;
gfxbank = 3;
}
else
{
spritebase = machine.generic.buffered_spriteram2.u16;
gfxbank = 4;
}
sprite = spritebase[offs + 1] & 0x7fff;
if (!sprite)
if ((pix & primask) != pri)
continue;
x = spritebase[offs + 2];
/* Alpha on chip 2 only */
if (bank == 1 && x & 0xc000)
alpha = 0x80;
y = spritebase[offs];
flash = y & 0x1000;
if (flash && (machine.primary_screen->frame_number() & 1))
continue;
colour = (x >> 9) & 0x1f;
if (y & 0x8000)
colour += 32;
fx = y & 0x2000;
fy = y & 0x4000;
multi = (1 << ((y & 0x0600) >> 9)) - 1; /* 1x, 2x, 4x, 8x height */
x = x & 0x01ff;
y = y & 0x01ff;
if (x >= 320) x -= 512;
if (y >= 256) y -= 512;
x = 304 - x;
y = 240 - y;
if (x > 320)
continue; /* Speedup */
sprite &= ~multi;
if (fy)
inc = -1;
else
if (pix&0xf)
{
sprite += multi;
inc = 1;
}
if (flip_screen_get(machine))
{
y = 240 - y;
x = 304 - x;
if (fx) fx = 0; else fx = 1;
if (fy) fy = 0; else fy = 1;
mult = 16;
}
else mult = -16;
/* Priority */
switch (pf_priority & 3)
{
case 0:
if (bank == 0)
{
switch (spritebase[offs+2]&0xc000)
UINT16 pen = pix&0x1ff;
if (pix & 0x800) pen += 0x200;
if (alpha!=0xff)
{
if (pix&0x600)
{
case 0xc000: pmask = 1; break;
case 0x8000: pmask = 8; break;
case 0x4000: pmask = 32; break;
case 0x0000: pmask = 128; break;
UINT32 base = dstline[x];
dstline[x] = alpha_blend_r32(base, paldata[pen+penbase], alpha);
}
else
{
dstline[x] = paldata[pen+penbase];
}
}
else
{
if (spritebase[offs + 2] & 0x8000)
pmask = 64; /* Check */
else
pmask = 64;
dstline[x] = paldata[pen+penbase];
}
break;
case 1:
if (bank == 0)
{
switch (spritebase[offs + 2] & 0xc000)
{
case 0xc000: pmask = 1; break;
case 0x8000: pmask = 8; break;
case 0x4000: pmask = 32; break;
case 0x0000: pmask = 128; break;
}
}
else
{
if (spritebase[offs + 2] & 0x8000)
pmask = 16; /* Check */
else
pmask = 16;
}
break;
case 2: /* Unused */
case 3:
if (bank == 0)
{
switch (spritebase[offs + 2] & 0xc000)
{
case 0xc000: pmask = 1; break;
case 0x8000: pmask = 8; break;
case 0x4000: pmask = 32; break;
case 0x0000: pmask = 128; break;
}
}
else
{
if (spritebase[offs + 2] & 0x8000)
pmask = 64; /* Check */
else
pmask = 64;
}
break;
}
while (multi >= 0)
{
decocomn_pdrawgfx(
state->m_decocomn,
bitmap,cliprect,machine.gfx[gfxbank],
sprite - multi * inc,
colour,
fx, fy,
x, y + mult * multi,
0, pmask, 1 << bank, 1, alpha);
multi--;
}
}
}
}
/******************************************************************************/
/* are the priorities 100% correct? they're the same as they were before conversion to DECO52 sprite device, but if (for example) you walk to the side of the crates in the first part of the game you appear over them... */
SCREEN_UPDATE_RGB32( dassault )
{
dassault_state *state = screen.machine().driver_data<dassault_state>();
UINT16 flip = deco16ic_pf_control_r(state->m_deco_tilegen1, 0, 0xffff);
UINT16 priority = decocomn_priority_r(state->m_decocomn, 0, 0xffff);
screen.machine().device<decospr_device>("spritegen2")->draw_sprites(bitmap, cliprect, screen.machine().generic.buffered_spriteram2.u16, 0x400, false);
screen.machine().device<decospr_device>("spritegen1")->draw_sprites(bitmap, cliprect, screen.machine().generic.buffered_spriteram.u16, 0x400, false);
bitmap_ind16* sprite_bitmap1 = &screen.machine().device<decospr_device>("spritegen1")->get_sprite_temp_bitmap();
bitmap_ind16* sprite_bitmap2 = &screen.machine().device<decospr_device>("spritegen2")->get_sprite_temp_bitmap();
/* Update tilemaps */
flip_screen_set(screen.machine(), BIT(flip, 7));
deco16ic_pf_update(state->m_deco_tilegen1, 0, state->m_pf2_rowscroll);
deco16ic_pf_update(state->m_deco_tilegen2, 0, state->m_pf4_rowscroll);
/* Draw playfields/update priority bitmap */
decocomn_clear_sprite_priority_bitmap(state->m_decocomn);
screen.machine().priority_bitmap.fill(0, cliprect);
bitmap.fill(screen.machine().pens[3072], cliprect);
deco16ic_tilemap_2_draw(state->m_deco_tilegen2, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0);
@ -193,26 +98,40 @@ SCREEN_UPDATE_RGB32( dassault )
/* The middle playfields can be swapped priority-wise */
if ((priority & 3) == 0)
{
deco16ic_tilemap_2_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 2);
deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, 0, 16);
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0600, 0x0600, 0x400, 0xff); // 1
deco16ic_tilemap_2_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 2); // 2
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0400, 0x0600, 0x400, 0xff); // 8
deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, 0, 16); // 16
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0200, 0x0600, 0x400, 0xff); // 32
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap2, cliprect, 0x0000, 0x0000, 0x800, 0x80); // 64?
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0000, 0x0600, 0x400, 0xff); // 128
}
else if ((priority & 3) == 1)
{
deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, 0, 2);
deco16ic_tilemap_2_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 64);
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0600, 0x0600, 0x400, 0xff); // 1
deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, 0, 2); // 2
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0400, 0x0600, 0x400, 0xff); // 8
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap2, cliprect, 0x0000, 0x0000, 0x800, 0x80); // 16?
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0200, 0x0600, 0x400, 0xff); // 32
deco16ic_tilemap_2_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 64); // 64
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0000, 0x0600, 0x400, 0xff); // 128
}
else if ((priority & 3) == 3)
{
deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, 0, 2);
deco16ic_tilemap_2_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 16);
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0600, 0x0600, 0x400, 0xff); // 1
deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, 0, 2); // 2
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0400, 0x0600, 0x400, 0xff); // 8
deco16ic_tilemap_2_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 16); // 16
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0200, 0x0600, 0x400, 0xff); // 32
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap2, cliprect, 0x0000, 0x0000, 0x800, 0x80); // 64?
mixdassaultlayer(screen.machine(), bitmap, sprite_bitmap1, cliprect, 0x0000, 0x0600, 0x400, 0xff); // 128
}
else
{
/* Unused */
}
/* Draw sprites - two sprite generators, with selectable priority */
draw_sprites(screen.machine(), bitmap, cliprect, priority);
deco16ic_tilemap_1_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 0);
return 0;
}

View File

@ -31,11 +31,10 @@
lemmings.c
deco32.c
rohga.c
dassault.c
to convert:
dassault.c - complex video mixing
boogwing.c - complex video mixing
notes:

View File

@ -131,16 +131,8 @@ static void mixwizdfirelayer(running_machine &machine, bitmap_rgb32 &bitmap, con
bitmap_ind16* sprite_bitmap;
int penbase;
if (gfxregion==3)
{
sprite_bitmap = &machine.device<decospr_device>("spritegen1")->get_sprite_temp_bitmap();
penbase = 0x400;
}
else
{
sprite_bitmap = &machine.device<decospr_device>("spritegen2")->get_sprite_temp_bitmap();
penbase = 0x600;
}
sprite_bitmap = &machine.device<decospr_device>("spritegen2")->get_sprite_temp_bitmap();
penbase = 0x600;
UINT16* srcline;
UINT32* dstline;
@ -161,25 +153,16 @@ static void mixwizdfirelayer(running_machine &machine, bitmap_rgb32 &bitmap, con
if (pix&0xf)
{
UINT16 pen = pix&0x1ff;
if (gfxregion==3)
{
dstline[x] = paldata[pen+penbase];
if (pen&0x100)
{
UINT32 base = dstline[x];
pen &=0xff;
dstline[x] = alpha_blend_r32(base, paldata[pen+penbase], 0x80);
}
else
{
if (pen&0x100)
{
UINT32 base = dstline[x];
pen &=0xff;
dstline[x] = alpha_blend_r32(base, paldata[pen+penbase], 0x80);
}
else
{
dstline[x] = paldata[pen+penbase];
}
dstline[x] = paldata[pen+penbase];
}
}
}
@ -205,16 +188,16 @@ SCREEN_UPDATE_RGB32( wizdfire )
bitmap.fill(screen.machine().pens[512], cliprect);
deco16ic_tilemap_2_draw(state->m_deco_tilegen2, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0);
mixwizdfirelayer(screen.machine(), bitmap, cliprect, 3, 0x600,0x600);
screen.machine().device<decospr_device>("spritegen1")->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0600, 0x0600, 0x400, 0x1ff);
deco16ic_tilemap_2_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 0);
mixwizdfirelayer(screen.machine(), bitmap, cliprect, 3, 0x400,0x600);
screen.machine().device<decospr_device>("spritegen1")->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0400, 0x0600, 0x400, 0x1ff);
if ((priority & 0x1f) == 0x1f) /* Wizdfire has bit 0x40 always set, Dark Seal 2 doesn't?! */
deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, TILEMAP_DRAW_ALPHA(0x80), 0);
else
deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, 0, 0);
mixwizdfirelayer(screen.machine(), bitmap, cliprect, 3, 0x000,0x400); // 0x000 and 0x200 of 0x600
screen.machine().device<decospr_device>("spritegen1")->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0000, 0x0400, 0x400, 0x1ff); // 0x000 and 0x200 of 0x600
mixwizdfirelayer(screen.machine(), bitmap, cliprect, 4, 0x000, 0x000);