start making the mixer a reusable device (nw)

This commit is contained in:
David Haywood 2014-05-22 18:56:49 +00:00
parent a8a523a151
commit fbaaffefb8
7 changed files with 343 additions and 212 deletions

2
.gitattributes vendored
View File

@ -7532,6 +7532,8 @@ src/mame/video/tc0480scp.h svneol=native#text/plain
src/mame/video/tceptor.c svneol=native#text/plain
src/mame/video/tecmo.c svneol=native#text/plain
src/mame/video/tecmo16.c svneol=native#text/plain
src/mame/video/tecmo_mix.c svneol=native#text/plain
src/mame/video/tecmo_mix.h svneol=native#text/plain
src/mame/video/tecmo_spr.c svneol=native#text/plain
src/mame/video/tecmo_spr.h svneol=native#text/plain
src/mame/video/tecmosys.c svneol=native#text/plain

View File

@ -432,6 +432,11 @@ static MACHINE_CONFIG_START( spbactn, spbactn_state )
MCFG_DEVICE_ADD("spritegen", TECMO_SPRITE, 0)
MCFG_TECMO_SPRITE_GFX_REGION(2)
MCFG_DEVICE_ADD("mixer", TECMO_MIXER, 0)
MCFG_TECMO_MIXER_SHIFTS(8,10,4)
MCFG_TECMO_MIXER_BLENDCOLS( 0x0000 + 0x300, 0x0000 + 0x200, 0x0000 + 0x100, 0x0000 + 0x000 )
MCFG_TECMO_MIXER_REGULARCOLS( 0x0800 + 0x300, 0x0800 + 0x200, 0x0800 + 0x100, 0x0800 + 0x000 )
MCFG_TECMO_MIXER_BLENDSOUCE( 0x1000 + 0x000, 0x1000 + 0x100)
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
@ -477,7 +482,11 @@ static MACHINE_CONFIG_START( spbactnp, spbactn_state )
MCFG_DEVICE_ADD("spritegen", TECMO_SPRITE, 0)
MCFG_TECMO_SPRITE_GFX_REGION(2)
//MCFG_TECMO_SPRITE_ALT_FORMAT
MCFG_DEVICE_ADD("mixer", TECMO_MIXER, 0)
MCFG_TECMO_MIXER_SHIFTS(12,14,8)
MCFG_TECMO_MIXER_BLENDCOLS( 0x0000 + 0x300, 0x0000 + 0x200, 0x0000 + 0x100, 0x0000 + 0x000 )
MCFG_TECMO_MIXER_REGULARCOLS( 0x0800 + 0x300, 0x0800 + 0x200, 0x0800 + 0x100, 0x0800 + 0x000 )
MCFG_TECMO_MIXER_BLENDSOUCE( 0x1000 + 0x000, 0x1000 + 0x100)
/* sound hardware - different? */
MCFG_SPEAKER_STANDARD_MONO("mono")

View File

@ -1,5 +1,6 @@
#include "video/tecmo_spr.h"
#include "video/tecmo_mix.h"
class spbactn_state : public driver_device
{
@ -16,7 +17,8 @@ public:
m_gfxdecode(*this, "gfxdecode"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_sprgen(*this, "spritegen")
m_sprgen(*this, "spritegen"),
m_mixer(*this, "mixer")
{ }
required_shared_ptr<UINT16> m_bgvideoram;
@ -77,4 +79,8 @@ public:
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
required_device<tecmo_spr_device> m_sprgen;
required_device<tecmo_mix_device> m_mixer;
};

View File

@ -1979,6 +1979,7 @@ $(MAMEOBJ)/technos.a: \
$(MAMEOBJ)/tehkan.a: \
$(VIDEO)/tecmo_spr.o \
$(VIDEO)/tecmo_mix.o \
$(DRIVERS)/bombjack.o $(VIDEO)/bombjack.o \
$(DRIVERS)/gaiden.o $(VIDEO)/gaiden.o \
$(DRIVERS)/lvcards.o $(VIDEO)/lvcards.o \

View File

@ -127,216 +127,8 @@ int spbactn_state::draw_video(screen_device &screen, bitmap_rgb32 &bitmap, const
m_bg_tilemap->draw(screen, m_tile_bitmap_bg, cliprect, 0, 0);
m_fg_tilemap->draw(screen, m_tile_bitmap_fg, cliprect, 0, 0);
//int frame = (screen.frame_number()) & 1;
// note this game has no tx layer, comments relate to other drivers
// mixer shifts
int sprpri_shift;
int sprbln_shift;
int sprcol_shift;
// when the blend bit is specified in the attribute the source blend palette for that sprite / fg pixel comes from these offsets instead
int sprblend_source = 0x1000 + 0x000;
int fgblend_source = 0x1000 + 0x100;
// the second blend component depends on the pixel we are blending with, the following palettes get used instead of the regular ones
int bgblend_comp = 0x0000 + 0x300;
// int fgblend_comp = 0x0000 + 0x200;
// int txblend_comp = 0x0000 + 0x100; // not used by this game
int spblend_comp = 0x0000 + 0x000;
// otherwise the regular palettes are
int bgregular_comp = 0x0800 + 0x300;
int fgregular_comp = 0x0800 + 0x200;
// int txregular_comp = 0x0800 + 0x100; // not used by this game
int spregular_comp = 0x0800 + 0x000;
if (!alt_sprites) // regular spba
{
sprpri_shift = 8;
sprbln_shift = 10;
sprcol_shift = 4;
}
else // proto spba
{
sprpri_shift = 12;
sprbln_shift = 14;
sprcol_shift = 8;
}
int y, x;
const pen_t *paldata = m_palette->pens();
for (y = cliprect.min_y; y <= cliprect.max_y; y++)
{
UINT32 *dd = &bitmap.pix32(y);
UINT16 *sd2 = &m_sprite_bitmap.pix16(y);
UINT16 *fg = &m_tile_bitmap_fg.pix16(y);
UINT16 *bg = &m_tile_bitmap_bg.pix16(y);
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
{
UINT16 sprpixel = (sd2[x]);
UINT16 sprpri = (sprpixel >> sprpri_shift) & 0x3;
UINT16 sprbln = (sprpixel >> sprbln_shift) & 0x1;
UINT16 sprcol = (sprpixel >> sprcol_shift) & 0xf;
sprpixel = (sprpixel & 0xf) | (sprcol << 4);
//sprpixel &= 0xff;
UINT16 fgpixel = (fg[x]);
UINT16 fgbln = (fgpixel & 0x0100) >> 8;
fgpixel &= 0xff;
UINT16 bgpixel = (bg[x]);
bgpixel &= 0xff;
if (sprpixel&0xf)
{
switch (sprpri)
{
case 0: // behind all
if (fgpixel & 0xf) // is the fg used?
{
if (fgbln)
{
dd[x] = rand();
}
else
{
// solid FG
dd[x] = paldata[fgpixel + fgregular_comp];
}
}
else if (bgpixel & 0x0f)
{
// solid BG
dd[x] = paldata[bgpixel + bgregular_comp];
}
else
{
if (sprbln)
{ // sprite is blended with bgpen?
dd[x] = rand();
}
else
{
// solid sprite
dd[x] = paldata[sprpixel + spregular_comp];
}
}
break;
case 1: // above bg, behind tx, fg
if (fgpixel & 0xf) // is the fg used?
{
if (fgbln)
{
if (sprbln)
{
// needs if bgpixel & 0xf check?
// fg is used and blended with sprite, sprite is used and blended with bg? -- used on 'trail' of ball when ball is under the transparent area
dd[x] = paldata[bgpixel + bgblend_comp] + paldata[sprpixel + sprblend_source]; // WRONG??
}
else
{
// fg is used and blended with opaque sprite
dd[x] = paldata[fgpixel + fgblend_source] + paldata[sprpixel + spblend_comp];
}
}
else
{
// fg is used and opaque
dd[x] = paldata[fgpixel + fgregular_comp];
}
}
else
{
if (sprbln)
{
// needs if bgpixel & 0xf check?
//fg isn't used, sprite is used and blended with bg? -- used on trail of ball / flippers
dd[x] = paldata[bgpixel + bgblend_comp];/* +paldata[sprpixel + sprblend_source];*/ // WRONG??
}
else
{
// fg isn't used, sprite is used and is opaque
dd[x] = paldata[sprpixel + spregular_comp];
}
}
break;
case 2: // above bg,fg, behind tx
if (sprbln)
{
// unusued by this game?
dd[x] = 0;// rand();
}
else
{
dd[x] = paldata[sprpixel + spregular_comp];
//dd[x] = rand();
}
break;
case 3: // above all?
if (sprbln)
{
// unusued by this game?
dd[x] = rand();
}
else
{
dd[x] = paldata[sprpixel + spregular_comp];
}
break;
}
}
else // NON SPRITE CASES
{
if (fgpixel & 0x0f)
{
if (fgbln)
{
// needs if bgpixel & 0xf check?
dd[x] = paldata[fgpixel + fgblend_source] + paldata[bgpixel + 0x0000+0x300];
}
else
{
dd[x] = paldata[fgpixel + 0x800 + 0x200];
}
}
else /*if (bgpixel & 0x0f) */
{
dd[x] = paldata[bgpixel + 0x800 + 0x300];
}
}
}
}
m_mixer->mix_bitmaps(screen, bitmap, cliprect, m_palette, &m_tile_bitmap_bg, &m_tile_bitmap_fg, (bitmap_ind16*)0, &m_sprite_bitmap);
return 0;
}

255
src/mame/video/tecmo_mix.c Normal file
View File

@ -0,0 +1,255 @@
#include "emu.h"
#include "tecmo_mix.h"
const device_type TECMO_MIXER = &device_creator<tecmo_mix_device>;
tecmo_mix_device::tecmo_mix_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, TECMO_MIXER, "Teccmo 16-bit Mixer", tag, owner, clock, "tecmo_mix", __FILE__),
device_video_interface(mconfig, *this),
m_sprpri_shift(0),
m_sprbln_shift(0),
m_sprcol_shift(0),
m_spblend_source(0),
m_fgblend_source(0),
m_bgblend_comp(0),
m_fgblend_comp(0),
m_txblend_comp(0),
m_spblend_comp(0),
m_bgregular_comp(0),
m_fgregular_comp(0),
m_txregular_comp(0),
m_spregular_comp(0)
{
}
void tecmo_mix_device::device_start()
{
}
void tecmo_mix_device::device_reset()
{
}
void tecmo_mix_device::set_mixer_shifts(device_t &device, int sprpri_shift, int sprbln_shift, int sprcol_shift)
{
tecmo_mix_device &dev = downcast<tecmo_mix_device &>(device);
dev.m_sprpri_shift = sprpri_shift;
dev.m_sprbln_shift = sprbln_shift;
dev.m_sprcol_shift = sprcol_shift;
}
void tecmo_mix_device::set_blendcols(device_t &device, int bgblend_comp, int fgblend_comp, int txblend_comp, int spblend_comp)
{
tecmo_mix_device &dev = downcast<tecmo_mix_device &>(device);
dev.m_bgblend_comp = bgblend_comp;
dev.m_fgblend_comp = fgblend_comp;
dev.m_txblend_comp = txblend_comp;
dev.m_spblend_comp = spblend_comp;
}
void tecmo_mix_device::set_regularcols(device_t &device, int bgregular_comp, int fgregular_comp, int txregular_comp, int spregular_comp)
{
tecmo_mix_device &dev = downcast<tecmo_mix_device &>(device);
dev.m_bgregular_comp = bgregular_comp;
dev.m_fgregular_comp = fgregular_comp;
dev.m_txregular_comp = txregular_comp;
dev.m_spregular_comp = spregular_comp;
}
void tecmo_mix_device::set_blendsource(device_t &device, int spblend_source, int fgblend_source)
{
tecmo_mix_device &dev = downcast<tecmo_mix_device &>(device);
dev.m_spblend_source = spblend_source;
dev.m_fgblend_source = fgblend_source;
}
void tecmo_mix_device::mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, palette_device* palette, bitmap_ind16* bitmap_bg, bitmap_ind16* bitmap_fg, bitmap_ind16* bitmap_tx, bitmap_ind16* bitmap_sp)
{
//int frame = (screen.frame_number()) & 1;
// note this game has no tx layer, comments relate to other drivers
int y, x;
const pen_t *paldata = palette->pens();
for (y = cliprect.min_y; y <= cliprect.max_y; y++)
{
UINT32 *dd = &bitmap.pix32(y);
UINT16 *sd2 = &bitmap_sp->pix16(y);
UINT16 *fg = &bitmap_fg->pix16(y);
UINT16 *bg = &bitmap_bg->pix16(y);
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
{
UINT16 sprpixel = (sd2[x]);
UINT16 m_sprpri = (sprpixel >> m_sprpri_shift) & 0x3;
UINT16 m_sprbln = (sprpixel >> m_sprbln_shift) & 0x1;
UINT16 m_sprcol = (sprpixel >> m_sprcol_shift) & 0xf;
sprpixel = (sprpixel & 0xf) | (m_sprcol << 4);
//sprpixel &= 0xff;
UINT16 fgpixel = (fg[x]);
UINT16 fgbln = (fgpixel & 0x0100) >> 8;
fgpixel &= 0xff;
UINT16 bgpixel = (bg[x]);
bgpixel &= 0xff;
if (sprpixel&0xf)
{
switch (m_sprpri)
{
case 0: // behind all
if (fgpixel & 0xf) // is the fg used?
{
if (fgbln)
{
dd[x] = rand();
}
else
{
// solid FG
dd[x] = paldata[fgpixel + m_fgregular_comp];
}
}
else if (bgpixel & 0x0f)
{
// solid BG
dd[x] = paldata[bgpixel + m_bgregular_comp];
}
else
{
if (m_sprbln)
{ // sprite is blended with bgpen?
dd[x] = rand();
}
else
{
// solid sprite
dd[x] = paldata[sprpixel + m_spregular_comp];
}
}
break;
case 1: // above bg, behind tx, fg
if (fgpixel & 0xf) // is the fg used?
{
if (fgbln)
{
if (m_sprbln)
{
// needs if bgpixel & 0xf check?
// fg is used and blended with sprite, sprite is used and blended with bg? -- used on 'trail' of ball when ball is under the transparent area
dd[x] = paldata[bgpixel + m_bgblend_comp] + paldata[sprpixel + m_spblend_source]; // WRONG??
}
else
{
// fg is used and blended with opaque sprite
dd[x] = paldata[fgpixel + m_fgblend_source] + paldata[sprpixel + m_spblend_comp];
}
}
else
{
// fg is used and opaque
dd[x] = paldata[fgpixel + m_fgregular_comp];
}
}
else
{
if (m_sprbln)
{
// needs if bgpixel & 0xf check?
//fg isn't used, sprite is used and blended with bg? -- used on trail of ball / flippers
dd[x] = paldata[bgpixel + m_bgblend_comp];/* +paldata[sprpixel + m_spblend_source];*/ // WRONG??
}
else
{
// fg isn't used, sprite is used and is opaque
dd[x] = paldata[sprpixel + m_spregular_comp];
}
}
break;
case 2: // above bg,fg, behind tx
if (m_sprbln)
{
// unusued by this game?
dd[x] = 0;// rand();
}
else
{
dd[x] = paldata[sprpixel + m_spregular_comp];
//dd[x] = rand();
}
break;
case 3: // above all?
if (m_sprbln)
{
// unusued by this game?
dd[x] = rand();
}
else
{
dd[x] = paldata[sprpixel + m_spregular_comp];
}
break;
}
}
else // NON SPRITE CASES
{
if (fgpixel & 0x0f)
{
if (fgbln)
{
// needs if bgpixel & 0xf check?
dd[x] = paldata[fgpixel + m_fgblend_source] + paldata[bgpixel + 0x0000+0x300];
}
else
{
dd[x] = paldata[fgpixel + 0x800 + 0x200];
}
}
else /*if (bgpixel & 0x0f) */
{
dd[x] = paldata[bgpixel + 0x800 + 0x300];
}
}
}
}
}

View File

@ -0,0 +1,66 @@
/* Tecmo Mixer */
class tecmo_mix_device : public device_t,
public device_video_interface
{
public:
tecmo_mix_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
void mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, palette_device* palette, bitmap_ind16* bitmap_bg, bitmap_ind16* bitmap_fg, bitmap_ind16* bitmap_tx, bitmap_ind16* bitmap_sp);
static void set_mixer_shifts(device_t &device, int sprpri_shift, int sprbln_shift, int sprcol_shift);
static void set_blendcols(device_t &device, int bgblend_comp, int fgblend_comp, int txblend_comp, int spblend_comp);
static void set_regularcols(device_t &device, int bgregular_comp, int fgregular_comp, int txregular_comp, int spregular_comp);
static void set_blendsource(device_t &device, int spblend_source, int fgblend_source);
protected:
virtual void device_start();
virtual void device_reset();
// mixer shifts
int m_sprpri_shift;
int m_sprbln_shift;
int m_sprcol_shift;
// when the blend bit is specified in the attribute the source blend palette for that sprite / fg pixel comes from these offsets instead
int m_spblend_source;
int m_fgblend_source;
// the second blend component depends on the pixel we are blending with, the following palettes get used instead of the regular ones
int m_bgblend_comp;
int m_fgblend_comp;
int m_txblend_comp;
int m_spblend_comp;
// otherwise the regular palettes are
int m_bgregular_comp;
int m_fgregular_comp;
int m_txregular_comp;
int m_spregular_comp;
private:
};
extern const device_type TECMO_MIXER;
#define MCFG_TECMO_MIXER_SHIFTS(_sprpri_shift, _sprbln_shift, _sprcol_shift) \
tecmo_mix_device::set_mixer_shifts(*device, _sprpri_shift, _sprbln_shift, _sprcol_shift);
#define MCFG_TECMO_MIXER_BLENDCOLS(_bgblend_comp, _fgblend_comp, _txblend_comp, _spblend_comp) \
tecmo_mix_device::set_blendcols(*device, _bgblend_comp, _fgblend_comp, _txblend_comp, _spblend_comp);
#define MCFG_TECMO_MIXER_REGULARCOLS(_bgregular_comp, _fgregular_comp, _txregular_comp, _spregular_comp) \
tecmo_mix_device::set_regularcols(*device, _bgregular_comp, _fgregular_comp, _txregular_comp, _spregular_comp);
#define MCFG_TECMO_MIXER_BLENDSOUCE(_spblend_source, _fgblend_source) \
tecmo_mix_device::set_blendsource(*device, _spblend_source, _fgblend_source);