diff options
Diffstat (limited to 'trunk/src/emu/tilemap.h')
-rw-r--r-- | trunk/src/emu/tilemap.h | 702 |
1 files changed, 702 insertions, 0 deletions
diff --git a/trunk/src/emu/tilemap.h b/trunk/src/emu/tilemap.h new file mode 100644 index 00000000000..4d29edc7765 --- /dev/null +++ b/trunk/src/emu/tilemap.h @@ -0,0 +1,702 @@ +/*************************************************************************** + + tilemap.h + + Generic tilemap management system. + +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +**************************************************************************** + + Core concepts: + + Tilemap = a 2-dimensional array of tiles; each tile has its own + independent characteristics which describe how that tile is + rendered. A tilemap is described by the number of rows and + columns in the map. Each tile in the tilemap is a fixed size + specified as width and height in pixels. + + Tile = a single rectangular element in a tilemap; tiles can be + any size, but all tiles in a tilemap are the same size. Each + tile is described by the following parameters: + + pen_data (required): pointer to an array of 8bpp pen data + describing the raw pixels to be rendered for a tile; + for example, an 8x8 tile requires 64 bytes of pen_data + + palette_base (required): the base index in the global palette; + each pixel fetched from pen_data will have this base added + to it before it is stored in the pixmap + + mask_data (optional): pointer to an array of 1bpp mask data + which controls which pixels are to be considered visible + or transparent (part of no layer); data is packed MSB + first with no padding, so an 8x8 tile requires 64 bits or + 8 bytes data + + category (optional): specifies one of 16 categories for the + pixels in the tile; the category controls which tiles are + rendered during a tilemap_draw() call + + group (optional): specifies one of 256 groups for pen mapping; + each pen in the tile is looked up in a table to determine + which layer(s) it belongs to, and the group selects one of + 256 different tables to use for this mapping + + flags (optional): specifies one or more of the following bits: + + TILE_FLIPX means render the tile flipped horizontally + + TILE_FLIPY means render the tile flipped vertically + + TILE_FORCE_LAYERn means all pixels are forced to be in + layer n, where n = 0,1,2 + + Pen = another name for pixel value; tilemap graphics are either + 4 or 8 bits per pixel, meaning that pen values range from + 0-15 (4bpp) or 0-255 (8bpp). + + Logical index = index of a tile in a tilemap, assuming perfect + packing in row-major order; this is always equal to + (rownum * tilemap_columns + colnum). + + Memory index = index of a tile in memory; this often does not + map 1:1 to the logical index (though it can). A mapper + function is provided when creating a new tilemap that can + map from (column,row) to memory index. + + Layer = one of 3 categories each pixel can belong to, based on + the pens in a tile; traditionally, layer 0 is the only + one used. If a pixel does not belong to any layers, it is + considered transparent. + + Group = one of 256 per-tile selectable means of mapping from + pens to layers; traditionally only group 0 is used. + + Category = a 4-bit value specified per-tile which allows for + separating tiles into categories which can be rendered + independently. + + Pixmap = a 16bpp bitmap containing the full tilemap with + all tiles rendered. + + Flagsmap = an 8bpp bitmap containing per-pixel flags, + specifically the category (specified in bits 0-3) and + the layer (specified in bits 4-6). + +**************************************************************************** + + How to use a tilemap: + + 1. First create a new tilemap by calling tilemap_create(). The + parameters are as follows: + + tile_get_info = pointer to a callback function which accepts a + memory index and in return fills in a tile_info structure + that describes the characteristics of a tile; this function + will be called whenever a dirty tile needs to be rendered + + mapper = pointer to a callback function which maps the logical + column and row to a memory index; several standard mappers + are provided, with tilemap_scan_rows being the most common + + tilewidth = the width, in pixels, of each individual tile + + tileheight = the height, in pixels, of each individual tile + + cols = the number of columns in the tilemap + + rows = the number of rows in the tilemap + + 2. Once you have created your tilemap, you need to configure it. + Common configuration tasks include: + + * marking one of the pens as transparent via + tilemap_set_transparent_pen() + + * performing more complex pen-to-layer mapping via + tilemap_map_pen_to_layer() or + tilemap_map_pens_to_layer() + + * configuring global scroll offsets via + tilemap_set_scrolldx() and tilemap_set_scrolldy() + + * specifying a pointer that is passed to your tile_get_info + callback via tilemap_set_user_data() + + * setting a global palette offset via + tilemap_set_palette_offset() + + 3. In your memory write handlers for the tile memory, anytime tile + data is modified, you need to mark the tile dirty so that it is + re-rendered with the new data the next time the tilemap is drawn. + Use tilemap_mark_tile_dirty() and pass in the memory index. + + 4. In your handlers for scrolling, update the scroll values for the + tilemap via tilemap_set_scrollx() and tilemap_set_scrolly(). + + 5. If any other major characteristics of the tilemap change (generally + any global state that is used by the tile_get_info callback but + which is not reported via other calls to the tilemap code), you + should invalidate the entire tilemap. You can do this by calling + tilemap_mark_all_tiles_dirty(). + + 6. In your VIDEO_UPDATE callback, render the tiles by calling + tilemap_draw() or tilemap_draw_roz(). If you need to do custom + rendering and want access to the raw pixels, call + tilemap_get_pixmap() to get a pointer to the updated bitmap_ind16 + containing the tilemap graphics. + +**************************************************************************** + + The following example shows how to use the tilemap system to create + a simple tilemap where pen 0 is transparent. Each tile is 8x8 pixels + in size, and there are 32 rows and 64 columns, stored in row-major + order. Based on bits in the tile memory, tiles can be drawn either + behind or in front of sprites. + + tilemap_t *tmap; + UINT16 *my_tmap_memory; + + TILE_GET_INFO( my_get_info ) + { + UINT8 tiledata = my_tmap_memory[tile_index]; + UINT8 code = tiledata & 0xff; + UINT8 color = (tiledata >> 8) & 0x1f; + UINT8 flipx = (tiledata >> 13) & 1; + UINT8 flipy = (tiledata >> 14) & 1; + UINT8 category = (tiledata >> 15) & 1; + + // set the common info for the tile + SET_TILE_INFO( + 1, // use machine.gfx[1] for tile graphics + code, // the index of the graphics for this tile + color, // the color to use for this tile + (flipx ? TILE_FLIPX : 0) | // flags for this tile; also + (flipy ? TILE_FLIPY : 0); // see the FLIP_YX macro + ); + + // set the category of each tile based on the high bit; this + // allows us to draw each category independently + tileinfo.category = category; + } + + VIDEO_START( mydriver ) + { + // first create the tilemap + tmap = tilemap_create(machine, + my_get_info, // pointer to your get_info + tilemap_scan_rows, // standard row-major mapper + 8,8, // 8x8 tiles + 64,32); // 64 columns, 32 rows + + // then set the transparent pen; all other pens will default + // to being part of layer 0 + tilemap_set_transparent_pen(tmap, 0); + } + + SCREEN_UPDATE( mydriver ) + { + // draw the tilemap first, fully opaque since it needs to + // erase all previous pixels + tilemap_draw( + bitmap, // destination bitmap + cliprect, // clipping rectangle + tmap, // tilemap to draw + TILEMAP_DRAW_OPAQUE, // flags + 0); // don't use priority_bitmap + + // next draw the sprites + my_draw_sprites(); + + // then draw the tiles which have priority over sprites + tilemap_draw( + bitmap, // destination bitmap + cliprect, // clipping rectangle + tmap, // tilemap to draw + TILEMAP_DRAW_CATEGORY(1),// flags: draw category 1 + 0); // don't use priority_bitmap + + return 0; + } + +**************************************************************************** + + Tilemap techniques: + + * The previous tilemap code specified a number of different tilemap + types that were fundamentally similar. This has been collapsed + into just two types now. Here is how to replicate that + functionality with the new system: + + TILEMAP_OPAQUE: If you want a tilemap with no transparency, + you don't need to do anything; by default all pens map to + layer 0 and are thus non-transparent. Note that a lot of + code used to create OPAQUE tilemaps and then set the + transparent pen for them; this no longer works. + + TILEMAP_TRANSPARENT: This described a tilemap with a single + transparent pen. To create the same effect, call + tilemap_set_transparent_pen() to specify which pen is + transparent; all other pens will map to layer 0. + + TILEMAP_BITMASK: This type is no longer special; with the new + code, any tile_get_info callback can specify a bitmask which + will be processed after rendering to make some pixels + transparent. + + TILEMAP_SPLIT: This type used to let you map pens into two + layers (called "front" and "back") based on their pens. It + also allowed for you to choose one of 4 mappings on a per-tile + basis. All of this functionality is now expanded: you can + specify one of 3 layers and can choose from one of 256 mappings + on a per-tile basis. You just call tilemap_set_transmask(), + which still exists but maps onto the new behavior. The "front" + layer is now "layer 0" and the "back" layer is now "layer 1". + + TILEMAP_SPLIT_PENBIT: This type was only used in one driver + and is not worth describing in detail how the new mapping + works. :) + + * By far the most common usage of layers is the simplest: layer 0 is + the only one used and rendered. If you want a particular tile to + render opaque, you can set the TILE_FORCE_LAYER0 file in your + tile_get_info callback. + + * When drawing, you can specify in the flags which classes of pixels + to draw. In the low 4 bits, you specify the category; this must + match exactly the category specified for the tile in order to + render. In addition, the flags TILEMAP_DRAW_LAYERn allow you to + control which layer pattern to draw; note that combining these + flags may produce interesting results. Specifying both layer 0 + and layer 1 will render only pixels that are in *both* layers. + If you want to render everything, regardless of layer, specify + the TILEMAP_DRAW_OPAQUE flag. If you don't specify any layers, + TILEMAP_DRAW_LAYER0 is assumed. + + * If you want to render with alpha blending, you can call + tilemap_draw() with the TILEMAP_DRAW_ALPHA flag. + + * To configure more complex pen-to-layer mapping, use the + tilemap_map_pens_to_layer() call. This call takes a group number + so that you can configure 1 of the 256 groups independently. + It also takes a pen and a mask; the mapping is updated for all + pens where ((pennum & mask) == pen). To set all the pens in a + group to the same value, pass a mask of 0. To set a single pen in + a group, pass a mask of ~0. The helper function + tilemap_map_pen_to_layer() does this for you. + +***************************************************************************/ + +#pragma once + +#ifndef __EMU_H__ +#error Dont include this file directly; include emu.h instead. +#endif + +#ifndef __TILEMAP_H__ +#define __TILEMAP_H__ + + +//************************************************************************** +// CONSTANTS +//************************************************************************** + +// maximum number of groups +#define TILEMAP_NUM_GROUPS 256 + + +// these flags control tilemap_draw() behavior +const UINT32 TILEMAP_DRAW_CATEGORY_MASK = 0x0f; // specify the category to draw +const UINT32 TILEMAP_DRAW_LAYER0 = 0x10; // draw layer 0 +const UINT32 TILEMAP_DRAW_LAYER1 = 0x20; // draw layer 1 +const UINT32 TILEMAP_DRAW_LAYER2 = 0x40; // draw layer 2 +const UINT32 TILEMAP_DRAW_OPAQUE = 0x80; // draw everything, even transparent stuff +const UINT32 TILEMAP_DRAW_ALPHA_FLAG = 0x100; // draw with alpha blending (in the upper 8 bits) +const UINT32 TILEMAP_DRAW_ALL_CATEGORIES = 0x200; // draw all categories + +// per-pixel flags in the transparency_bitmap +const UINT8 TILEMAP_PIXEL_CATEGORY_MASK = 0x0f; // category is stored in the low 4 bits +const UINT8 TILEMAP_PIXEL_TRANSPARENT = 0x00; // transparent if in none of the layers below +const UINT8 TILEMAP_PIXEL_LAYER0 = 0x10; // pixel is opaque in layer 0 +const UINT8 TILEMAP_PIXEL_LAYER1 = 0x20; // pixel is opaque in layer 1 +const UINT8 TILEMAP_PIXEL_LAYER2 = 0x40; // pixel is opaque in layer 2 + +// per-tile flags, set by get_tile_info callback +const UINT8 TILE_FLIPX = 0x01; // draw this tile horizontally flipped +const UINT8 TILE_FLIPY = 0x02; // draw this tile vertically flipped +const UINT8 TILE_FORCE_LAYER0 = TILEMAP_PIXEL_LAYER0; // force all pixels to be layer 0 (no transparency) +const UINT8 TILE_FORCE_LAYER1 = TILEMAP_PIXEL_LAYER1; // force all pixels to be layer 1 (no transparency) +const UINT8 TILE_FORCE_LAYER2 = TILEMAP_PIXEL_LAYER2; // force all pixels to be layer 2 (no transparency) + +// tilemap global flags, used by tilemap_set_flip() +const UINT32 TILEMAP_FLIPX = TILE_FLIPX; // draw the tilemap horizontally flipped +const UINT32 TILEMAP_FLIPY = TILE_FLIPY; // draw the tilemap vertically flipped + +// set this value for a scroll row/column to fully disable it +const UINT32 TILE_LINE_DISABLED = 0x80000000; + + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// forward declarations +class tilemap_t; +class tilemap_manager; + + +// global types +typedef UINT32 tilemap_memory_index; + + +// tile_data is filled in by the get_tile_info callback +struct tile_data +{ + const UINT8 * pen_data; // required + const UINT8 * mask_data; // required + pen_t palette_base; // defaults to 0 + UINT8 category; // defaults to 0; range from 0..15 + UINT8 group; // defaults to 0; range from 0..TILEMAP_NUM_GROUPS + UINT8 flags; // defaults to 0; one or more of TILE_* flags above + UINT8 pen_mask; // defaults to 0xff; mask to apply to pen_data while rendering the tile + UINT8 gfxnum; // defaults to 0xff; specify index of machine.gfx for auto-invalidation on dirty + + void set(running_machine &machine, int _gfxnum, int rawcode, int rawcolor, int _flags) + { + const gfx_element *gfx = machine.gfx[_gfxnum]; + int code = rawcode % gfx->total_elements; + pen_data = gfx_element_get_data(gfx, code); + palette_base = gfx->color_base + gfx->color_granularity * rawcolor; + flags = _flags; + gfxnum = _gfxnum; + } +}; + + +// modern delegates +typedef delegate<void (tile_data &, tilemap_memory_index, void *)> tilemap_get_info_delegate; +typedef delegate<tilemap_memory_index (UINT32, UINT32, UINT32, UINT32)> tilemap_mapper_delegate; + + +// legacy callbacks +typedef void (*tile_get_info_func)(running_machine &machine, tile_data &tileinfo, tilemap_memory_index tile_index, void *param); +typedef void (*tile_get_info_device_func)(device_t *device, tile_data &tileinfo, tilemap_memory_index tile_index, void *param); +typedef tilemap_memory_index (*tilemap_mapper_func)(running_machine &machine, UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows); + + +// core tilemap structure +class tilemap_t +{ + DISABLE_COPYING(tilemap_t); + + friend class tilemap_manager; + friend class simple_list<tilemap_t>; + friend resource_pool_object<tilemap_t>::~resource_pool_object(); + + // logical index + typedef UINT32 logical_index; + + // internal usage to mark tiles dirty + static const UINT8 TILE_FLAG_DIRTY = 0xff; + + // invalid logical index + static const logical_index INVALID_LOGICAL_INDEX = (logical_index)~0; + + // maximum index in each array + static const int MAX_PEN_TO_FLAGS = 256; + + // tilemap_manager controlls our allocations + tilemap_t(tilemap_manager &manager, tilemap_get_info_delegate tile_get_info, tilemap_mapper_delegate mapper, int tilewidth, int tileheight, int cols, int rows); + ~tilemap_t(); + +public: + // getters + running_machine &machine() const; + tilemap_t *next() const { return m_next; } + UINT32 width() const { return m_width; } + UINT32 height() const { return m_height; } + bool enabled() const { return m_enable; } + int scrolldx() const { return (m_attributes & TILEMAP_FLIPX) ? m_dx_flipped : m_dx; } + int scrolldy() const { return (m_attributes & TILEMAP_FLIPY) ? m_dy_flipped : m_dy; } + int scrollx(int which = 0) const { return (which < m_scrollrows) ? m_rowscroll[which] : 0; } + int scrolly(int which = 0) const { return (which < m_scrollcols) ? m_colscroll[which] : 0; } + bitmap_ind16 &pixmap() { pixmap_update(); return m_pixmap; } + bitmap_ind8 &flagsmap() { pixmap_update(); return m_flagsmap; } + UINT8 *tile_flags() { pixmap_update(); return m_tileflags; } + tilemap_memory_index memory_index(UINT32 col, UINT32 row) { return m_mapper(col, row, m_cols, m_rows); } + + // setters + void enable(bool enable = true) { m_enable = enable; } + void set_user_data(void *user_data) { m_user_data = user_data; } + void set_palette_offset(UINT32 offset) { m_palette_offset = offset; } + void set_scrolldx(int dx, int dx_flipped) { m_dx = dx; m_dx_flipped = dx_flipped; } + void set_scrolldy(int dy, int dy_flipped) { m_dy = dy; m_dy_flipped = dy_flipped; } + void set_scrollx(int which, int value) { if (which < m_scrollrows) m_rowscroll[which] = value; } + void set_scrolly(int which, int value) { if (which < m_scrollcols) m_colscroll[which] = value; } + void set_scrollx(int value) { set_scrollx(0, value); } + void set_scrolly(int value) { set_scrolly(0, value); } + void set_scroll_rows(UINT32 scroll_rows) { assert(scroll_rows <= m_height); m_scrollrows = scroll_rows; } + void set_scroll_cols(UINT32 scroll_cols) { assert(scroll_cols <= m_width); m_scrollcols = scroll_cols; } + void set_flip(UINT32 attributes) { if (m_attributes != attributes) { m_attributes = attributes; mappings_update(); } } + + // dirtying + void mark_tile_dirty(tilemap_memory_index memindex); + void mark_all_dirty() { m_all_tiles_dirty = true; m_all_tiles_clean = false; } + + // pen mapping + void map_pens_to_layer(int group, pen_t pen, pen_t mask, UINT8 layermask); + void map_pen_to_layer(int group, pen_t pen, UINT8 layermask) { map_pens_to_layer(group, pen, ~0, layermask); } + void set_transparent_pen(pen_t pen); + void set_transmask(int group, UINT32 fgmask, UINT32 bgmask); + + // drawing + void draw(bitmap_ind16 &dest, const rectangle &cliprect, UINT32 flags, UINT8 priority, UINT8 priority_mask = 0xff); + void draw(bitmap_rgb32 &dest, const rectangle &cliprect, UINT32 flags, UINT8 priority, UINT8 priority_mask = 0xff); + void draw_roz(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 = 0xff); + void draw_roz(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 = 0xff); + void draw_debug(bitmap_rgb32 &dest, UINT32 scrollx, UINT32 scrolly); + +private: + // internal set of transparency states for rendering + enum trans_t + { + WHOLLY_TRANSPARENT, + WHOLLY_OPAQUE, + MASKED + }; + + // blitting parameters for rendering + struct blit_parameters + { + rectangle cliprect; + UINT32 tilemap_priority_code; + UINT8 mask; + UINT8 value; + UINT8 alpha; + }; + + // inline helpers + INT32 effective_rowscroll(int index, UINT32 screen_width); + INT32 effective_colscroll(int index, UINT32 screen_height); + bool gfx_elements_changed(); + + // inline scanline rasterizers + void scanline_draw_opaque_null(int count, UINT8 *pri, UINT32 pcode); + void scanline_draw_masked_null(const UINT8 *maskptr, int mask, int value, int count, UINT8 *pri, UINT32 pcode); + void scanline_draw_opaque_ind16(UINT16 *dest, const UINT16 *source, int count, UINT8 *pri, UINT32 pcode); + void scanline_draw_masked_ind16(UINT16 *dest, const UINT16 *source, const UINT8 *maskptr, int mask, int value, int count, UINT8 *pri, UINT32 pcode); + void scanline_draw_opaque_rgb32(UINT32 *dest, const UINT16 *source, int count, const pen_t *pens, UINT8 *pri, UINT32 pcode); + void scanline_draw_masked_rgb32(UINT32 *dest, const UINT16 *source, const UINT8 *maskptr, int mask, int value, int count, const pen_t *pens, UINT8 *pri, UINT32 pcode); + void scanline_draw_opaque_rgb32_alpha(UINT32 *dest, const UINT16 *source, int count, const pen_t *pens, UINT8 *pri, UINT32 pcode, UINT8 alpha); + void scanline_draw_masked_rgb32_alpha(UINT32 *dest, const UINT16 *source, const UINT8 *maskptr, int mask, int value, int count, const pen_t *pens, UINT8 *pri, UINT32 pcode, UINT8 alpha); + + // internal helpers + void postload(); + void mappings_create(); + void mappings_update(); + void realize_all_dirty_tiles(); + + // internal drawing + void pixmap_update(); + void tile_update(logical_index logindex, UINT32 col, UINT32 row); + UINT8 tile_draw(const UINT8 *pendata, UINT32 x0, UINT32 y0, UINT32 palette_base, UINT8 category, UINT8 group, UINT8 flags, UINT8 pen_mask); + UINT8 tile_apply_bitmask(const UINT8 *maskdata, UINT32 x0, UINT32 y0, UINT8 category, UINT8 flags); + void configure_blit_parameters(blit_parameters &blit, const rectangle &cliprect, UINT32 flags, UINT8 priority, UINT8 priority_mask); + template<class _BitmapClass> void draw_common(_BitmapClass &dest, const rectangle &cliprect, UINT32 flags, UINT8 priority, UINT8 priority_mask); + template<class _BitmapClass> void draw_roz_common(_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); + template<class _BitmapClass> void draw_instance(_BitmapClass &dest, const blit_parameters &blit, int xpos, int ypos); + template<class _BitmapClass> void draw_roz_core(_BitmapClass &destbitmap, const blit_parameters &blit, UINT32 startx, UINT32 starty, int incxx, int incxy, int incyx, int incyy, bool wraparound); + + // basic tilemap metrics + tilemap_t * m_next; // pointer to next tilemap + UINT32 m_rows; // number of tile rows + UINT32 m_cols; // number of tile columns + UINT32 m_tilewidth; // width of a single tile in pixels + UINT32 m_tileheight; // height of a single tile in pixels + UINT32 m_width; // width of the full tilemap in pixels + UINT32 m_height; // height of the full tilemap in pixels + + // logical <-> memory mappings + tilemap_mapper_delegate m_mapper; // callback to map a row/column to a memory index + logical_index * m_memory_to_logical; // map from memory index to logical index + logical_index m_max_logical_index; // maximum valid logical index + tilemap_memory_index * m_logical_to_memory; // map from logical index to memory index + tilemap_memory_index m_max_memory_index; // maximum valid memory index + + // callback to interpret video RAM for the tilemap + tilemap_get_info_delegate m_tile_get_info; // callback to get information about a tile + tile_data m_tileinfo; // structure to hold the data for a tile + void * m_user_data; // user data value passed to the callback + + // global tilemap states + bool m_enable; // true if we are enabled + UINT8 m_attributes; // global attributes (flipx/y) + bool m_all_tiles_dirty; // true if all tiles are dirty + bool m_all_tiles_clean; // true if all tiles are clean + UINT32 m_palette_offset; // palette offset + UINT32 m_pen_data_offset; // pen data offset + UINT32 m_gfx_used; // bitmask of gfx items used + UINT32 m_gfx_dirtyseq[MAX_GFX_ELEMENTS]; // dirtyseq values from last check + + // scroll information + UINT32 m_scrollrows; // number of independently scrolled rows + UINT32 m_scrollcols; // number of independently scrolled columns + INT32 * m_rowscroll; // array of rowscroll values + INT32 * m_colscroll; // array of colscroll values + INT32 m_dx; // global horizontal scroll offset + INT32 m_dx_flipped; // global horizontal scroll offset when flipped + INT32 m_dy; // global vertical scroll offset + INT32 m_dy_flipped; // global vertical scroll offset when flipped + + // pixel data + bitmap_ind16 m_pixmap; // cached pixel data + + // transparency mapping + bitmap_ind8 m_flagsmap; // per-pixel flags + UINT8 * m_tileflags; // per-tile flags + UINT8 m_pen_to_flags[MAX_PEN_TO_FLAGS * TILEMAP_NUM_GROUPS]; // mapping of pens to flags + +private: + tilemap_manager & m_manager; // reference to the owning manager +}; + + +// tilemap manager +class tilemap_manager +{ + friend class tilemap_t; + +public: + // construction/destuction + tilemap_manager(running_machine &machine); + + // getters + running_machine &machine() const { return m_machine; } + + // tilemap creation + tilemap_t &create(tilemap_get_info_delegate tile_get_info, tilemap_mapper_delegate mapper, int tilewidth, int tileheight, int cols, int rows); + tilemap_t &create(tile_get_info_func tile_get_info, tilemap_mapper_func mapper, int tilewidth, int tileheight, int cols, int rows); + + // tilemap list information + tilemap_t *find(int index) { return m_tilemap_list.find(index); } + int count() const { return m_tilemap_list.count(); } + + // global operations on all tilemaps + void mark_all_dirty(); + void set_flip_all(UINT32 attributes); + +private: + // allocate an instance index + int alloc_instance() { return ++m_instance; } + + // internal state + running_machine & m_machine; + simple_list<tilemap_t> m_tilemap_list; + int m_instance; +}; + + + +//************************************************************************** +// MACROS +//************************************************************************** + +// macros to help form flags for tilemap_draw +#define TILEMAP_DRAW_CATEGORY(x) (x) // specify category to draw +#define TILEMAP_DRAW_ALPHA(x) (TILEMAP_DRAW_ALPHA_FLAG | (rgb_clamp(x) << 24)) + +// function definition for a get info callback +#define TILE_GET_INFO(_name) void _name(running_machine &machine, tile_data &tileinfo, tilemap_memory_index tile_index, void *param) +#define TILE_GET_INFO_DEVICE(_name) void _name(device_t *device, tile_data &tileinfo, tilemap_memory_index tile_index, void *param) + +// function definition for a logical-to-memory mapper +#define TILEMAP_MAPPER(_name) tilemap_memory_index _name(running_machine &machine, UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows) + +// useful macro inside of a TILE_GET_INFO callback to set tile information +#define SET_TILE_INFO(GFX,CODE,COLOR,FLAGS) tileinfo.set(machine, GFX, CODE, COLOR, FLAGS) +#define SET_TILE_INFO_DEVICE(GFX,CODE,COLOR,FLAGS) tileinfo.set(device->machine(), GFX, CODE, COLOR, FLAGS) + +// Macros for setting tile attributes in the TILE_GET_INFO callback: +// TILE_FLIP_YX assumes that flipy is in bit 1 and flipx is in bit 0 +// TILE_FLIP_XY assumes that flipy is in bit 0 and flipx is in bit 1 +#define TILE_FLIPYX(YX) ((YX) & 3) +#define TILE_FLIPXY(XY) ((((XY) & 2) >> 1) | (((XY) & 1) << 1)) + + + +//************************************************************************** +// FUNCTION PROTOTYPES +//************************************************************************** + + +// ----- tilemap creation and configuration ----- + +// create a new tilemap; note that tilemaps are tracked by the core so there is no dispose +inline tilemap_t *tilemap_create(running_machine &machine, tile_get_info_func tile_get_info, tilemap_mapper_func mapper, int tilewidth, int tileheight, int cols, int rows) +{ return &machine.tilemap().create(tilemap_get_info_delegate(tile_get_info, "", &machine), tilemap_mapper_delegate(mapper, "", &machine), tilewidth, tileheight, cols, rows); } + +// create a new tilemap that is owned by a device +inline tilemap_t *tilemap_create_device(device_t *device, tile_get_info_device_func tile_get_info, tilemap_mapper_func mapper, int tilewidth, int tileheight, int cols, int rows) +{ return &device->machine().tilemap().create(tilemap_get_info_delegate(tile_get_info, "", device), tilemap_mapper_delegate(mapper, "", &device->machine()), tilewidth, tileheight, cols, rows); } + + + +// ----- common logical-to-memory mappers ----- + +// scan in row-major order with optional flipping +TILEMAP_MAPPER( tilemap_scan_rows ); +TILEMAP_MAPPER( tilemap_scan_rows_flip_x ); +TILEMAP_MAPPER( tilemap_scan_rows_flip_y ); +TILEMAP_MAPPER( tilemap_scan_rows_flip_xy ); + +// scan in column-major order with optional flipping +TILEMAP_MAPPER( tilemap_scan_cols ); +TILEMAP_MAPPER( tilemap_scan_cols_flip_x ); +TILEMAP_MAPPER( tilemap_scan_cols_flip_y ); +TILEMAP_MAPPER( tilemap_scan_cols_flip_xy ); + + + +//************************************************************************** +// INLINE FUNCTIONS +//************************************************************************** + + +inline running_machine &tilemap_t::machine() const +{ + return m_manager.machine(); +} + + +#endif // __TILEMAP_H__ |