mirror of
https://github.com/holub/mame
synced 2025-05-04 21:43:05 +03:00
Fix problem with bac06 NW
The previous emulation logic change was correct, however Sly Spy, Hippodrome, Birdy Try suffered from an ordering bug - tilemap.cpp in the core cached the tile indices before the game updated the dynamic colmun/row major bit. It seems the correct fix is to make sure tilemap::mappings_update() should be called when the column/row bit changes, however this is currently a private function. I've put in a hack at line 396 so that mappings_update() is called as a side effect of a flip. The better fix would be just to expose mappings_update for general driver use, but I didn't want to make that larger change without approval.
This commit is contained in:
parent
ea78bea4ee
commit
2bf7666664
592
src/mame/video/decbac06 - Copy (2).cpp
Normal file
592
src/mame/video/decbac06 - Copy (2).cpp
Normal file
@ -0,0 +1,592 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Bryan McPhail, David Haywood
|
||||
/*
|
||||
Deco BAC06 tilemap generator:
|
||||
|
||||
this a direct relative of the later chip implemented in deco16ic.c
|
||||
we could implement this as either an 8-bit or a 16-bit chip, for now
|
||||
I'm using the 16-bit implementation from dec0.c
|
||||
|
||||
used by:
|
||||
|
||||
actfancr.c
|
||||
dec0.c
|
||||
dec8.c (oscar, cobracom, ghostb)
|
||||
madmotor.c
|
||||
stadhero.c
|
||||
pcktgal.c
|
||||
|
||||
Notes (from dec0.c)
|
||||
|
||||
All games contain three BAC06 background generator chips, usual (software)
|
||||
configuration is 2 chips of 16*16 tiles, 1 of 8*8.
|
||||
|
||||
Playfield control registers:
|
||||
bank 0:
|
||||
0:
|
||||
bit 0 (0x1) set = 8*8 tiles, else 16*16 tiles
|
||||
Bit 1 (0x2) set = row major tile layout, else column major*
|
||||
bit 2 (0x4) set enables rowscroll
|
||||
bit 3 (0x8) set enables colscroll
|
||||
bit 7 (0x80) set in playfield 1 is reverse screen (set via dip-switch)
|
||||
bit 7 (0x80) in other playfields unknown
|
||||
2: unknown (00 in bg, 03 in fg+text - maybe controls pf transparency?)
|
||||
4: unknown (always 00) [Used to access 2nd bank of tiles in Stadium Hero)
|
||||
6: playfield shape: 00 = 4x1, 01 = 2x2, 02 = 1x4 (low 4 bits only)
|
||||
|
||||
bank 1:
|
||||
0: horizontal scroll
|
||||
2: vertical scroll
|
||||
4: colscroll shifter (low 4 bits, top 4 bits do nothing)
|
||||
6: rowscroll shifter (low 4 bits, top 4 bits do nothing)
|
||||
|
||||
Row & column scroll can be applied simultaneously or by themselves.
|
||||
The shift register controls the granularity of the scroll offsets
|
||||
(more details given later).
|
||||
|
||||
* Bandit is the only game known to use column major tile layout, when in this
|
||||
mode X scrolling is also inverted, and tile character data is flipped on X.
|
||||
|
||||
Playfield priority (Bad Dudes, etc):
|
||||
In the bottommost playfield, pens 8-15 can have priority over the next playfield.
|
||||
In that next playfield, pens 8-15 can have priority over sprites.
|
||||
|
||||
Bit 0: Playfield inversion
|
||||
Bit 1: Enable playfield mixing (for palettes 8-15 only)
|
||||
Bit 2: Enable playfield/sprite mixing (for palettes 8-15 only)
|
||||
|
||||
Priority word (Midres):
|
||||
Bit 0 set = Playfield 3 drawn over Playfield 2
|
||||
~ = Playfield 2 drawn over Playfield 3
|
||||
Bit 1 set = Sprites are drawn inbetween playfields
|
||||
~ = Sprites are on top of playfields
|
||||
Bit 2
|
||||
Bit 3 set = ...
|
||||
|
||||
Note that priority mixing is handled outside of the BAC-06 chip.
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "decbac06.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(DECO_BAC06, deco_bac06_device, "deco_back06", "DECO BAC06 Tilemap")
|
||||
|
||||
deco_bac06_device::deco_bac06_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, DECO_BAC06, tag, owner, clock)
|
||||
, m_pf_data(nullptr)
|
||||
, m_pf_rowscroll(nullptr)
|
||||
, m_pf_colscroll(nullptr)
|
||||
, m_tile_region_8(0)
|
||||
, m_tile_region_16(0)
|
||||
, m_supports_8x8(true)
|
||||
, m_supports_16x16(true)
|
||||
, m_supports_rc_scroll(true)
|
||||
, m_gfxcolmask(0)
|
||||
, m_rambank(0)
|
||||
, m_gfxregion8x8(0)
|
||||
, m_gfxregion16x16(0)
|
||||
, m_wide(0)
|
||||
, m_bppmult(0)
|
||||
, m_bppmask(0)
|
||||
, m_gfxdecode(*this, finder_base::DUMMY_TAG)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
m_pf_control_0[i] = 0;
|
||||
m_pf_control_1[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void deco_bac06_device::device_start()
|
||||
{
|
||||
if(!m_gfxdecode->started())
|
||||
throw device_missing_dependencies();
|
||||
|
||||
m_pf_data = make_unique_clear<uint16_t[]>(0x4000 / 2); // 0x2000 is the maximum needed, some games / chip setups map less and mirror - stadium hero banks this to 0x4000?!
|
||||
m_pf_rowscroll = make_unique_clear<uint16_t[]>(0x2000 / 2);
|
||||
m_pf_colscroll = make_unique_clear<uint16_t[]>(0x2000 / 2);
|
||||
|
||||
create_tilemaps(m_gfxregion8x8, m_gfxregion16x16);
|
||||
m_gfxcolmask = 0x0f;
|
||||
|
||||
m_bppmult = 0x10;
|
||||
m_bppmask = 0x0f;
|
||||
m_rambank = 0;
|
||||
m_flip_screen = false;
|
||||
|
||||
save_pointer(NAME(m_pf_data), 0x4000/2);
|
||||
save_pointer(NAME(m_pf_rowscroll), 0x2000/2);
|
||||
save_pointer(NAME(m_pf_colscroll), 0x2000/2);
|
||||
save_item(NAME(m_pf_control_0));
|
||||
save_item(NAME(m_pf_control_1));
|
||||
save_item(NAME(m_gfxcolmask));
|
||||
save_item(NAME(m_rambank));
|
||||
save_item(NAME(m_flip_screen));
|
||||
}
|
||||
|
||||
void deco_bac06_device::device_reset()
|
||||
{
|
||||
}
|
||||
|
||||
void deco_bac06_device::set_flip_screen(bool flip)
|
||||
{
|
||||
if (m_flip_screen != flip)
|
||||
{
|
||||
m_flip_screen = flip;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
m_pf8x8_tilemap[i]->set_flip(flip ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
|
||||
m_pf16x16_tilemap[i]->set_flip(flip ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape0_scan)
|
||||
{
|
||||
if ((m_pf_control_0[0]&2)==0)
|
||||
return (row & 0xf) + ((0x3f - (col & 0x3f)) << 4);
|
||||
return (col & 0xf) + ((row & 0xf) << 4) + ((col & 0x1f0) << 4);
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape1_scan)
|
||||
{
|
||||
//if (m_pf_control_0[0]&2) // Needs testing on real hardware, not used by any game
|
||||
// return (row & 0xf) + ((col & 0x1f) << 4) + ((col & 0xf0) << 5);
|
||||
return (col & 0xf) + ((row & 0x1f) << 4) + ((col & 0xf0) << 5);
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape2_scan)
|
||||
{
|
||||
//if (m_pf_control_0[0]&2) // Needs testing on real hardware, not used by any game
|
||||
// return (col & 0xf) + ((row & 0x3f) << 4) + ((row & 0x70) << 6);
|
||||
return (col & 0xf) + ((row & 0x3f) << 4) + ((col & 0x70) << 6);
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape0_8x8_scan)
|
||||
{
|
||||
//if (m_pf_control_0[0]&2) // Needs testing on real hardware, not used by any game
|
||||
// return (col & 0x1f) + ((row & 0x1f) << 5) + ((row & 0x60) << 5);
|
||||
return (col & 0x1f) + ((row & 0x1f) << 5) + ((col & 0x60) << 5);
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape1_8x8_scan)
|
||||
{
|
||||
//if (m_pf_control_0[0]&2) // Needs testing on real hardware, not used by any game
|
||||
// return (row & 0x1f) + ((col & 0x1f) << 5) + ((col & 0x20) << 5) + ((row & 0x20) << 6);
|
||||
return (col & 0x1f) + ((row & 0x1f) << 5) + ((row & 0x20) << 5) + ((col & 0x20) << 6);
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape2_8x8_scan)
|
||||
{
|
||||
//if (m_pf_control_0[0]&2) // Needs testing on real hardware, not used by any game
|
||||
// return (row & 0x1f) + ((col & 0x7f) << 5);
|
||||
return (col & 0x1f) + ((row & 0x7f) << 5);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(deco_bac06_device::get_pf8x8_tile_info)
|
||||
{
|
||||
if (m_rambank&1) tile_index+=0x1000;
|
||||
int tile=m_pf_data[tile_index];
|
||||
int colourpri=(tile>>12);
|
||||
int flags=(m_pf_control_0[0]&2) ? 0 : TILE_FLIPX;
|
||||
SET_TILE_INFO_MEMBER(m_tile_region_8,tile&0xfff,0,flags);
|
||||
tileinfo.category = colourpri;
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(deco_bac06_device::get_pf16x16_tile_info)
|
||||
{
|
||||
if (m_rambank&1) tile_index+=0x1000;
|
||||
int tile=m_pf_data[tile_index];
|
||||
int colourpri=(tile>>12);
|
||||
int flags=(m_pf_control_0[0]&2) ? 0 : TILE_FLIPX;
|
||||
SET_TILE_INFO_MEMBER(m_tile_region_16,tile&0xfff,0,flags);
|
||||
tileinfo.category = colourpri;
|
||||
}
|
||||
|
||||
void deco_bac06_device::create_tilemaps(int region8x8, int region16x16)
|
||||
{
|
||||
m_tile_region_8 = region8x8;
|
||||
m_tile_region_16 = region16x16;
|
||||
|
||||
m_pf8x8_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf8x8_tile_info),this),tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape0_8x8_scan),this), 8, 8,128, 32);
|
||||
m_pf8x8_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf8x8_tile_info),this),tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape1_8x8_scan),this), 8, 8, 64, 64);
|
||||
m_pf8x8_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf8x8_tile_info),this),tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape2_8x8_scan),this), 8, 8, 32,128);
|
||||
|
||||
|
||||
if (m_wide==2)
|
||||
{
|
||||
m_pf16x16_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf16x16_tile_info),this), tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape0_scan),this), 16, 16, 256, 16);
|
||||
m_pf16x16_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf16x16_tile_info),this), tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape1_scan),this), 16, 16, 128, 32);
|
||||
m_pf16x16_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf16x16_tile_info),this), tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape2_scan),this), 16, 16, 64, 64);
|
||||
}
|
||||
else if (m_wide==1)
|
||||
{
|
||||
m_pf16x16_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf16x16_tile_info),this), tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape0_scan),this), 16, 16, 128, 16);
|
||||
m_pf16x16_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf16x16_tile_info),this), tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape1_scan),this), 16, 16, 64, 32);
|
||||
m_pf16x16_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf16x16_tile_info),this), tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape2_scan),this), 16, 16, 32, 64);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pf16x16_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf16x16_tile_info),this),tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape0_scan),this), 16,16, 64, 16);
|
||||
m_pf16x16_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf16x16_tile_info),this),tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape1_scan),this), 16,16, 32, 32);
|
||||
m_pf16x16_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(deco_bac06_device::get_pf16x16_tile_info),this),tilemap_mapper_delegate(FUNC(deco_bac06_device::tile_shape2_scan),this), 16,16, 16, 64);
|
||||
}
|
||||
}
|
||||
|
||||
void deco_bac06_device::custom_tilemap_draw(bitmap_ind16 &bitmap,
|
||||
const rectangle &cliprect,
|
||||
tilemap_t *tilemap_ptr,
|
||||
const uint16_t *rowscroll_ptr,
|
||||
const uint16_t *colscroll_ptr,
|
||||
const uint16_t *control0,
|
||||
const uint16_t *control1,
|
||||
int flags,
|
||||
uint16_t penmask,
|
||||
uint16_t pencondition,
|
||||
uint16_t colprimask,
|
||||
uint16_t colpricondition
|
||||
)
|
||||
{
|
||||
const bitmap_ind16 &src_bitmap = tilemap_ptr->pixmap();
|
||||
const bitmap_ind8 &flags_bitmap = tilemap_ptr->flagsmap();
|
||||
int x, y, p, colpri;
|
||||
int column_offset=0, src_x=0, src_y=0;
|
||||
uint32_t scrollx = 0;
|
||||
uint32_t scrolly = 0;
|
||||
|
||||
if (control1)
|
||||
{
|
||||
if (control0 && (control0[0]&2)==0) // Use of column major mode inverts scroll direction
|
||||
scrollx = -control1[0] - 0x100;
|
||||
else
|
||||
scrollx = control1[0];
|
||||
scrolly = control1[1];
|
||||
}
|
||||
|
||||
int width_mask;
|
||||
int height_mask;
|
||||
int row_scroll_enabled = 0;
|
||||
int col_scroll_enabled = 0;
|
||||
|
||||
if (m_supports_rc_scroll)
|
||||
{
|
||||
if (control0)
|
||||
{
|
||||
row_scroll_enabled = (rowscroll_ptr && (control0[0] & 0x4));
|
||||
col_scroll_enabled = (colscroll_ptr && (control0[0] & 0x8));
|
||||
}
|
||||
}
|
||||
|
||||
width_mask = src_bitmap.width() - 1;
|
||||
height_mask = src_bitmap.height() - 1;
|
||||
|
||||
/* Column scroll & row scroll may per applied per pixel, there are
|
||||
shift registers for each which control the granularity of the row/col
|
||||
offset (down to per line level for row, and per 8 lines for column).
|
||||
|
||||
Nb: The row & col selectors are _not_ affected by the shape of the
|
||||
playfield (ie, 256*1024, 512*512 or 1024*256). So even if the tilemap
|
||||
width is only 256, 'src_x' should not wrap at 256 in the code below (to
|
||||
do so would mean the top half of row RAM would never be accessed which
|
||||
is incorrect).
|
||||
|
||||
Nb2: Real hardware exhibits a strange bug with column scroll on 'mode 2'
|
||||
(256*1024) - the first column has a strange additional offset, but
|
||||
curiously the first 'wrap' (at scroll offset 256) does not have this offset,
|
||||
it is displayed as expected. The bug is confimed to only affect this mode,
|
||||
the other two modes work as expected. This bug is not emulated, as it
|
||||
doesn't affect any games.
|
||||
*/
|
||||
|
||||
if (m_flip_screen)
|
||||
src_y = (src_bitmap.height() - 256) - scrolly;
|
||||
else
|
||||
src_y = scrolly;
|
||||
|
||||
for (y=0; y<=cliprect.bottom(); y++) {
|
||||
if (row_scroll_enabled)
|
||||
src_x=scrollx + rowscroll_ptr[(src_y >> (control1[3]&0xf))&(0x1ff>>(control1[3]&0xf))];
|
||||
else
|
||||
src_x=scrollx;
|
||||
|
||||
if (m_flip_screen)
|
||||
src_x=(src_bitmap.width() - 256) - src_x;
|
||||
|
||||
for (x=0; x<=cliprect.right(); x++) {
|
||||
if (col_scroll_enabled)
|
||||
column_offset=colscroll_ptr[((src_x >> 3) >> (control1[2]&0xf))&(0x3f>>(control1[2]&0xf))];
|
||||
|
||||
p = src_bitmap.pix16((src_y + column_offset)&height_mask, src_x&width_mask);
|
||||
colpri = flags_bitmap.pix8((src_y + column_offset)&height_mask, src_x&width_mask)&0xf;
|
||||
|
||||
src_x++;
|
||||
if ((flags&TILEMAP_DRAW_OPAQUE) || (p&m_bppmask))
|
||||
{
|
||||
if ((p&penmask)==pencondition)
|
||||
if((colpri&colprimask)==colpricondition)
|
||||
bitmap.pix16(y, x) = p+(colpri&m_gfxcolmask)*m_bppmult;
|
||||
}
|
||||
}
|
||||
src_y++;
|
||||
}
|
||||
}
|
||||
|
||||
void deco_bac06_device::deco_bac06_pf_draw(bitmap_ind16 &bitmap,const rectangle &cliprect,int flags,uint16_t penmask, uint16_t pencondition,uint16_t colprimask, uint16_t colpricondition)
|
||||
{
|
||||
tilemap_t* tm = nullptr;
|
||||
|
||||
int tm_dimensions = m_pf_control_0[3] & 0x3;
|
||||
if (tm_dimensions == 3) tm_dimensions = 1; // 3 is invalid / the same as 1?
|
||||
|
||||
if (m_pf_control_0[0]&0x1) // is 8x8 tiles mode selected?
|
||||
{
|
||||
if (m_supports_8x8)
|
||||
{
|
||||
tm = m_pf8x8_tilemap[tm_dimensions];
|
||||
}
|
||||
else if (m_supports_16x16)
|
||||
{
|
||||
tm = m_pf16x16_tilemap[tm_dimensions];
|
||||
}
|
||||
}
|
||||
else // 16x16 tiles mode is selected
|
||||
{
|
||||
if (m_supports_16x16)
|
||||
{
|
||||
tm = m_pf16x16_tilemap[tm_dimensions];
|
||||
}
|
||||
else if (m_supports_8x8)
|
||||
{
|
||||
tm = m_pf8x8_tilemap[tm_dimensions];
|
||||
}
|
||||
}
|
||||
|
||||
if (tm)
|
||||
custom_tilemap_draw(bitmap,cliprect,tm,m_pf_rowscroll.get(),m_pf_colscroll.get(),m_pf_control_0,m_pf_control_1,flags, penmask, pencondition, colprimask, colpricondition);
|
||||
|
||||
}
|
||||
|
||||
// used for pocket gal bootleg, which doesn't set registers properly and simply expects a fixed size tilemap.
|
||||
void deco_bac06_device::deco_bac06_pf_draw_bootleg(bitmap_ind16 &bitmap,const rectangle &cliprect,int flags, int mode, int type)
|
||||
{
|
||||
tilemap_t* tm = nullptr;
|
||||
if (!mode) tm = m_pf8x8_tilemap[type];
|
||||
else tm = m_pf16x16_tilemap[type];
|
||||
|
||||
custom_tilemap_draw(bitmap,cliprect,tm,m_pf_rowscroll.get(),m_pf_colscroll.get(),nullptr,nullptr,flags, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
WRITE16_MEMBER( deco_bac06_device::pf_control_0_w )
|
||||
{
|
||||
int oldRegister0 = m_pf_control_0[0];
|
||||
|
||||
offset &= 3;
|
||||
|
||||
COMBINE_DATA(&m_pf_control_0[offset]);
|
||||
|
||||
bool dirtyAll = false;
|
||||
if (offset==0)
|
||||
{
|
||||
if ((oldRegister0&2)!=(m_pf_control_0[offset]&2))
|
||||
{
|
||||
int flip = m_flip_screen;
|
||||
set_flip_screen(flip^1);
|
||||
set_flip_screen(flip); // Hack to force tilemap.cpp mappings_update() to be called
|
||||
dirtyAll = true;
|
||||
}
|
||||
}
|
||||
if (offset==2)
|
||||
{
|
||||
int newbank = m_pf_control_0[offset]&1;
|
||||
if ((newbank&1) != (m_rambank&1))
|
||||
{
|
||||
// I don't know WHY Stadium Hero uses this as a bank but the RAM test expects it..
|
||||
// I'm curious as to if anything else sets it tho
|
||||
if (strcmp(machine().system().name,"stadhero"))
|
||||
printf("tilemap ram bank change to %d\n", newbank&1);
|
||||
|
||||
dirtyAll = true;
|
||||
m_rambank = newbank&1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirtyAll)
|
||||
{
|
||||
m_pf8x8_tilemap[0]->mark_all_dirty();
|
||||
m_pf8x8_tilemap[1]->mark_all_dirty();
|
||||
m_pf8x8_tilemap[2]->mark_all_dirty();
|
||||
m_pf16x16_tilemap[0]->mark_all_dirty();
|
||||
m_pf16x16_tilemap[1]->mark_all_dirty();
|
||||
m_pf16x16_tilemap[2]->mark_all_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
READ16_MEMBER( deco_bac06_device::pf_control_1_r )
|
||||
{
|
||||
offset &= 7;
|
||||
return m_pf_control_1[offset];
|
||||
}
|
||||
|
||||
WRITE16_MEMBER( deco_bac06_device::pf_control_1_w )
|
||||
{
|
||||
offset &= 7;
|
||||
COMBINE_DATA(&m_pf_control_1[offset]);
|
||||
}
|
||||
|
||||
WRITE16_MEMBER( deco_bac06_device::pf_data_w )
|
||||
{
|
||||
if (m_rambank&1) offset+=0x1000;
|
||||
|
||||
COMBINE_DATA(&m_pf_data[offset]);
|
||||
m_pf8x8_tilemap[0]->mark_tile_dirty(offset);
|
||||
m_pf8x8_tilemap[1]->mark_tile_dirty(offset);
|
||||
m_pf8x8_tilemap[2]->mark_tile_dirty(offset);
|
||||
m_pf16x16_tilemap[0]->mark_tile_dirty(offset);
|
||||
m_pf16x16_tilemap[1]->mark_tile_dirty(offset);
|
||||
m_pf16x16_tilemap[2]->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
READ16_MEMBER( deco_bac06_device::pf_data_r )
|
||||
{
|
||||
if (m_rambank&1) offset+=0x1000;
|
||||
|
||||
return m_pf_data[offset];
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( deco_bac06_device::pf_data_8bit_w )
|
||||
{
|
||||
if (offset&1)
|
||||
pf_data_w(space,offset/2,data,0x00ff);
|
||||
else
|
||||
pf_data_w(space,offset/2,data<<8,0xff00);
|
||||
}
|
||||
|
||||
READ8_MEMBER( deco_bac06_device::pf_data_8bit_r )
|
||||
{
|
||||
if (offset&1) /* MSB */
|
||||
return pf_data_r(space,offset/2,0x00ff);
|
||||
else
|
||||
return pf_data_r(space,offset/2,0xff00)>>8;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER( deco_bac06_device::pf_rowscroll_w )
|
||||
{
|
||||
COMBINE_DATA(&m_pf_rowscroll[offset]);
|
||||
}
|
||||
|
||||
WRITE16_MEMBER( deco_bac06_device::pf_colscroll_w )
|
||||
{
|
||||
COMBINE_DATA(&m_pf_colscroll[offset]);
|
||||
}
|
||||
|
||||
READ16_MEMBER( deco_bac06_device::pf_rowscroll_r )
|
||||
{
|
||||
return m_pf_rowscroll[offset];
|
||||
}
|
||||
|
||||
READ16_MEMBER( deco_bac06_device::pf_colscroll_r )
|
||||
{
|
||||
return m_pf_colscroll[offset];
|
||||
}
|
||||
|
||||
/* used by dec8.c */
|
||||
WRITE8_MEMBER( deco_bac06_device::pf_control0_8bit_w )
|
||||
{
|
||||
if (offset&1)
|
||||
pf_control_0_w(space,offset/2,data,0x00ff); // oscar (mirrors?)
|
||||
else
|
||||
pf_control_0_w(space,offset/2,data,0x00ff);
|
||||
}
|
||||
|
||||
/* used by dec8.c */
|
||||
READ8_MEMBER( deco_bac06_device::pf_control1_8bit_r )
|
||||
{
|
||||
if (offset&1)
|
||||
return pf_control_1_r(space,offset/2,0x00ff);
|
||||
else
|
||||
return pf_control_1_r(space,offset/2,0xff00)>>8;
|
||||
}
|
||||
|
||||
/* used by dec8.c */
|
||||
WRITE8_MEMBER( deco_bac06_device::pf_control1_8bit_w )
|
||||
{
|
||||
if (offset<4) // these registers are 16-bit?
|
||||
{
|
||||
if (offset&1)
|
||||
pf_control_1_w(space,offset/2,data,0x00ff);
|
||||
else
|
||||
pf_control_1_w(space,offset/2,data<<8,0xff00);
|
||||
}
|
||||
else // these registers are 8-bit and mirror? (triothep vs actfancr)
|
||||
{
|
||||
if (offset&1)
|
||||
pf_control_1_w(space,offset/2,data,0x00ff);
|
||||
else
|
||||
pf_control_1_w(space,offset/2,data,0x00ff);
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER( deco_bac06_device::pf_rowscroll_8bit_r )
|
||||
{
|
||||
if (offset&1)
|
||||
return pf_rowscroll_r(space,offset/2,0x00ff);
|
||||
else
|
||||
return pf_rowscroll_r(space,offset/2,0xff00)>>8;
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER( deco_bac06_device::pf_rowscroll_8bit_w )
|
||||
{
|
||||
if (offset&1)
|
||||
pf_rowscroll_w(space,offset/2,data,0x00ff);
|
||||
else
|
||||
pf_rowscroll_w(space,offset/2,data<<8,0xff00);
|
||||
}
|
||||
|
||||
READ8_MEMBER( deco_bac06_device::pf_rowscroll_8bit_swap_r )
|
||||
{
|
||||
if (offset&1)
|
||||
return pf_rowscroll_r(space,offset/2,0xff00)>>8;
|
||||
else
|
||||
return pf_rowscroll_r(space,offset/2,0x00ff);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( deco_bac06_device::pf_rowscroll_8bit_swap_w )
|
||||
{
|
||||
if (offset&1)
|
||||
pf_rowscroll_w(space,offset/2,data<<8,0xff00);
|
||||
else
|
||||
pf_rowscroll_w(space,offset/2,data,0x00ff);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* used by hippodrm */
|
||||
WRITE8_MEMBER( deco_bac06_device::pf_control0_8bit_packed_w )
|
||||
{
|
||||
if (offset&1)
|
||||
pf_control_0_w(space,offset/2,data<<8,0xff00);
|
||||
else
|
||||
pf_control_0_w(space,offset/2,data,0x00ff);
|
||||
}
|
||||
|
||||
/* used by hippodrm */
|
||||
WRITE8_MEMBER( deco_bac06_device::pf_control1_8bit_swap_w )
|
||||
{
|
||||
pf_control1_8bit_w(space, offset^1, data);
|
||||
}
|
||||
|
||||
/* used by hippodrm */
|
||||
READ8_MEMBER( deco_bac06_device::pf_data_8bit_swap_r )
|
||||
{
|
||||
return pf_data_8bit_r(space, offset^1);
|
||||
}
|
||||
|
||||
/* used by hippodrm */
|
||||
WRITE8_MEMBER( deco_bac06_device::pf_data_8bit_swap_w )
|
||||
{
|
||||
pf_data_8bit_w(space, offset^1, data);
|
||||
}
|
@ -25,7 +25,7 @@ configuration is 2 chips of 16*16 tiles, 1 of 8*8.
|
||||
bank 0:
|
||||
0:
|
||||
bit 0 (0x1) set = 8*8 tiles, else 16*16 tiles
|
||||
Bit 1 (0x2) unknown
|
||||
Bit 1 (0x2) set = row major tile layout, else column major*
|
||||
bit 2 (0x4) set enables rowscroll
|
||||
bit 3 (0x8) set enables colscroll
|
||||
bit 7 (0x80) set in playfield 1 is reverse screen (set via dip-switch)
|
||||
@ -44,6 +44,9 @@ configuration is 2 chips of 16*16 tiles, 1 of 8*8.
|
||||
The shift register controls the granularity of the scroll offsets
|
||||
(more details given later).
|
||||
|
||||
* Bandit is the only game known to use column major tile layout, when in this
|
||||
mode X scrolling is also inverted, and tile character data is flipped on X.
|
||||
|
||||
Playfield priority (Bad Dudes, etc):
|
||||
In the bottommost playfield, pens 8-15 can have priority over the next playfield.
|
||||
In that next playfield, pens 8-15 can have priority over sprites.
|
||||
@ -60,6 +63,8 @@ Priority word (Midres):
|
||||
Bit 2
|
||||
Bit 3 set = ...
|
||||
|
||||
Note that priority mixing is handled outside of the BAC-06 chip.
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -139,31 +144,43 @@ void deco_bac06_device::set_flip_screen(bool flip)
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape0_scan)
|
||||
{
|
||||
if ((m_pf_control_0[0]&2)==0)
|
||||
return (row & 0xf) + ((0x3f - (col & 0x3f)) << 4);
|
||||
return (col & 0xf) + ((row & 0xf) << 4) + ((col & 0x1f0) << 4);
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape1_scan)
|
||||
{
|
||||
//if (m_pf_control_0[0]&2) // Needs testing on real hardware, not used by any game
|
||||
// return (row & 0xf) + ((col & 0x1f) << 4) + ((col & 0xf0) << 5);
|
||||
return (col & 0xf) + ((row & 0x1f) << 4) + ((col & 0xf0) << 5);
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape2_scan)
|
||||
{
|
||||
//if (m_pf_control_0[0]&2) // Needs testing on real hardware, not used by any game
|
||||
// return (col & 0xf) + ((row & 0x3f) << 4) + ((row & 0x70) << 6);
|
||||
return (col & 0xf) + ((row & 0x3f) << 4) + ((col & 0x70) << 6);
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape0_8x8_scan)
|
||||
{
|
||||
//if (m_pf_control_0[0]&2) // Needs testing on real hardware, not used by any game
|
||||
// return (col & 0x1f) + ((row & 0x1f) << 5) + ((row & 0x60) << 5);
|
||||
return (col & 0x1f) + ((row & 0x1f) << 5) + ((col & 0x60) << 5);
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape1_8x8_scan)
|
||||
{
|
||||
//if (m_pf_control_0[0]&2) // Needs testing on real hardware, not used by any game
|
||||
// return (row & 0x1f) + ((col & 0x1f) << 5) + ((col & 0x20) << 5) + ((row & 0x20) << 6);
|
||||
return (col & 0x1f) + ((row & 0x1f) << 5) + ((row & 0x20) << 5) + ((col & 0x20) << 6);
|
||||
}
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deco_bac06_device::tile_shape2_8x8_scan)
|
||||
{
|
||||
//if (m_pf_control_0[0]&2) // Needs testing on real hardware, not used by any game
|
||||
// return (row & 0x1f) + ((col & 0x7f) << 5);
|
||||
return (col & 0x1f) + ((row & 0x7f) << 5);
|
||||
}
|
||||
|
||||
@ -172,7 +189,8 @@ TILE_GET_INFO_MEMBER(deco_bac06_device::get_pf8x8_tile_info)
|
||||
if (m_rambank&1) tile_index+=0x1000;
|
||||
int tile=m_pf_data[tile_index];
|
||||
int colourpri=(tile>>12);
|
||||
SET_TILE_INFO_MEMBER(m_tile_region_8,tile&0xfff,0,0);
|
||||
int flags=(m_pf_control_0[0]&2) ? 0 : TILE_FLIPX;
|
||||
SET_TILE_INFO_MEMBER(m_tile_region_8,tile&0xfff,0,flags);
|
||||
tileinfo.category = colourpri;
|
||||
}
|
||||
|
||||
@ -181,7 +199,8 @@ TILE_GET_INFO_MEMBER(deco_bac06_device::get_pf16x16_tile_info)
|
||||
if (m_rambank&1) tile_index+=0x1000;
|
||||
int tile=m_pf_data[tile_index];
|
||||
int colourpri=(tile>>12);
|
||||
SET_TILE_INFO_MEMBER(m_tile_region_16,tile&0xfff,0,0);
|
||||
int flags=(m_pf_control_0[0]&2) ? 0 : TILE_FLIPX;
|
||||
SET_TILE_INFO_MEMBER(m_tile_region_16,tile&0xfff,0,flags);
|
||||
tileinfo.category = colourpri;
|
||||
}
|
||||
|
||||
@ -238,7 +257,10 @@ void deco_bac06_device::custom_tilemap_draw(bitmap_ind16 &bitmap,
|
||||
|
||||
if (control1)
|
||||
{
|
||||
scrollx = control1[0];
|
||||
if (control0 && (control0[0]&2)==0) // Use of column major mode inverts scroll direction
|
||||
scrollx = -control1[0] - 0x100;
|
||||
else
|
||||
scrollx = control1[0];
|
||||
scrolly = control1[1];
|
||||
}
|
||||
|
||||
@ -359,10 +381,23 @@ void deco_bac06_device::deco_bac06_pf_draw_bootleg(bitmap_ind16 &bitmap,const re
|
||||
|
||||
WRITE16_MEMBER( deco_bac06_device::pf_control_0_w )
|
||||
{
|
||||
int oldRegister0 = m_pf_control_0[0];
|
||||
|
||||
offset &= 3;
|
||||
|
||||
COMBINE_DATA(&m_pf_control_0[offset]);
|
||||
|
||||
bool dirtyAll = false;
|
||||
if (offset==0)
|
||||
{
|
||||
if ((oldRegister0&2)!=(m_pf_control_0[offset]&2))
|
||||
{
|
||||
int flip = m_flip_screen;
|
||||
set_flip_screen(flip^1);
|
||||
set_flip_screen(flip); // Hack to force tilemap.cpp mappings_update() to be called
|
||||
dirtyAll = true;
|
||||
}
|
||||
}
|
||||
if (offset==2)
|
||||
{
|
||||
int newbank = m_pf_control_0[offset]&1;
|
||||
@ -373,15 +408,20 @@ WRITE16_MEMBER( deco_bac06_device::pf_control_0_w )
|
||||
if (strcmp(machine().system().name,"stadhero"))
|
||||
printf("tilemap ram bank change to %d\n", newbank&1);
|
||||
|
||||
dirtyAll = true;
|
||||
m_rambank = newbank&1;
|
||||
m_pf8x8_tilemap[0]->mark_all_dirty();
|
||||
m_pf8x8_tilemap[1]->mark_all_dirty();
|
||||
m_pf8x8_tilemap[2]->mark_all_dirty();
|
||||
m_pf16x16_tilemap[0]->mark_all_dirty();
|
||||
m_pf16x16_tilemap[1]->mark_all_dirty();
|
||||
m_pf16x16_tilemap[2]->mark_all_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
if (dirtyAll)
|
||||
{
|
||||
m_pf8x8_tilemap[0]->mark_all_dirty();
|
||||
m_pf8x8_tilemap[1]->mark_all_dirty();
|
||||
m_pf8x8_tilemap[2]->mark_all_dirty();
|
||||
m_pf16x16_tilemap[0]->mark_all_dirty();
|
||||
m_pf16x16_tilemap[1]->mark_all_dirty();
|
||||
m_pf16x16_tilemap[2]->mark_all_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
READ16_MEMBER( deco_bac06_device::pf_control_1_r )
|
||||
|
@ -61,7 +61,7 @@ void deco_mxc06_device::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cli
|
||||
offs = 0;
|
||||
while (offs < m_ramsize / 2)
|
||||
{
|
||||
int sx, sy, code, color, w, h, flipx, flipy, incy, flash, mult, x, y;
|
||||
int sx, sy, code, color, w, h, flipx, flipy, incy, flash, mult, x, y, parentFlipY;
|
||||
|
||||
sy = spriteram[offs];
|
||||
sx = spriteram[offs + 2];
|
||||
@ -70,12 +70,9 @@ void deco_mxc06_device::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cli
|
||||
flash = sx & 0x800;
|
||||
|
||||
flipx = sy & 0x2000;
|
||||
flipy = sy & 0x4000;
|
||||
parentFlipY = flipy = sy & 0x4000;
|
||||
h = (1 << ((sy & 0x1800) >> 11)); /* 1x, 2x, 4x, 8x height */
|
||||
w = (1 << ((sy & 0x0600) >> 9)); /* 1x, 2x, 4x, 8x width */
|
||||
/* multi width used only on the title screen? */
|
||||
|
||||
|
||||
|
||||
sx = sx & 0x01ff;
|
||||
sy = sy & 0x01ff;
|
||||
@ -112,7 +109,7 @@ void deco_mxc06_device::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cli
|
||||
code &= ~(h - 1);
|
||||
|
||||
// not affected by flipscreen
|
||||
if (spriteram[offs] & 0x4000)
|
||||
if (parentFlipY) // in the case of multi-width sprites the y flip bit is set by the parent
|
||||
incy = -1;
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user