summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/tilemap.c
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-11-08 12:56:12 +0100
committer Miodrag Milanovic <mmicko@gmail.com>2015-11-08 12:56:12 +0100
commit7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch)
treef310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/emu/tilemap.c
parenta57b46ae933badd7441ce1644711dbb851e2b504 (diff)
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/emu/tilemap.c')
-rw-r--r--src/emu/tilemap.c1799
1 files changed, 0 insertions, 1799 deletions
diff --git a/src/emu/tilemap.c b/src/emu/tilemap.c
deleted file mode 100644
index 6f61210355b..00000000000
--- a/src/emu/tilemap.c
+++ /dev/null
@@ -1,1799 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-/***************************************************************************
-
- tilemap.c
-
- Generic tilemap management system.
-
-***************************************************************************/
-
-#include "emu.h"
-
-
-//**************************************************************************
-// INLINE FUNCTIONS
-//**************************************************************************
-
-//-------------------------------------------------
-// effective_rowscroll - return the effective
-// rowscroll value for a given index, taking into
-// account tilemap flip states
-//-------------------------------------------------
-
-inline INT32 tilemap_t::effective_rowscroll(int index, UINT32 screen_width)
-{
- // if we're flipping vertically, adjust the row number
- if (m_attributes & TILEMAP_FLIPY)
- index = m_scrollrows - 1 - index;
-
- // adjust final result based on the horizontal flip and dx values
- INT32 value;
- if (!(m_attributes & TILEMAP_FLIPX))
- value = m_dx - m_rowscroll[index];
- else
- value = screen_width - m_width - (m_dx_flipped - m_rowscroll[index]);
-
- // clamp to 0..width
- if (value < 0)
- value = m_width - (-value) % m_width;
- else
- value %= m_width;
- return value;
-}
-
-
-//-------------------------------------------------
-// effective_colscroll - return the effective
-// colscroll value for a given index, taking into
-// account tilemap flip states
-//-------------------------------------------------
-
-inline INT32 tilemap_t::effective_colscroll(int index, UINT32 screen_height)
-{
- // if we're flipping horizontally, adjust the column number
- if (m_attributes & TILEMAP_FLIPX)
- index = m_scrollcols - 1 - index;
-
- // adjust final result based on the vertical flip and dx values
- INT32 value;
- if (!(m_attributes & TILEMAP_FLIPY))
- value = m_dy - m_colscroll[index];
- else
- value = screen_height - m_height - (m_dy_flipped - m_colscroll[index]);
-
- // clamp to 0..height
- if (value < 0)
- value = m_height - (-value) % m_height;
- else
- value %= m_height;
- return value;
-}
-
-
-//-------------------------------------------------
-// gfx_tiles_changed - return TRUE if any
-// gfx_elements used by this tilemap have
-// changed
-//-------------------------------------------------
-
-inline bool tilemap_t::gfx_elements_changed()
-{
- UINT32 usedmask = m_gfx_used;
- bool isdirty = false;
-
- // iterate over all used gfx types and set the dirty flag if any of them have changed
- for (int gfxnum = 0; usedmask != 0; usedmask >>= 1, gfxnum++)
- if ((usedmask & 1) != 0)
- if (m_gfx_dirtyseq[gfxnum] != m_tileinfo.decoder->gfx(gfxnum)->dirtyseq())
- {
- m_gfx_dirtyseq[gfxnum] = m_tileinfo.decoder->gfx(gfxnum)->dirtyseq();
- isdirty = true;
- }
-
- return isdirty;
-}
-
-
-//**************************************************************************
-// SCANLINE RASTERIZERS
-//**************************************************************************
-
-//-------------------------------------------------
-// scanline_draw_opaque_null - draw to a NULL
-// bitmap, setting priority only
-//-------------------------------------------------
-
-inline void tilemap_t::scanline_draw_opaque_null(int count, UINT8 *pri, UINT32 pcode)
-{
- // skip entirely if not changing priority
- if (pcode == 0xff00)
- return;
-
- // update priority across the scanline
- for (int i = 0; i < count; i++)
- pri[i] = (pri[i] & (pcode >> 8)) | pcode;
-}
-
-
-//-------------------------------------------------
-// scanline_draw_masked_null - draw to a NULL
-// bitmap using a mask, setting priority only
-//-------------------------------------------------
-
-inline void tilemap_t::scanline_draw_masked_null(const UINT8 *maskptr, int mask, int value, int count, UINT8 *pri, UINT32 pcode)
-{
- // skip entirely if not changing priority
- if (pcode == 0xff00)
- return;
-
- // update priority across the scanline, checking the mask
- for (int i = 0; i < count; i++)
- if ((maskptr[i] & mask) == value)
- pri[i] = (pri[i] & (pcode >> 8)) | pcode;
-}
-
-
-
-//-------------------------------------------------
-// scanline_draw_opaque_ind16 - draw to a 16bpp
-// indexed bitmap
-//-------------------------------------------------
-
-inline void tilemap_t::scanline_draw_opaque_ind16(UINT16 *dest, const UINT16 *source, int count, UINT8 *pri, UINT32 pcode)
-{
- // special case for no palette offset
- int pal = pcode >> 16;
- if (pal == 0)
- {
- // use memcpy which should be well-optimized for the platform
- memcpy(dest, source, count * 2);
-
- // skip the rest if not changing priority
- if (pcode == 0xff00)
- return;
-
- // update priority across the scanline
- for (int i = 0; i < count; i++)
- pri[i] = (pri[i] & (pcode >> 8)) | pcode;
- }
-
- // priority case
- else if ((pcode & 0xffff) != 0xff00)
- {
- for (int i = 0; i < count; i++)
- {
- dest[i] = source[i] + pal;
- pri[i] = (pri[i] & (pcode >> 8)) | pcode;
- }
- }
-
- // no priority case
- else
- {
- for (int i = 0; i < count; i++)
- dest[i] = source[i] + pal;
- }
-}
-
-
-//-------------------------------------------------
-// scanline_draw_masked_ind16 - draw to a 16bpp
-// indexed bitmap using a mask
-//-------------------------------------------------
-
-inline void tilemap_t::scanline_draw_masked_ind16(UINT16 *dest, const UINT16 *source, const UINT8 *maskptr, int mask, int value, int count, UINT8 *pri, UINT32 pcode)
-{
- int pal = pcode >> 16;
-
- // priority case
- if ((pcode & 0xffff) != 0xff00)
- {
- for (int i = 0; i < count; i++)
- if ((maskptr[i] & mask) == value)
- {
- dest[i] = source[i] + pal;
- pri[i] = (pri[i] & (pcode >> 8)) | pcode;
- }
- }
-
- // no priority case
- else
- {
- for (int i = 0; i < count; i++)
- if ((maskptr[i] & mask) == value)
- dest[i] = source[i] + pal;
- }
-}
-
-
-
-//-------------------------------------------------
-// scanline_draw_opaque_rgb32 - draw to a 32bpp
-// RGB bitmap
-//-------------------------------------------------
-
-inline void tilemap_t::scanline_draw_opaque_rgb32(UINT32 *dest, const UINT16 *source, int count, const rgb_t *pens, UINT8 *pri, UINT32 pcode)
-{
- const rgb_t *clut = &pens[pcode >> 16];
-
- // priority case
- if ((pcode & 0xffff) != 0xff00)
- {
- for (int i = 0; i < count; i++)
- {
- dest[i] = clut[source[i]];
- pri[i] = (pri[i] & (pcode >> 8)) | pcode;
- }
- }
-
- // no priority case
- else
- {
- for (int i = 0; i < count; i++)
- dest[i] = clut[source[i]];
- }
-}
-
-
-//-------------------------------------------------
-// scanline_draw_masked_rgb32 - draw to a 32bpp
-// RGB bitmap using a mask
-//-------------------------------------------------
-
-inline void tilemap_t::scanline_draw_masked_rgb32(UINT32 *dest, const UINT16 *source, const UINT8 *maskptr, int mask, int value, int count, const rgb_t *pens, UINT8 *pri, UINT32 pcode)
-{
- const rgb_t *clut = &pens[pcode >> 16];
-
- // priority case
- if ((pcode & 0xffff) != 0xff00)
- {
- for (int i = 0; i < count; i++)
- if ((maskptr[i] & mask) == value)
- {
- dest[i] = clut[source[i]];
- pri[i] = (pri[i] & (pcode >> 8)) | pcode;
- }
- }
-
- // no priority case
- else
- {
- for (int i = 0; i < count; i++)
- if ((maskptr[i] & mask) == value)
- dest[i] = clut[source[i]];
- }
-}
-
-
-//-------------------------------------------------
-// scanline_draw_opaque_rgb32_alpha - draw to a
-// 32bpp RGB bitmap with alpha blending
-//-------------------------------------------------
-
-inline void tilemap_t::scanline_draw_opaque_rgb32_alpha(UINT32 *dest, const UINT16 *source, int count, const rgb_t *pens, UINT8 *pri, UINT32 pcode, UINT8 alpha)
-{
- const rgb_t *clut = &pens[pcode >> 16];
-
- // priority case
- if ((pcode & 0xffff) != 0xff00)
- {
- for (int i = 0; i < count; i++)
- {
- dest[i] = alpha_blend_r32(dest[i], clut[source[i]], alpha);
- pri[i] = (pri[i] & (pcode >> 8)) | pcode;
- }
- }
-
- // no priority case
- else
- {
- for (int i = 0; i < count; i++)
- dest[i] = alpha_blend_r32(dest[i], clut[source[i]], alpha);
- }
-}
-
-
-//-------------------------------------------------
-// scanline_draw_masked_rgb32_alpha - draw to a
-// 32bpp RGB bitmap using a mask and alpha
-// blending
-//-------------------------------------------------
-
-inline void tilemap_t::scanline_draw_masked_rgb32_alpha(UINT32 *dest, const UINT16 *source, const UINT8 *maskptr, int mask, int value, int count, const rgb_t *pens, UINT8 *pri, UINT32 pcode, UINT8 alpha)
-{
- const rgb_t *clut = &pens[pcode >> 16];
-
- // priority case
- if ((pcode & 0xffff) != 0xff00)
- {
- for (int i = 0; i < count; i++)
- if ((maskptr[i] & mask) == value)
- {
- dest[i] = alpha_blend_r32(dest[i], clut[source[i]], alpha);
- pri[i] = (pri[i] & (pcode >> 8)) | pcode;
- }
- }
-
- // no priority case
- else
- {
- for (int i = 0; i < count; i++)
- if ((maskptr[i] & mask) == value)
- dest[i] = alpha_blend_r32(dest[i], clut[source[i]], alpha);
- }
-}
-
-
-//**************************************************************************
-// TILEMAP CREATION AND CONFIGURATION
-//**************************************************************************
-
-//-------------------------------------------------
-// tilemap_t - constructor
-//-------------------------------------------------
-
-tilemap_t::tilemap_t()
-{
- // until init() is called, data is floating; this is deliberate
-}
-
-
-//-------------------------------------------------
-// init - initialize the tilemap
-//-------------------------------------------------
-
-tilemap_t &tilemap_t::init(tilemap_manager &manager, device_gfx_interface &decoder, tilemap_get_info_delegate tile_get_info, tilemap_mapper_delegate mapper, int tilewidth, int tileheight, int cols, int rows)
-{
- // populate managers and devices
- m_manager = &manager;
- m_device = dynamic_cast<tilemap_device *>(this);
- m_palette = decoder.palette();
- m_next = NULL;
- m_user_data = NULL;
-
- // populate tilemap metrics
- m_rows = rows;
- m_cols = cols;
- m_tilewidth = tilewidth;
- m_tileheight = tileheight;
- m_width = cols * tilewidth;
- m_height = rows * tileheight;
-
- // populate logical <-> memory mappings
- m_mapper = mapper;
-
- // initialize tile information geters
- m_tile_get_info = tile_get_info;
-
- // reset global states
- m_enable = true;
- m_attributes = 0;
- m_all_tiles_dirty = true;
- m_all_tiles_clean = false;
- m_palette_offset = 0;
- m_gfx_used = 0;
- memset(m_gfx_dirtyseq, 0, sizeof(m_gfx_dirtyseq));
-
- // reset scroll information
- m_scrollrows = 1;
- m_scrollcols = 1;
- m_rowscroll.resize(m_height);
- memset(&m_rowscroll[0], 0, m_height*sizeof(m_rowscroll[0]));
- m_colscroll.resize(m_width);
- memset(&m_colscroll[0], 0, m_width*sizeof(m_colscroll[0]));
- m_dx = 0;
- m_dx_flipped = 0;
- m_dy = 0;
- m_dy_flipped = 0;
-
- // allocate pixmap
- m_pixmap.allocate(m_width, m_height);
-
- // allocate transparency mapping
- m_flagsmap.allocate(m_width, m_height);
- memset(m_pen_to_flags, 0, sizeof(m_pen_to_flags));
-
- // create the initial mappings
- mappings_create();
-
- // set up the default tile data
- memset(&m_tileinfo, 0, sizeof(m_tileinfo));
- m_tileinfo.decoder = &decoder;
- m_tileinfo.pen_mask = 0xff;
- m_tileinfo.gfxnum = 0xff;
-
- // allocate transparency mapping data
- for (int group = 0; group < TILEMAP_NUM_GROUPS; group++)
- map_pens_to_layer(group, 0, 0, TILEMAP_PIXEL_LAYER0);
-
- // save relevant state
- int instance = manager.alloc_instance();
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_enable));
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_attributes));
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_palette_offset));
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_scrollrows));
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_scrollcols));
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_rowscroll));
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_colscroll));
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_dx));
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_dx_flipped));
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_dy));
- machine().save().save_item(m_device, "tilemap", NULL, instance, NAME(m_dy_flipped));
-
- // reset everything after a load
- machine().save().register_postload(save_prepost_delegate(FUNC(tilemap_t::postload), this));
- return *this;
-}
-
-
-//-------------------------------------------------
-// ~tilemap_t - destructor
-//-------------------------------------------------
-
-tilemap_t::~tilemap_t()
-{
-}
-
-
-//-------------------------------------------------
-// mark_tile_dirty - mark a single tile dirty
-// based on its memory index
-//-------------------------------------------------
-
-void tilemap_t::mark_tile_dirty(tilemap_memory_index memindex)
-{
- // only mark if within range
- if (memindex < m_memory_to_logical.size())
- {
- // there may be no logical index for a given memory index
- logical_index logindex = m_memory_to_logical[memindex];
- if (logindex != INVALID_LOGICAL_INDEX)
- {
- m_tileflags[logindex] = TILE_FLAG_DIRTY;
- m_all_tiles_clean = false;
- }
- }
-}
-
-
-//-------------------------------------------------
-// map_pens_to_layer - specify the mapping of one
-// or more pens (where (<pen> & mask) == pen) to
-// a layer
-//-------------------------------------------------
-
-void tilemap_t::map_pens_to_layer(int group, pen_t pen, pen_t mask, UINT8 layermask)
-{
- assert(group < TILEMAP_NUM_GROUPS);
- assert((layermask & TILEMAP_PIXEL_CATEGORY_MASK) == 0);
-
- // we start at the index where (pen & mask) == pen, and all other bits are 0
- pen_t start = pen & mask;
-
- // we stop at the index where (pen & mask) == pen, and all other bits are 1
- pen_t stop = start | ~mask;
-
- // clamp to the number of entries actually there
- stop = MIN(stop, MAX_PEN_TO_FLAGS - 1);
-
- // iterate and set
- UINT8 *array = m_pen_to_flags + group * MAX_PEN_TO_FLAGS;
- bool changed = false;
- for (pen_t cur = start; cur <= stop; cur++)
- if ((cur & mask) == pen && array[cur] != layermask)
- {
- changed = true;
- array[cur] = layermask;
- }
-
- // everything gets dirty if anything changed
- if (changed)
- mark_all_dirty();
-}
-
-
-//-------------------------------------------------
-// set_transparent_pen - set a single transparent
-// pen into the tilemap, mapping all other pens
-// to layer 0
-//-------------------------------------------------
-
-void tilemap_t::set_transparent_pen(pen_t pen)
-{
- // reset the whole pen map to opaque
- map_pens_to_layer(0, 0, 0, TILEMAP_PIXEL_LAYER0);
-
- // set the single pen to transparent
- map_pen_to_layer(0, pen, TILEMAP_PIXEL_TRANSPARENT);
-}
-
-
-//-------------------------------------------------
-// set_transmask - set up the first 32 pens using
-// a foreground mask (mapping to layer 0) and a
-// background mask (mapping to layer 1)
-//-------------------------------------------------
-
-void tilemap_t::set_transmask(int group, UINT32 fgmask, UINT32 bgmask)
-{
- // iterate over all 32 pens specified
- for (pen_t pen = 0; pen < 32; pen++)
- {
- UINT8 fgbits = ((fgmask >> pen) & 1) ? TILEMAP_PIXEL_TRANSPARENT : TILEMAP_PIXEL_LAYER0;
- UINT8 bgbits = ((bgmask >> pen) & 1) ? TILEMAP_PIXEL_TRANSPARENT : TILEMAP_PIXEL_LAYER1;
- map_pen_to_layer(group, pen, fgbits | bgbits);
- }
-}
-
-
-//-------------------------------------------------
-// configure_groups - configure groups so that
-// when group == color, pens whose indirect value
-// matches the given transcolor are transparent
-//-------------------------------------------------
-
-void tilemap_t::configure_groups(gfx_element &gfx, int transcolor)
-{
- int color;
-
- assert(gfx.colors() <= TILEMAP_NUM_GROUPS);
-
- // iterate over all colors in the tilemap
- for (color = 0; color < gfx.colors(); color++)
- set_transmask(color, m_palette->transpen_mask(gfx, color, transcolor), 0);
-}
-
-
-
-//**************************************************************************
-// COMMON LOGICAL-TO-MEMORY MAPPERS
-//**************************************************************************
-
-//-------------------------------------------------
-// scan_rows
-// scan_rows_flip_x
-// scan_rows_flip_y
-// scan_rows_flip_xy - scan in row-major
-// order with optional flipping
-//-------------------------------------------------
-
-tilemap_memory_index tilemap_t::scan_rows(driver_device &device, UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows)
-{
- return row * num_cols + col;
-}
-
-tilemap_memory_index tilemap_t::scan_rows_flip_x(driver_device &device, UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows)
-{
- return row * num_cols + (num_cols - 1 - col);
-}
-
-tilemap_memory_index tilemap_t::scan_rows_flip_y(driver_device &device, UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows)
-{
- return (num_rows - 1 - row) * num_cols + col;
-}
-
-tilemap_memory_index tilemap_t::scan_rows_flip_xy(driver_device &device, UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows)
-{
- return (num_rows - 1 - row) * num_cols + (num_cols - 1 - col);
-}
-
-
-//-------------------------------------------------
-// scan_cols
-// scan_cols_flip_x
-// scan_cols_flip_y
-// scan_cols_flip_xy - scan in column-
-// major order with optional flipping
-//-------------------------------------------------
-
-tilemap_memory_index tilemap_t::scan_cols(driver_device &device, UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows)
-{
- return col * num_rows + row;
-}
-
-tilemap_memory_index tilemap_t::scan_cols_flip_x(driver_device &device, UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows)
-{
- return (num_cols - 1 - col) * num_rows + row;
-}
-
-tilemap_memory_index tilemap_t::scan_cols_flip_y(driver_device &device, UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows)
-{
- return col * num_rows + (num_rows - 1 - row);
-}
-
-tilemap_memory_index tilemap_t::scan_cols_flip_xy(driver_device &device, UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows)
-{
- return (num_cols - 1 - col) * num_rows + (num_rows - 1 - row);
-}
-
-
-//-------------------------------------------------
-// postload - after loading a save state
-// invalidate everything
-//-------------------------------------------------
-
-void tilemap_t::postload()
-{
- mappings_update();
-}
-
-
-
-//**************************************************************************
-// LOGICAL <-> MEMORY INDEX MAPPING
-//**************************************************************************
-
-//-------------------------------------------------
-// mappings_create - allocate memory for the
-// mapping tables and compute their extents
-//-------------------------------------------------
-
-void tilemap_t::mappings_create()
-{
- // compute the maximum logical index
- int max_logical_index = m_rows * m_cols;
-
- // compute the maximum memory index
- int max_memory_index = 0;
- for (UINT32 row = 0; row < m_rows; row++)
- for (UINT32 col = 0; col < m_cols; col++)
- {
- tilemap_memory_index memindex = memory_index(col, row);
- max_memory_index = MAX(max_memory_index, memindex);
- }
- max_memory_index++;
-
- // allocate the necessary mappings
- m_memory_to_logical.resize(max_memory_index);
- m_logical_to_memory.resize(max_logical_index);
- m_tileflags.resize(max_logical_index);
-
- // update the mappings
- mappings_update();
-}
-
-
-//-------------------------------------------------
-// mappings_update - update the mappings after
-// a major change (flip x/y changes)
-//-------------------------------------------------
-
-void tilemap_t::mappings_update()
-{
- // initialize all the mappings to invalid values
- memset(&m_memory_to_logical[0], 0xff, m_memory_to_logical.size() * sizeof(m_memory_to_logical[0]));
-
- // now iterate over all logical indexes and populate the memory index
- for (logical_index logindex = 0; logindex < m_logical_to_memory.size(); logindex++)
- {
- UINT32 logical_col = logindex % m_cols;
- UINT32 logical_row = logindex / m_cols;
- tilemap_memory_index memindex = memory_index(logical_col, logical_row);
-
- // apply tilemap flip to get the final location to store
- if (m_attributes & TILEMAP_FLIPX)
- logical_col = (m_cols - 1) - logical_col;
- if (m_attributes & TILEMAP_FLIPY)
- logical_row = (m_rows - 1) - logical_row;
- UINT32 flipped_logindex = logical_row * m_cols + logical_col;
-
- // fill in entries in both arrays
- m_memory_to_logical[memindex] = flipped_logindex;
- m_logical_to_memory[flipped_logindex] = memindex;
- }
-
- // mark the whole tilemap dirty
- mark_all_dirty();
-}
-
-
-
-//**************************************************************************
-// TILE RENDERING
-//**************************************************************************
-
-inline void tilemap_t::realize_all_dirty_tiles()
-{
- // if all the tiles are marked dirty, or something in the gfx has changed,
- // flush the dirty status to all tiles
- if (m_all_tiles_dirty || gfx_elements_changed())
- {
- memset(&m_tileflags[0], TILE_FLAG_DIRTY, m_tileflags.size());
- m_all_tiles_dirty = false;
- m_gfx_used = 0;
- }
-}
-
-//-------------------------------------------------
-// pixmap_update - update the entire pixmap
-//-------------------------------------------------
-
-void tilemap_t::pixmap_update()
-{
- // if the graphics changed, we need to mark everything dirty
- if (gfx_elements_changed())
- mark_all_dirty();
-
- // if everything is clean, do nothing
- if (m_all_tiles_clean)
- return;
-
-g_profiler.start(PROFILER_TILEMAP_DRAW);
-
- // flush the dirty state to all tiles as appropriate
- realize_all_dirty_tiles();
-
- // iterate over rows and columns
- logical_index logindex = 0;
- for (int row = 0; row < m_rows; row++)
- for (int col = 0; col < m_cols; col++, logindex++)
- if (m_tileflags[logindex] == TILE_FLAG_DIRTY)
- tile_update(logindex, col, row);
-
- // mark it all clean
- m_all_tiles_clean = true;
-
-g_profiler.stop();
-}
-
-
-//-------------------------------------------------
-// tile_update - update a single dirty tile
-//-------------------------------------------------
-
-void tilemap_t::tile_update(logical_index logindex, UINT32 col, UINT32 row)
-{
-g_profiler.start(PROFILER_TILEMAP_UPDATE);
-
- // call the get info callback for the associated memory index
- tilemap_memory_index memindex = m_logical_to_memory[logindex];
- m_tile_get_info(*this, m_tileinfo, memindex);
-
- // apply the global tilemap flip to the returned flip flags
- UINT32 flags = m_tileinfo.flags ^ (m_attributes & 0x03);
-
- // draw the tile, using either direct or transparent
- UINT32 x0 = m_tilewidth * col;
- UINT32 y0 = m_tileheight * row;
- m_tileflags[logindex] = tile_draw(m_tileinfo.pen_data, x0, y0,
- m_tileinfo.palette_base, m_tileinfo.category, m_tileinfo.group, flags, m_tileinfo.pen_mask);
-
- // if mask data is specified, apply it
- if ((flags & (TILE_FORCE_LAYER0 | TILE_FORCE_LAYER1 | TILE_FORCE_LAYER2)) == 0 && m_tileinfo.mask_data != NULL)
- m_tileflags[logindex] = tile_apply_bitmask(m_tileinfo.mask_data, x0, y0, m_tileinfo.category, flags);
-
- // track which gfx have been used for this tilemap
- if (m_tileinfo.gfxnum != 0xff && (m_gfx_used & (1 << m_tileinfo.gfxnum)) == 0)
- {
- m_gfx_used |= 1 << m_tileinfo.gfxnum;
- m_gfx_dirtyseq[m_tileinfo.gfxnum] = m_tileinfo.decoder->gfx(m_tileinfo.gfxnum)->dirtyseq();
- }
-
-g_profiler.stop();
-}
-
-
-//-------------------------------------------------
-// tile_draw - draw a single tile to the
-// tilemap's internal pixmap, using the pen as
-// the pen_to_flags lookup value, and adding
-// the palette_base
-//-------------------------------------------------
-
-UINT8 tilemap_t::tile_draw(const UINT8 *pendata, UINT32 x0, UINT32 y0, UINT32 palette_base, UINT8 category, UINT8 group, UINT8 flags, UINT8 pen_mask)
-{
- // OR in the force layer flags
- category |= flags & (TILE_FORCE_LAYER0 | TILE_FORCE_LAYER1 | TILE_FORCE_LAYER2);
-
- // if we're vertically flipped, point to the bottom row and work backwards
- int dy0 = 1;
- if (flags & TILE_FLIPY)
- {
- y0 += m_tileheight - 1;
- dy0 = -1;
- }
-
- // if we're horizontally flipped, point to the rightmost column and work backwards
- int dx0 = 1;
- if (flags & TILE_FLIPX)
- {
- x0 += m_tilewidth - 1;
- dx0 = -1;
- }
-
- // iterate over rows
- const UINT8 *penmap = m_pen_to_flags + group * MAX_PEN_TO_FLAGS;
- UINT8 andmask = ~0, ormask = 0;
- for (int ty = 0; ty < m_tileheight; ty++)
- {
- UINT16 *pixptr = &m_pixmap.pix16(y0, x0);
- UINT8 *flagsptr = &m_flagsmap.pix8(y0, x0);
-
- // pre-advance to the next row
- y0 += dy0;
-
- // 8bpp data
- for (int tx = 0, xoffs = 0; tx < m_tilewidth; tx++, xoffs += dx0)
- {
- UINT8 pen = (*pendata++) & pen_mask;
- UINT8 map = penmap[pen];
- pixptr[xoffs] = palette_base + pen;
- flagsptr[xoffs] = map | category;
- andmask &= map;
- ormask |= map;
- }
- }
- return andmask ^ ormask;
-}
-
-
-//-------------------------------------------------
-// tile_apply_bitmask - apply a bitmask to an
-// already-rendered tile by modifying the
-// flagsmap appropriately
-//-------------------------------------------------
-
-UINT8 tilemap_t::tile_apply_bitmask(const UINT8 *maskdata, UINT32 x0, UINT32 y0, UINT8 category, UINT8 flags)
-{
- // if we're vertically flipped, point to the bottom row and work backwards
- int dy0 = 1;
- if (flags & TILE_FLIPY)
- {
- y0 += m_tileheight - 1;
- dy0 = -1;
- }
-
- // if we're horizontally flipped, point to the rightmost column and work backwards
- int dx0 = 1;
- if (flags & TILE_FLIPX)
- {
- x0 += m_tilewidth - 1;
- dx0 = -1;
- }
-
- // iterate over rows
- UINT8 andmask = ~0, ormask = 0;
- int bitoffs = 0;
- for (int ty = 0; ty < m_tileheight; ty++)
- {
- // pre-advance to the next row
- UINT8 *flagsptr = &m_flagsmap.pix8(y0, x0);
- y0 += dy0;
-
- // anywhere the bitmask is 0 should be transparent
- for (int tx = 0, xoffs = 0; tx < m_tilewidth; tx++, xoffs += dx0)
- {
- UINT8 map = flagsptr[xoffs];
-
- if ((maskdata[bitoffs / 8] & (0x80 >> (bitoffs & 7))) == 0)
- map = flagsptr[xoffs] = TILEMAP_PIXEL_TRANSPARENT | category;
- andmask &= map;
- ormask |= map;
- bitoffs++;
- }
- }
- return andmask ^ ormask;
-}
-
-
-
-//**************************************************************************
-// DRAWING HELPERS
-//**************************************************************************
-
-//-------------------------------------------------
-// configure_blit_parameters - fill in the
-// standard blit parameters based on the input
-// data; this code is shared by normal, roz,
-// and indexed drawing code
-//-------------------------------------------------
-
-void tilemap_t::configure_blit_parameters(blit_parameters &blit, bitmap_ind8 &priority_bitmap, const rectangle &cliprect, UINT32 flags, UINT8 priority, UINT8 priority_mask)
-{
- // set the target bitmap
- blit.priority = &priority_bitmap;
- blit.cliprect = cliprect;
-
- // set the priority code and alpha
- blit.tilemap_priority_code = priority | (priority_mask << 8) | (m_palette_offset << 16);
- blit.alpha = (flags & TILEMAP_DRAW_ALPHA_FLAG) ? (flags >> 24) : 0xff;
-
- // tile priority; unless otherwise specified, draw anything in layer 0
- blit.mask = TILEMAP_PIXEL_CATEGORY_MASK;
- blit.value = flags & TILEMAP_PIXEL_CATEGORY_MASK;
-
- // if no layers specified, draw layer 0
- if ((flags & (TILEMAP_DRAW_LAYER0 | TILEMAP_DRAW_LAYER1 | TILEMAP_DRAW_LAYER2)) == 0)
- flags |= TILEMAP_DRAW_LAYER0;
-
- // OR in the bits from the draw masks
- blit.mask |= flags & (TILEMAP_DRAW_LAYER0 | TILEMAP_DRAW_LAYER1 | TILEMAP_DRAW_LAYER2);
- blit.value |= flags & (TILEMAP_DRAW_LAYER0 | TILEMAP_DRAW_LAYER1 | TILEMAP_DRAW_LAYER2);
-
- // for all-opaque rendering, don't check any of the layer bits
- if (flags & TILEMAP_DRAW_OPAQUE)
- {
- blit.mask &= ~(TILEMAP_PIXEL_LAYER0 | TILEMAP_PIXEL_LAYER1 | TILEMAP_PIXEL_LAYER2);
- blit.value &= ~(TILEMAP_PIXEL_LAYER0 | TILEMAP_PIXEL_LAYER1 | TILEMAP_PIXEL_LAYER2);
- }
-
- // don't check category if requested
- if (flags & TILEMAP_DRAW_ALL_CATEGORIES)
- {
- blit.mask &= ~TILEMAP_PIXEL_CATEGORY_MASK;
- blit.value &= ~TILEMAP_PIXEL_CATEGORY_MASK;
- }
-}
-
-
-//-------------------------------------------------
-// draw_common - draw a tilemap to the
-// destination with clipping; pixels apply
-// priority/priority_mask to the priority bitmap
-//-------------------------------------------------
-
-template<class _BitmapClass>
-void tilemap_t::draw_common(screen_device &screen, _BitmapClass &dest, const rectangle &cliprect, UINT32 flags, UINT8 priority, UINT8 priority_mask)
-{
- // skip if disabled
- if (!m_enable)
- return;
-
-g_profiler.start(PROFILER_TILEMAP_DRAW);
- // configure the blit parameters based on the input parameters
- blit_parameters blit;
- configure_blit_parameters(blit, screen.priority(), cliprect, flags, priority, priority_mask);
-
- // flush the dirty state to all tiles as appropriate
- realize_all_dirty_tiles();
-
- // flip the tilemap around the center of the visible area
- rectangle visarea = screen.visible_area();
- UINT32 width = visarea.min_x + visarea.max_x + 1;
- UINT32 height = visarea.min_y + visarea.max_y + 1;
-
- // XY scrolling playfield
- if (m_scrollrows == 1 && m_scrollcols == 1)
- {
- // iterate to handle wraparound
- int scrollx = effective_rowscroll(0, width);
- int scrolly = effective_colscroll(0, height);
- for (int ypos = scrolly - m_height; ypos <= blit.cliprect.max_y; ypos += m_height)
- for (int xpos = scrollx - m_width; xpos <= blit.cliprect.max_x; xpos += m_width)
- draw_instance(screen, dest, blit, xpos, ypos);
- }
-
- // scrolling rows + vertical scroll
- else if (m_scrollcols == 1)
- {
- const rectangle original_cliprect = blit.cliprect;
-
- // iterate over Y to handle wraparound
- int rowheight = m_height / m_scrollrows;
- int scrolly = effective_colscroll(0, height);
- for (int ypos = scrolly - m_height; ypos <= original_cliprect.max_y; ypos += m_height)
- {
- int const firstrow = MAX((original_cliprect.min_y - ypos) / rowheight, 0);
- int const lastrow = MIN((original_cliprect.max_y - ypos) / rowheight, m_scrollrows - 1);
-
- // iterate over rows in the tilemap
- int nextrow;
- for (int currow = firstrow; currow <= lastrow; currow = nextrow)
- {
- // scan forward until we find a non-matching row
- int scrollx = effective_rowscroll(currow, width);
- for (nextrow = currow + 1; nextrow <= lastrow; nextrow++)
- if (effective_rowscroll(nextrow, width) != scrollx)
- break;
-
- // skip if disabled
- if (scrollx == TILE_LINE_DISABLED)
- continue;
-
- // update the cliprect just for this set of rows
- blit.cliprect.min_y = currow * rowheight + ypos;
- blit.cliprect.max_y = nextrow * rowheight - 1 + ypos;
- blit.cliprect &= original_cliprect;
-
- // iterate over X to handle wraparound
- for (int xpos = scrollx - m_width; xpos <= original_cliprect.max_x; xpos += m_width)
- draw_instance(screen, dest, blit, xpos, ypos);
- }
- }
- }
-
- // scrolling columns + horizontal scroll
- else if (m_scrollrows == 1)
- {
- const rectangle original_cliprect = blit.cliprect;
-
- // iterate over columns in the tilemap
- int scrollx = effective_rowscroll(0, width);
- int colwidth = m_width / m_scrollcols;
- int nextcol;
- for (int curcol = 0; curcol < m_scrollcols; curcol = nextcol)
- {
- // scan forward until we find a non-matching column
- int scrolly = effective_colscroll(curcol, height);
- for (nextcol = curcol + 1; nextcol < m_scrollcols; nextcol++)
- if (effective_colscroll(nextcol, height) != scrolly)
- break;
-
- // skip if disabled
- if (scrolly == TILE_LINE_DISABLED)
- continue;
-
- // iterate over X to handle wraparound
- for (int xpos = scrollx - m_width; xpos <= original_cliprect.max_x; xpos += m_width)
- {
- // update the cliprect just for this set of columns
- blit.cliprect.min_x = curcol * colwidth + xpos;
- blit.cliprect.max_x = nextcol * colwidth - 1 + xpos;
- blit.cliprect &= original_cliprect;
-
- // iterate over Y to handle wraparound
- for (int ypos = scrolly - m_height; ypos <= original_cliprect.max_y; ypos += m_height)
- draw_instance(screen, dest, blit, xpos, ypos);
- }
- }
- }
-g_profiler.stop();
-}
-
-void tilemap_t::draw(screen_device &screen, bitmap_ind16 &dest, const rectangle &cliprect, UINT32 flags, UINT8 priority, UINT8 priority_mask)
-{ draw_common(screen, dest, cliprect, flags, priority, priority_mask); }
-
-void tilemap_t::draw(screen_device &screen, bitmap_rgb32 &dest, const rectangle &cliprect, UINT32 flags, UINT8 priority, UINT8 priority_mask)
-{ draw_common(screen, dest, cliprect, flags, priority, priority_mask); }
-
-
-//-------------------------------------------------
-// draw_roz - draw a tilemap to the destination
-// with clipping and arbitrary rotate/zoom; pixels
-// apply priority/priority_mask to the priority
-// bitmap
-//-------------------------------------------------
-
-template<class _BitmapClass>
-void tilemap_t::draw_roz_common(screen_device &screen, _BitmapClass &dest, const rectangle &cliprect,
- UINT32 startx, UINT32 starty, int incxx, int incxy, int incyx, int incyy,
- bool wraparound, UINT32 flags, UINT8 priority, UINT8 priority_mask)
-{
-// notes:
-// - startx and starty MUST be UINT32 for calculations to work correctly
-// - srcbim_width and height are assumed to be a power of 2 to speed up wraparound
-
- // skip if disabled
- if (!m_enable)
- return;
-
- // see if this is just a regular render and if so, do a regular render
- if (incxx == (1 << 16) && incxy == 0 && incyx == 0 && incyy == (1 << 16) && wraparound)
- {
- set_scrollx(0, startx >> 16);
- set_scrolly(0, starty >> 16);
- draw(screen, dest, cliprect, flags, priority, priority_mask);
- return;
- }
-
-g_profiler.start(PROFILER_TILEMAP_DRAW_ROZ);
- // configure the blit parameters
- blit_parameters blit;
- configure_blit_parameters(blit, screen.priority(), cliprect, flags, priority, priority_mask);
-
- // get the full pixmap for the tilemap
- pixmap();
-
- // then do the roz copy
- draw_roz_core(screen, dest, blit, startx, starty, incxx, incxy, incyx, incyy, wraparound);
-g_profiler.stop();
-}
-
-void tilemap_t::draw_roz(screen_device &screen, bitmap_ind16 &dest, const rectangle &cliprect,
- UINT32 startx, UINT32 starty, int incxx, int incxy, int incyx, int incyy,
- bool wraparound, UINT32 flags, UINT8 priority, UINT8 priority_mask)
-{ draw_roz_common(screen, dest, cliprect, startx, starty, incxx, incxy, incyx, incyy, wraparound, flags, priority, priority_mask); }
-
-void tilemap_t::draw_roz(screen_device &screen, bitmap_rgb32 &dest, const rectangle &cliprect,
- UINT32 startx, UINT32 starty, int incxx, int incxy, int incyx, int incyy,
- bool wraparound, UINT32 flags, UINT8 priority, UINT8 priority_mask)
-{ draw_roz_common(screen, dest, cliprect, startx, starty, incxx, incxy, incyx, incyy, wraparound, flags, priority, priority_mask); }
-
-
-//-------------------------------------------------
-// draw_instance - draw a single instance of the
-// tilemap to the internal pixmap at the given
-// xpos,ypos
-//-------------------------------------------------
-
-template<class _BitmapClass>
-void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const blit_parameters &blit, int xpos, int ypos)
-{
- // clip destination coordinates to the tilemap
- // note that x2/y2 are exclusive, not inclusive
- int x1 = MAX(xpos, blit.cliprect.min_x);
- int x2 = MIN(xpos + (int)m_width, blit.cliprect.max_x + 1);
- int y1 = MAX(ypos, blit.cliprect.min_y);
- int y2 = MIN(ypos + (int)m_height, blit.cliprect.max_y + 1);
-
- // if totally clipped, stop here
- if (x1 >= x2 || y1 >= y2)
- return;
-
- // look up priority and destination base addresses for y1
- bitmap_ind8 &priority_bitmap = *blit.priority;
- UINT8 *priority_baseaddr = &priority_bitmap.pix8(y1, xpos);
- typename _BitmapClass::pixel_t *dest_baseaddr = NULL;
- int dest_rowpixels = 0;
- if (dest.valid())
- {
- dest_rowpixels = dest.rowpixels();
- dest_baseaddr = &dest.pix(y1, xpos);
- }
-
- // convert screen coordinates to source tilemap coordinates
- x1 -= xpos;
- y1 -= ypos;
- x2 -= xpos;
- y2 -= ypos;
-
- // get tilemap pixels
- const UINT16 *source_baseaddr = &m_pixmap.pix16(y1);
- const UINT8 *mask_baseaddr = &m_flagsmap.pix8(y1);
-
- // get start/stop columns, rounding outward
- int mincol = x1 / m_tilewidth;
- int maxcol = (x2 + m_tilewidth - 1) / m_tilewidth;
-
- // set up row counter
- int y = y1;
- int nexty = m_tileheight * (y1 / m_tileheight) + m_tileheight;
- nexty = MIN(nexty, y2);
-
- // loop over tilemap rows
- for (;;)
- {
- int row = y / m_tileheight;
- int x_start = x1;
-
- // iterate across the applicable tilemap columns
- trans_t prev_trans = WHOLLY_TRANSPARENT;
- trans_t cur_trans;
- for (int column = mincol; column <= maxcol; column++)
- {
- int x_end;
-
- // we don't actually render the last column; it is always just used for flushing
- if (column == maxcol)
- cur_trans = WHOLLY_TRANSPARENT;
-
- // for other columns we look up the transparency information
- else
- {
- logical_index logindex = row * m_cols + column;
-
- // if the current tile is dirty, fix it
- if (m_tileflags[logindex] == TILE_FLAG_DIRTY)
- tile_update(logindex, column, row);
-
- // if the current summary data is non-zero, we must draw masked
- if ((m_tileflags[logindex] & blit.mask) != 0)
- cur_trans = MASKED;
-
- // otherwise, our transparency state is constant across the tile; fetch it
- else
- cur_trans = ((mask_baseaddr[column * m_tilewidth] & blit.mask) == blit.value) ? WHOLLY_OPAQUE : WHOLLY_TRANSPARENT;
- }
-
- // if the transparency state is the same as last time, don't render yet
- if (cur_trans == prev_trans)
- continue;
-
- // compute the end of this run, in pixels
- x_end = column * m_tilewidth;
- x_end = MAX(x_end, x1);
- x_end = MIN(x_end, x2);
-
- // if we're rendering something, compute the pointers
- const rgb_t *clut = m_palette->palette()->entry_list_adjusted();
- if (prev_trans != WHOLLY_TRANSPARENT)
- {
- const UINT16 *source0 = source_baseaddr + x_start;
- typename _BitmapClass::pixel_t *dest0 = dest_baseaddr + x_start;
- UINT8 *pmap0 = priority_baseaddr + x_start;
-
- // if we were opaque, use the opaque renderer
- if (prev_trans == WHOLLY_OPAQUE)
- {
- for (int cury = y; cury < nexty; cury++)
- {
- if (dest_baseaddr == NULL)
- scanline_draw_opaque_null(x_end - x_start, pmap0, blit.tilemap_priority_code);
- else if (sizeof(*dest0) == 2)
- scanline_draw_opaque_ind16(reinterpret_cast<UINT16 *>(dest0), source0, x_end - x_start, pmap0, blit.tilemap_priority_code);
- else if (sizeof(*dest0) == 4 && blit.alpha >= 0xff)
- scanline_draw_opaque_rgb32(reinterpret_cast<UINT32 *>(dest0), source0, x_end - x_start, clut, pmap0, blit.tilemap_priority_code);
- else if (sizeof(*dest0) == 4)
- scanline_draw_opaque_rgb32_alpha(reinterpret_cast<UINT32 *>(dest0), source0, x_end - x_start, clut, pmap0, blit.tilemap_priority_code, blit.alpha);
-
- dest0 += dest_rowpixels;
- source0 += m_pixmap.rowpixels();
- pmap0 += priority_bitmap.rowpixels();
- }
- }
-
- // otherwise use the masked renderer
- else
- {
- const UINT8 *mask0 = mask_baseaddr + x_start;
- for (int cury = y; cury < nexty; cury++)
- {
- if (dest_baseaddr == NULL)
- scanline_draw_masked_null(mask0, blit.mask, blit.value, x_end - x_start, pmap0, blit.tilemap_priority_code);
- else if (sizeof(*dest0) == 2)
- scanline_draw_masked_ind16(reinterpret_cast<UINT16 *>(dest0), source0, mask0, blit.mask, blit.value, x_end - x_start, pmap0, blit.tilemap_priority_code);
- else if (sizeof(*dest0) == 4 && blit.alpha >= 0xff)
- scanline_draw_masked_rgb32(reinterpret_cast<UINT32 *>(dest0), source0, mask0, blit.mask, blit.value, x_end - x_start, clut, pmap0, blit.tilemap_priority_code);
- else if (sizeof(*dest0) == 4)
- scanline_draw_masked_rgb32_alpha(reinterpret_cast<UINT32 *>(dest0), source0, mask0, blit.mask, blit.value, x_end - x_start, clut, pmap0, blit.tilemap_priority_code, blit.alpha);
-
- dest0 += dest_rowpixels;
- source0 += m_pixmap.rowpixels();
- mask0 += m_flagsmap.rowpixels();
- pmap0 += priority_bitmap.rowpixels();
- }
- }
- }
-
- // the new start is the end
- x_start = x_end;
- prev_trans = cur_trans;
- }
-
- // if this was the last row, stop
- if (nexty == y2)
- break;
-
- // advance to the next row on all our bitmaps
- priority_baseaddr += priority_bitmap.rowpixels() * (nexty - y);
- source_baseaddr += m_pixmap.rowpixels() * (nexty - y);
- mask_baseaddr += m_flagsmap.rowpixels() * (nexty - y);
- dest_baseaddr += dest_rowpixels * (nexty - y);
-
- // increment the Y counter
- y = nexty;
- nexty += m_tileheight;
- nexty = MIN(nexty, y2);
- }
-}
-
-
-//-------------------------------------------------
-// tilemap_draw_roz_core - render the tilemap's
-// pixmap to the destination with rotation
-// and zoom
-//-------------------------------------------------
-
-#define ROZ_PLOT_PIXEL(INPUT_VAL) \
-do { \
- if (sizeof(*dest) == 2) \
- *dest = (INPUT_VAL) + (priority >> 16); \
- else if (sizeof(*dest) == 4 && alpha >= 0xff) \
- *dest = clut[INPUT_VAL]; \
- else if (sizeof(*dest) == 4) \
- *dest = alpha_blend_r32(*dest, clut[INPUT_VAL], alpha); \
-} while (0)
-
-template<class _BitmapClass>
-void tilemap_t::draw_roz_core(screen_device &screen, _BitmapClass &destbitmap, const blit_parameters &blit,
- UINT32 startx, UINT32 starty, int incxx, int incxy, int incyx, int incyy, bool wraparound)
-{
- // pre-cache all the inner loop values
- const rgb_t *clut = m_palette->palette()->entry_list_adjusted() + (blit.tilemap_priority_code >> 16);
- bitmap_ind8 &priority_bitmap = *blit.priority;
- const int xmask = m_pixmap.width() - 1;
- const int ymask = m_pixmap.height() - 1;
- const int widthshifted = m_pixmap.width() << 16;
- const int heightshifted = m_pixmap.height() << 16;
- UINT32 priority = blit.tilemap_priority_code;
- UINT8 mask = blit.mask;
- UINT8 value = blit.value;
- UINT8 alpha = blit.alpha;
-
- // pre-advance based on the cliprect
- startx += blit.cliprect.min_x * incxx + blit.cliprect.min_y * incyx;
- starty += blit.cliprect.min_x * incxy + blit.cliprect.min_y * incyy;
-
- // extract start/end points
- int sx = blit.cliprect.min_x;
- int sy = blit.cliprect.min_y;
- int ex = blit.cliprect.max_x;
- int ey = blit.cliprect.max_y;
-
- // optimized loop for the not rotated case
- if (incxy == 0 && incyx == 0 && !wraparound)
- {
- // skip without drawing until we are within the bitmap
- while (startx >= widthshifted && sx <= ex)
- {
- startx += incxx;
- sx++;
- }
-
- // early exit if we're done already
- if (sx > ex)
- return;
-
- // loop over rows
- while (sy <= ey)
- {
- // only draw if Y is within range
- if (starty < heightshifted)
- {
- // initialize X counters
- int x = sx;
- UINT32 cx = startx;
- UINT32 cy = starty >> 16;
-
- // get source and priority pointers
- UINT8 *pri = &priority_bitmap.pix8(sy, sx);
- const UINT16 *src = &m_pixmap.pix16(cy);
- const UINT8 *maskptr = &m_flagsmap.pix8(cy);
- typename _BitmapClass::pixel_t *dest = &destbitmap.pix(sy, sx);
-
- // loop over columns
- while (x <= ex && cx < widthshifted)
- {
- // plot if we match the mask
- if ((maskptr[cx >> 16] & mask) == value)
- {
- ROZ_PLOT_PIXEL(src[cx >> 16]);
- *pri = (*pri & (priority >> 8)) | priority;
- }
-
- // advance in X
- cx += incxx;
- x++;
- dest++;
- pri++;
- }
- }
-
- // advance in Y
- starty += incyy;
- sy++;
- }
- }
-
- // wraparound case
- else if (wraparound)
- {
- // loop over rows
- while (sy <= ey)
- {
- // initialize X counters
- int x = sx;
- UINT32 cx = startx;
- UINT32 cy = starty;
-
- // get dest and priority pointers
- typename _BitmapClass::pixel_t *dest = &destbitmap.pix(sy, sx);
- UINT8 *pri = &priority_bitmap.pix8(sy, sx);
-
- // loop over columns
- while (x <= ex)
- {
- // plot if we match the mask
- if ((m_flagsmap.pix8((cy >> 16) & ymask, (cx >> 16) & xmask) & mask) == value)
- {
- ROZ_PLOT_PIXEL(m_pixmap.pix16((cy >> 16) & ymask, (cx >> 16) & xmask));
- *pri = (*pri & (priority >> 8)) | priority;
- }
-
- // advance in X
- cx += incxx;
- cy += incxy;
- x++;
- dest++;
- pri++;
- }
-
- // advance in Y
- startx += incyx;
- starty += incyy;
- sy++;
- }
- }
-
- // non-wraparound case
- else
- {
- // loop over rows
- while (sy <= ey)
- {
- // initialize X counters
- int x = sx;
- UINT32 cx = startx;
- UINT32 cy = starty;
-
- // get dest and priority pointers
- typename _BitmapClass::pixel_t *dest = &destbitmap.pix(sy, sx);
- UINT8 *pri = &priority_bitmap.pix8(sy, sx);
-
- // loop over columns
- while (x <= ex)
- {
- // plot if we're within the bitmap and we match the mask
- if (cx < widthshifted && cy < heightshifted)
- if ((m_flagsmap.pix8(cy >> 16, cx >> 16) & mask) == value)
- {
- ROZ_PLOT_PIXEL(m_pixmap.pix16(cy >> 16, cx >> 16));
- *pri = (*pri & (priority >> 8)) | priority;
- }
-
- // advance in X
- cx += incxx;
- cy += incxy;
- x++;
- dest++;
- pri++;
- }
-
- // advance in Y
- startx += incyx;
- starty += incyy;
- sy++;
- }
- }
-}
-
-
-//-------------------------------------------------
-// draw_debug - draw a debug version without any
-// rowscroll and with fixed parameters
-//-------------------------------------------------
-
-void tilemap_t::draw_debug(screen_device &screen, bitmap_rgb32 &dest, UINT32 scrollx, UINT32 scrolly)
-{
- // set up for the blit, using hard-coded parameters (no priority, etc)
- blit_parameters blit;
- bitmap_ind8 dummy_priority;
- configure_blit_parameters(blit, dummy_priority, dest.cliprect(), TILEMAP_DRAW_OPAQUE | TILEMAP_DRAW_ALL_CATEGORIES, 0, 0xff);
-
- // compute the effective scroll positions
- scrollx = m_width - scrollx % m_width;
- scrolly = m_height - scrolly % m_height;
-
- // flush the dirty state to all tiles as appropriate
- realize_all_dirty_tiles();
-
- // iterate to handle wraparound
- for (int ypos = scrolly - m_height; ypos <= blit.cliprect.max_y; ypos += m_height)
- for (int xpos = scrollx - m_width; xpos <= blit.cliprect.max_x; xpos += m_width)
- draw_instance(screen, dest, blit, xpos, ypos);
-}
-
-
-
-//**************************************************************************
-// TILEMAP MANAGER
-//**************************************************************************
-
-//-------------------------------------------------
-// tilemap_manager - constructor
-//-------------------------------------------------
-
-tilemap_manager::tilemap_manager(running_machine &machine)
- : m_machine(machine),
- m_instance(0)
-{
-}
-
-
-//-------------------------------------------------
-// ~tilemap_manager - destructor
-//-------------------------------------------------
-
-tilemap_manager::~tilemap_manager()
-{
- // detach all device tilemaps since they will be destroyed
- // as subdevices elsewhere
- bool found = true;
- while (found)
- {
- found = false;
- for (tilemap_t *tmap = m_tilemap_list.first(); tmap != NULL; tmap = tmap->next())
- if (tmap->device() != NULL)
- {
- found = true;
- m_tilemap_list.detach(*tmap);
- break;
- }
- }
-}
-
-
-//-------------------------------------------------
-// set_flip_all - set a global flip for all the
-// tilemaps
-//-------------------------------------------------
-
-static const struct
-{
- tilemap_memory_index (*func)(driver_device &, UINT32, UINT32, UINT32, UINT32);
- const char *name;
-} s_standard_mappers[TILEMAP_STANDARD_COUNT] =
-{
- { FUNC(tilemap_t::scan_rows) },
- { FUNC(tilemap_t::scan_rows_flip_x) },
- { FUNC(tilemap_t::scan_rows_flip_y) },
- { FUNC(tilemap_t::scan_rows_flip_xy) },
- { FUNC(tilemap_t::scan_cols) },
- { FUNC(tilemap_t::scan_cols_flip_x) },
- { FUNC(tilemap_t::scan_cols_flip_y) },
- { FUNC(tilemap_t::scan_cols_flip_xy) }
-};
-
-tilemap_t &tilemap_manager::create(device_gfx_interface &decoder, tilemap_get_info_delegate tile_get_info, tilemap_mapper_delegate mapper, int tilewidth, int tileheight, int cols, int rows, tilemap_t *allocated)
-{
- if (allocated == NULL)
- allocated = global_alloc(tilemap_t);
- return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, mapper, tilewidth, tileheight, cols, rows));
-}
-
-tilemap_t &tilemap_manager::create(device_gfx_interface &decoder, tilemap_get_info_delegate tile_get_info, tilemap_standard_mapper mapper, int tilewidth, int tileheight, int cols, int rows, tilemap_t *allocated)
-{
- if (allocated == NULL)
- allocated = global_alloc(tilemap_t);
- return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, tilemap_mapper_delegate(s_standard_mappers[mapper].func, s_standard_mappers[mapper].name, machine().driver_data()), tilewidth, tileheight, cols, rows));
-}
-
-
-//-------------------------------------------------
-// set_flip_all - set a global flip for all the
-// tilemaps
-//-------------------------------------------------
-
-void tilemap_manager::set_flip_all(UINT32 attributes)
-{
- for (tilemap_t *tmap = m_tilemap_list.first(); tmap != NULL; tmap = tmap->next())
- tmap->set_flip(attributes);
-}
-
-
-//-------------------------------------------------
-// mark_all_dirty - mark all the tiles in all the
-// tilemaps dirty
-//-------------------------------------------------
-
-void tilemap_manager::mark_all_dirty()
-{
- for (tilemap_t *tmap = m_tilemap_list.first(); tmap != NULL; tmap = tmap->next())
- tmap->mark_all_dirty();
-}
-
-
-
-//**************************************************************************
-// TILEMAP DEVICE
-//**************************************************************************
-
-// device type definition
-const device_type TILEMAP = &device_creator<tilemap_device>;
-
-//-------------------------------------------------
-// tilemap_device - constructor
-//-------------------------------------------------
-
-tilemap_device::tilemap_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : device_t(mconfig, TILEMAP, "Tilemap", tag, owner, clock, "tilemap", __FILE__),
- m_gfxdecode(*this),
- m_standard_mapper(TILEMAP_STANDARD_COUNT),
- m_tile_width(8),
- m_tile_height(8),
- m_num_columns(64),
- m_num_rows(64),
- m_transparent_pen_set(false),
- m_transparent_pen(0)
-{
-}
-
-
-//-------------------------------------------------
-// static_set_gfxdecode_tag: Set the tag of the
-// gfx decoder
-//-------------------------------------------------
-
-void tilemap_device::static_set_gfxdecode_tag(device_t &device, const char *tag)
-{
- downcast<tilemap_device &>(device).m_gfxdecode.set_tag(tag);
-}
-
-
-//-------------------------------------------------
-// static_set_bytes_per_entry: Set the
-// transparent pen
-//-------------------------------------------------
-
-void tilemap_device::static_set_bytes_per_entry(device_t &device, int bpe)
-{
- downcast<tilemap_device &>(device).m_bytes_per_entry = bpe;
-}
-
-
-//-------------------------------------------------
-// static_set_info_callback: Set the get info
-// callback delegate
-//-------------------------------------------------
-
-void tilemap_device::static_set_info_callback(device_t &device, tilemap_get_info_delegate get_info)
-{
- downcast<tilemap_device &>(device).m_get_info = get_info;
-}
-
-
-//-------------------------------------------------
-// static_set_layout: Set the tilemap size and
-// layout
-//-------------------------------------------------
-
-void tilemap_device::static_set_layout(device_t &device, tilemap_standard_mapper mapper, int columns, int rows)
-{
- tilemap_device &target = downcast<tilemap_device &>(device);
- target.m_standard_mapper = mapper;
- target.m_num_columns = columns;
- target.m_num_rows = rows;
-}
-
-void tilemap_device::static_set_layout(device_t &device, tilemap_mapper_delegate mapper, int columns, int rows)
-{
- tilemap_device &target = downcast<tilemap_device &>(device);
- target.m_standard_mapper = TILEMAP_STANDARD_COUNT;
- target.m_mapper = mapper;
- target.m_num_columns = columns;
- target.m_num_rows = rows;
-}
-
-
-//-------------------------------------------------
-// static_set_tile_size: Set the tile size
-//-------------------------------------------------
-
-void tilemap_device::static_set_tile_size(device_t &device, int width, int height)
-{
- tilemap_device &target = downcast<tilemap_device &>(device);
- target.m_tile_width = width;
- target.m_tile_height = height;
-}
-
-
-//-------------------------------------------------
-// static_set_transparent_pen: Set the
-// transparent pen
-//-------------------------------------------------
-
-void tilemap_device::static_set_transparent_pen(device_t &device, pen_t pen)
-{
- tilemap_device &target = downcast<tilemap_device &>(device);
- target.m_transparent_pen_set = true;
- target.m_transparent_pen = pen;
-}
-
-
-//-------------------------------------------------
-// write: Main memory writes
-//-------------------------------------------------
-
-WRITE8_MEMBER(tilemap_device::write)
-{
- m_basemem.write8(offset, data);
- offset /= m_bytes_per_entry;
- mark_tile_dirty(offset);
-}
-
-WRITE16_MEMBER(tilemap_device::write)
-{
- m_basemem.write16(offset, data, mem_mask);
- offset = offset * 2 / m_bytes_per_entry;
- mark_tile_dirty(offset);
- if (m_bytes_per_entry < 2)
- mark_tile_dirty(offset + 1);
-}
-
-WRITE32_MEMBER(tilemap_device::write)
-{
- m_basemem.write32(offset, data, mem_mask);
- offset = offset * 4 / m_bytes_per_entry;
- mark_tile_dirty(offset);
- if (m_bytes_per_entry < 4)
- {
- mark_tile_dirty(offset + 1);
- if (m_bytes_per_entry < 2)
- {
- mark_tile_dirty(offset + 2);
- mark_tile_dirty(offset + 3);
- }
- }
-}
-
-
-//-------------------------------------------------
-// write_entry_ext: Extension memory writes
-//-------------------------------------------------
-
-WRITE8_MEMBER(tilemap_device::write_ext)
-{
- m_extmem.write8(offset, data);
- offset /= m_bytes_per_entry;
- mark_tile_dirty(offset);
-}
-
-WRITE16_MEMBER(tilemap_device::write_ext)
-{
- m_extmem.write16(offset, data, mem_mask);
- offset = offset * 2 / m_bytes_per_entry;
- mark_tile_dirty(offset);
- if (m_bytes_per_entry < 2)
- mark_tile_dirty(offset + 1);
-}
-
-WRITE32_MEMBER(tilemap_device::write_ext)
-{
- m_extmem.write32(offset, data, mem_mask);
- offset = offset * 4 / m_bytes_per_entry;
- mark_tile_dirty(offset);
- if (m_bytes_per_entry < 4)
- {
- mark_tile_dirty(offset + 1);
- if (m_bytes_per_entry < 2)
- {
- mark_tile_dirty(offset + 2);
- mark_tile_dirty(offset + 3);
- }
- }
-}
-
-
-//-------------------------------------------------
-// device_start: Start up the device
-//-------------------------------------------------
-
-void tilemap_device::device_start()
-{
- // check configuration
- if (m_get_info.isnull())
- throw emu_fatalerror("Tilemap device '%s' has no get info callback!", tag());
- if (m_standard_mapper == TILEMAP_STANDARD_COUNT && m_mapper.isnull())
- throw emu_fatalerror("Tilemap device '%s' has no mapper callback!", tag());
-
- if(!m_gfxdecode->started())
- throw device_missing_dependencies();
-
- // bind our callbacks
- m_get_info.bind_relative_to(*owner());
- m_mapper.bind_relative_to(*owner());
-
- // allocate the tilemap
- if (m_standard_mapper == TILEMAP_STANDARD_COUNT)
- machine().tilemap().create(m_gfxdecode, m_get_info, m_mapper, m_tile_width, m_tile_height, m_num_columns, m_num_rows, this);
- else
- machine().tilemap().create(m_gfxdecode, m_get_info, m_standard_mapper, m_tile_width, m_tile_height, m_num_columns, m_num_rows, this);
-
- // find the memory, if present
- const memory_share *share = memshare(tag());
- if (share != NULL)
- {
- m_basemem.set(*share, m_bytes_per_entry);
-
- // look for an extension entry
- std::string tag_ext = std::string(tag()).append("_ext");
- share = memshare(tag_ext.c_str());
- if (share != NULL)
- m_extmem.set(*share, m_bytes_per_entry);
- }
-
- // configure the device and set the pen
- if (m_transparent_pen_set)
- set_transparent_pen(m_transparent_pen);
-}