diff options
Diffstat (limited to 'docs/release/src/mame/video/decbac06.cpp')
-rw-r--r-- | docs/release/src/mame/video/decbac06.cpp | 632 |
1 files changed, 632 insertions, 0 deletions
diff --git a/docs/release/src/mame/video/decbac06.cpp b/docs/release/src/mame/video/decbac06.cpp new file mode 100644 index 00000000000..ad1ab7a7ab6 --- /dev/null +++ b/docs/release/src/mame/video/decbac06.cpp @@ -0,0 +1,632 @@ +// 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.cpp + 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.cpp + + used by: + + actfancr.cpp + dec0.cpp + dec8.cpp (oscar, cobracom, ghostb) + madmotor.cpp + stadhero.cpp + pcktgal.cpp + + Notes (from dec0.cpp) + + 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" + +#include <algorithm> + +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, u32 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_8x8(0) + , m_bppmask_8x8(0) + , m_bppmult_16x16(0) + , m_bppmask_16x16(0) + , m_gfxdecode(*this, finder_base::DUMMY_TAG) +{ + std::fill(std::begin(m_pf_control_0), std::end(m_pf_control_0), 0); + std::fill(std::begin(m_pf_control_1), std::end(m_pf_control_1), 0); +} + +void deco_bac06_device::device_start() +{ + if(!m_gfxdecode->started()) + throw device_missing_dependencies(); + + m_pf_data = make_unique_clear<u16[]>(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<u16[]>(0x2000 / 2); + m_pf_colscroll = make_unique_clear<u16[]>(0x2000 / 2); + + create_tilemaps(m_gfxregion8x8, m_gfxregion16x16); + m_gfxcolmask = 0x0f; + + m_bppmult_8x8 = m_gfxdecode->gfx(m_gfxregion8x8)->granularity(); + m_bppmask_8x8 = m_gfxdecode->gfx(m_gfxregion8x8)->depth() - 1; + + m_bppmult_16x16 = m_gfxdecode->gfx(m_gfxregion16x16)->granularity(); + m_bppmask_16x16 = m_gfxdecode->gfx(m_gfxregion16x16)->depth() - 1; + + 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) +{ +// HBMAME fix for decodemo 2019-02-27 +// if ((m_pf_control_0[0]&2)==0) +// { +// int col_mask = num_cols - 1; +// return (row & 0xf) + ((col_mask - (col & col_mask)) << 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; // HBMAME fix for decodemo 2019-02-27 - TILE_GET_INFO_MEMBER always returns 0 for m_pf_control_0[0] regardless of its real value + SET_TILE_INFO_MEMBER(m_tile_region_8,tile&0xfff,0,0); // HBMAME fix for decodemo 2019-02-27 + 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; // HBMAME fix for decodemo 2019-02-27 - TILE_GET_INFO_MEMBER always returns 0 for m_pf_control_0[0] regardless of its real value + SET_TILE_INFO_MEMBER(m_tile_region_16,tile&0xfff,0,0); // HBMAME fix for decodemo 2019-02-27 + 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, + bitmap_ind8 &primap, + const rectangle &cliprect, + tilemap_t *tilemap_ptr, + const u16 *rowscroll_ptr, + const u16 *colscroll_ptr, + const u16 *control0, + const u16 *control1, + int flags, + u16 penmask, + u16 pencondition, + u16 colprimask, + u16 colpricondition, + u8 bppmult, + u8 bppmask, + u8 pri, + u8 pmask) +{ + const bitmap_ind16 &src_bitmap = tilemap_ptr->pixmap(); + const bitmap_ind8 &flags_bitmap = tilemap_ptr->flagsmap(); + int column_offset = 0, src_x = 0, src_y = 0; + u32 scrollx = 0; + u32 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]; + scrollx = control1[0]; // HBMAME fix for decodemo 2019-02-27 + scrolly = control1[1]; + } + + 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)); + } + } + + const int width_mask = src_bitmap.width() - 1; + const int 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; + + src_y += cliprect.top(); + for (int y = cliprect.top(); y <= cliprect.bottom(); y++) + { + u16 *dstpix = &bitmap.pix16(y); + u8 *dstpri = &primap.pix8(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; + + src_x += cliprect.left(); + for (int x = cliprect.left(); x <= cliprect.right(); x++) + { + if (col_scroll_enabled) + column_offset=colscroll_ptr[((src_x >> 3) >> (control1[2] & 0xf)) & (0x3f >> (control1[2] & 0xf))]; + + const u16 p = src_bitmap.pix16((src_y + column_offset) & height_mask, src_x & width_mask); + const u8 colpri = flags_bitmap.pix8((src_y + column_offset) & height_mask, src_x & width_mask) & 0xf; + + src_x++; + if ((flags & TILEMAP_DRAW_OPAQUE) || (p & bppmask)) + { + if ((p & penmask) == pencondition) + if((colpri & colprimask) == colpricondition) + { + dstpix[x] = p + (colpri & m_gfxcolmask) * bppmult; + dstpri[x] = (dstpri[x] & pmask) | pri; + } + } + } + src_y++; + } +} + +void deco_bac06_device::deco_bac06_pf_draw(screen_device &screen,bitmap_ind16 &bitmap,const rectangle &cliprect,int flags,u16 penmask, u16 pencondition,u16 colprimask, u16 colpricondition, u8 pri, u8 primask) +{ + tilemap_t* tm = nullptr; + u8 bppmult = 0, bppmask = 0; + + 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]; + bppmult = m_bppmult_8x8; + bppmask = m_bppmask_8x8; + } + else if (m_supports_16x16) + { + tm = m_pf16x16_tilemap[tm_dimensions]; + bppmult = m_bppmult_16x16; + bppmask = m_bppmask_16x16; + } + } + else // 16x16 tiles mode is selected + { + if (m_supports_16x16) + { + tm = m_pf16x16_tilemap[tm_dimensions]; + bppmult = m_bppmult_16x16; + bppmask = m_bppmask_16x16; + } + else if (m_supports_8x8) + { + tm = m_pf8x8_tilemap[tm_dimensions]; + bppmult = m_bppmult_8x8; + bppmask = m_bppmask_8x8; + } + } + + if (tm) + custom_tilemap_draw(bitmap,screen.priority(),cliprect,tm,m_pf_rowscroll.get(),m_pf_colscroll.get(),m_pf_control_0,m_pf_control_1,flags, penmask, pencondition, colprimask, colpricondition, bppmult, bppmask, pri, primask); +} + +// 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(screen_device &screen,bitmap_ind16 &bitmap,const rectangle &cliprect,int flags, int mode, int type, u8 pri, u8 primask) +{ + tilemap_t* tm = nullptr; + u8 bppmult, bppmask; + if (!mode) + { + tm = m_pf8x8_tilemap[type]; + bppmult = m_bppmult_8x8; + bppmask = m_bppmask_8x8; + } + else + { + tm = m_pf16x16_tilemap[type]; + bppmult = m_bppmult_16x16; + bppmask = m_bppmask_16x16; + } + + custom_tilemap_draw(bitmap,screen.priority(),cliprect,tm,m_pf_rowscroll.get(),m_pf_colscroll.get(),nullptr,nullptr,flags, 0, 0, 0, 0, bppmult, bppmask, pri, primask); +} + + + +void deco_bac06_device::pf_control_0_w(offs_t offset, u16 data, u16 mem_mask) +{ + int old_register0 = m_pf_control_0[0]; + + offset &= 3; + + COMBINE_DATA(&m_pf_control_0[offset]); + + bool dirty_all = false; + if (offset == 0) + { + if ((old_register0 & 2) != (m_pf_control_0[offset] & 2)) + { + // The tilemap has changed from row major to column major or vice versa. + // Must force an update of the mapping. + for (int i = 0; i < 3; i++) + { + m_pf8x8_tilemap[i]->mark_mapping_dirty(); + m_pf16x16_tilemap[i]->mark_mapping_dirty(); + } + dirty_all = 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")) + logerror("tilemap ram bank change to %02x\n", newbank & 1); + + dirty_all = true; + m_rambank = newbank & 1; + } + } + + if (dirty_all) + { + for (int i = 0; i < 3; i++) + { + m_pf8x8_tilemap[i]->mark_all_dirty(); + m_pf16x16_tilemap[i]->mark_all_dirty(); + } + } +} + +u16 deco_bac06_device::pf_control_1_r(offs_t offset) +{ + offset &= 7; + return m_pf_control_1[offset]; +} + +void deco_bac06_device::pf_control_1_w(offs_t offset, u16 data, u16 mem_mask) +{ + offset &= 7; + COMBINE_DATA(&m_pf_control_1[offset]); +} + +void deco_bac06_device::pf_data_w(offs_t offset, u16 data, u16 mem_mask) +{ + if (m_rambank & 1) offset += 0x1000; + + COMBINE_DATA(&m_pf_data[offset]); + + for (int i = 0; i < 3; i++) + { + m_pf8x8_tilemap[i]->mark_tile_dirty(offset); + m_pf16x16_tilemap[i]->mark_tile_dirty(offset); + } +} + +u16 deco_bac06_device::pf_data_r(offs_t offset) +{ + if (m_rambank & 1) offset += 0x1000; + + return m_pf_data[offset]; +} + +void deco_bac06_device::pf_data_8bit_w(offs_t offset, u8 data) +{ + if (offset & 1) + pf_data_w(offset / 2, data, 0x00ff); + else + pf_data_w(offset / 2, data << 8, 0xff00); +} + +u8 deco_bac06_device::pf_data_8bit_r(offs_t offset) +{ + if (offset & 1) /* MSB */ + return pf_data_r(offset / 2); + else + return pf_data_r(offset / 2)>>8; +} + +void deco_bac06_device::pf_rowscroll_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_pf_rowscroll[offset]); +} + +void deco_bac06_device::pf_colscroll_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_pf_colscroll[offset]); +} + +u16 deco_bac06_device::pf_rowscroll_r(offs_t offset) +{ + return m_pf_rowscroll[offset]; +} + +u16 deco_bac06_device::pf_colscroll_r(offs_t offset) +{ + return m_pf_colscroll[offset]; +} + +/* used by dec8.cpp */ +void deco_bac06_device::pf_control0_8bit_w(offs_t offset, u8 data) +{ + if (offset & 1) + pf_control_0_w(offset / 2, data, 0x00ff); // oscar (mirrors?) + else + pf_control_0_w(offset / 2, data, 0x00ff); +} + +/* used by dec8.cpp */ +u8 deco_bac06_device::pf_control1_8bit_r(offs_t offset) +{ + if (offset & 1) + return pf_control_1_r(offset / 2); + else + return pf_control_1_r(offset / 2)>>8; +} + +/* used by dec8.cpp */ +void deco_bac06_device::pf_control1_8bit_w(offs_t offset, u8 data) +{ + if (offset<4) // these registers are 16-bit? + { + if (offset & 1) + pf_control_1_w(offset / 2, data, 0x00ff); + else + pf_control_1_w(offset / 2, data << 8, 0xff00); + } + else // these registers are 8-bit and mirror? (triothep vs actfancr) + { + if (offset & 1) + pf_control_1_w(offset / 2, data, 0x00ff); + else + pf_control_1_w(offset / 2, data, 0x00ff); + } +} + +u8 deco_bac06_device::pf_rowscroll_8bit_r(offs_t offset) +{ + if (offset & 1) + return pf_rowscroll_r(offset / 2); + else + return pf_rowscroll_r(offset / 2)>>8; +} + + +void deco_bac06_device::pf_rowscroll_8bit_w(offs_t offset, u8 data) +{ + if (offset & 1) + pf_rowscroll_w(offset / 2, data, 0x00ff); + else + pf_rowscroll_w(offset / 2, data << 8, 0xff00); +} + +u8 deco_bac06_device::pf_rowscroll_8bit_swap_r(offs_t offset) +{ + if (offset & 1) + return pf_rowscroll_r(offset / 2)>>8; + else + return pf_rowscroll_r(offset / 2); +} + +void deco_bac06_device::pf_rowscroll_8bit_swap_w(offs_t offset, u8 data) +{ + if (offset & 1) + pf_rowscroll_w(offset / 2, data << 8, 0xff00); + else + pf_rowscroll_w(offset / 2, data, 0x00ff); +} + + +/* used by hippodrm */ +void deco_bac06_device::pf_control0_8bit_packed_w(offs_t offset, u8 data) +{ + if (offset & 1) + pf_control_0_w(offset / 2, data << 8, 0xff00); + else + pf_control_0_w(offset / 2, data, 0x00ff); +} + +/* used by hippodrm */ +void deco_bac06_device::pf_control1_8bit_swap_w(offs_t offset, u8 data) +{ + pf_control1_8bit_w(offset ^ 1, data); +} + +/* used by hippodrm */ +u8 deco_bac06_device::pf_data_8bit_swap_r(offs_t offset) +{ + return pf_data_8bit_r(offset ^ 1); +} + +/* used by hippodrm */ +void deco_bac06_device::pf_data_8bit_swap_w(offs_t offset, u8 data) +{ + pf_data_8bit_w(offset ^ 1, data); +} |