diff options
Diffstat (limited to 'src/emu/tilemap.cpp')
-rw-r--r-- | src/emu/tilemap.cpp | 232 |
1 files changed, 146 insertions, 86 deletions
diff --git a/src/emu/tilemap.cpp b/src/emu/tilemap.cpp index 083b4b4ef5a..8c4e20e158f 100644 --- a/src/emu/tilemap.cpp +++ b/src/emu/tilemap.cpp @@ -336,7 +336,9 @@ inline void tilemap_t::scanline_draw_masked_rgb32_alpha(u32 *dest, const u16 *so // tilemap_t - constructor //------------------------------------------------- -tilemap_t::tilemap_t() +tilemap_t::tilemap_t(device_t &owner) + : m_mapper(owner) + , m_tile_get_info(owner) { // until init() is called, data is floating; this is deliberate } @@ -346,11 +348,18 @@ tilemap_t::tilemap_t() // 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, u16 tilewidth, u16 tileheight, u32 cols, u32 rows) +void tilemap_t::init_common( + tilemap_manager &manager, + device_gfx_interface &decoder, + tilemap_get_info_delegate tile_get_info, + u16 tilewidth, + u16 tileheight, + u32 cols, + u32 rows) { // populate managers and devices m_manager = &manager; - m_device = dynamic_cast<tilemap_device *>(this); + m_device = dynamic_cast<device_t *>(this); m_palette = &decoder.palette(); m_next = nullptr; m_user_data = nullptr; @@ -363,9 +372,6 @@ tilemap_t &tilemap_t::init(tilemap_manager &manager, device_gfx_interface &decod 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; @@ -426,6 +432,52 @@ tilemap_t &tilemap_t::init(tilemap_manager &manager, device_gfx_interface &decod // reset everything after a load machine().save().register_postload(save_prepost_delegate(FUNC(tilemap_t::postload), this)); +} + +tilemap_t &tilemap_t::init( + tilemap_manager &manager, + device_gfx_interface &decoder, + tilemap_get_info_delegate tile_get_info, + tilemap_mapper_delegate mapper, + u16 tilewidth, + u16 tileheight, + u32 cols, + u32 rows) +{ + // populate logical <-> memory mappings + m_mapper = mapper; + + init_common(manager, decoder, tile_get_info, tilewidth, tileheight, cols, rows); + + return *this; +} + +tilemap_t &tilemap_t::init( + tilemap_manager &manager, + device_gfx_interface &decoder, + tilemap_get_info_delegate tile_get_info, + tilemap_standard_mapper mapper, + u16 tilewidth, + u16 tileheight, + u32 cols, + u32 rows) +{ + // populate logical <-> memory mappings + switch (mapper) + { + case TILEMAP_SCAN_ROWS: m_mapper.set(*this, FUNC(tilemap_t::scan_rows)); break; + case TILEMAP_SCAN_ROWS_FLIP_X: m_mapper.set(*this, FUNC(tilemap_t::scan_rows_flip_x)); break; + case TILEMAP_SCAN_ROWS_FLIP_Y: m_mapper.set(*this, FUNC(tilemap_t::scan_rows_flip_y)); break; + case TILEMAP_SCAN_ROWS_FLIP_XY: m_mapper.set(*this, FUNC(tilemap_t::scan_rows_flip_xy)); break; + case TILEMAP_SCAN_COLS: m_mapper.set(*this, FUNC(tilemap_t::scan_cols)); break; + case TILEMAP_SCAN_COLS_FLIP_X: m_mapper.set(*this, FUNC(tilemap_t::scan_cols_flip_x)); break; + case TILEMAP_SCAN_COLS_FLIP_Y: m_mapper.set(*this, FUNC(tilemap_t::scan_cols_flip_y)); break; + case TILEMAP_SCAN_COLS_FLIP_XY: m_mapper.set(*this, FUNC(tilemap_t::scan_cols_flip_xy)); break; + default: throw emu_fatalerror("Tilemap init unknown mapper %d", mapper); + } + + init_common(manager, decoder, tile_get_info, tilewidth, tileheight, cols, rows); + return *this; } @@ -720,7 +772,7 @@ void tilemap_t::pixmap_update() if (m_all_tiles_clean) return; -g_profiler.start(PROFILER_TILEMAP_DRAW); + auto profile = g_profiler.start(PROFILER_TILEMAP_DRAW); // flush the dirty state to all tiles as appropriate realize_all_dirty_tiles(); @@ -734,8 +786,6 @@ g_profiler.start(PROFILER_TILEMAP_DRAW); // mark it all clean m_all_tiles_clean = true; - -g_profiler.stop(); } @@ -745,7 +795,7 @@ g_profiler.stop(); void tilemap_t::tile_update(logical_index logindex, u32 col, u32 row) { -g_profiler.start(PROFILER_TILEMAP_UPDATE); + auto profile = 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]; @@ -770,8 +820,6 @@ g_profiler.start(PROFILER_TILEMAP_UPDATE); m_gfx_used |= 1 << m_tileinfo.gfxnum; m_gfx_dirtyseq[m_tileinfo.gfxnum] = m_tileinfo.decoder->gfx(m_tileinfo.gfxnum)->dirtyseq(); } - -g_profiler.stop(); } @@ -808,8 +856,8 @@ u8 tilemap_t::tile_draw(const u8 *pendata, u32 x0, u32 y0, u32 palette_base, u8 u8 andmask = ~0, ormask = 0; for (u16 ty = 0; ty < m_tileheight; ty++) { - u16 *pixptr = &m_pixmap.pix16(y0, x0); - u8 *flagsptr = &m_flagsmap.pix8(y0, x0); + u16 *pixptr = &m_pixmap.pix(y0, x0); + u8 *flagsptr = &m_flagsmap.pix(y0, x0); // pre-advance to the next row y0 += dy0; @@ -861,7 +909,7 @@ u8 tilemap_t::tile_apply_bitmask(const u8 *maskdata, u32 x0, u32 y0, u8 category for (u16 ty = 0; ty < m_tileheight; ty++) { // pre-advance to the next row - u8 *flagsptr = &m_flagsmap.pix8(y0, x0); + u8 *flagsptr = &m_flagsmap.pix(y0, x0); y0 += dy0; // anywhere the bitmask is 0 should be transparent @@ -945,12 +993,13 @@ void tilemap_t::draw_common(screen_device &screen, _BitmapClass &dest, const rec if (!m_enable) return; -g_profiler.start(PROFILER_TILEMAP_DRAW); + auto profile = g_profiler.start(PROFILER_TILEMAP_DRAW); + // configure the blit parameters based on the input parameters - assert(dest.cliprect().contains(cliprect)); - assert(screen.cliprect().contains(cliprect)); blit_parameters blit; configure_blit_parameters(blit, screen.priority(), cliprect, flags, priority, priority_mask); + assert(dest.cliprect().contains(cliprect)); + assert(screen.cliprect().contains(cliprect) || blit.tilemap_priority_code == 0xff00); // flush the dirty state to all tiles as appropriate realize_all_dirty_tiles(); @@ -1043,7 +1092,6 @@ g_profiler.start(PROFILER_TILEMAP_DRAW); } } } -g_profiler.stop(); } void tilemap_t::draw(screen_device &screen, bitmap_ind16 &dest, const rectangle &cliprect, u32 flags, u8 priority, u8 priority_mask) @@ -1082,19 +1130,19 @@ void tilemap_t::draw_roz_common(screen_device &screen, _BitmapClass &dest, const return; } -g_profiler.start(PROFILER_TILEMAP_DRAW_ROZ); + auto profile = g_profiler.start(PROFILER_TILEMAP_DRAW_ROZ); + // configure the blit parameters - assert(dest.cliprect().contains(cliprect)); - assert(screen.cliprect().contains(cliprect)); blit_parameters blit; configure_blit_parameters(blit, screen.priority(), cliprect, flags, priority, priority_mask); + assert(dest.cliprect().contains(cliprect)); + assert(screen.cliprect().contains(cliprect) || blit.tilemap_priority_code == 0xff00); // 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, @@ -1130,7 +1178,16 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b // look up priority and destination base addresses for y1 bitmap_ind8 &priority_bitmap = *blit.priority; - u8 *priority_baseaddr = &priority_bitmap.pix8(y1, xpos); + u8 *priority_baseaddr = nullptr; + int prio_rowpixels = 0; + if (priority_bitmap.valid()) + { + prio_rowpixels = priority_bitmap.rowpixels(); + priority_baseaddr = &priority_bitmap.pix(y1, xpos); + } + else + assert((blit.tilemap_priority_code & 0xffff) == 0xff00); + typename _BitmapClass::pixel_t *dest_baseaddr = nullptr; int dest_rowpixels = 0; if (dest.valid()) @@ -1146,8 +1203,8 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b y2 -= ypos; // get tilemap pixels - const u16 *source_baseaddr = &m_pixmap.pix16(y1); - const u8 *mask_baseaddr = &m_flagsmap.pix8(y1); + const u16 *source_baseaddr = &m_pixmap.pix(y1); + const u8 *mask_baseaddr = &m_flagsmap.pix(y1); // get start/stop columns, rounding outward int mincol = x1 / m_tilewidth; @@ -1208,7 +1265,7 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b { const u16 *source0 = source_baseaddr + x_start; typename _BitmapClass::pixel_t *dest0 = dest_baseaddr + x_start; - u8 *pmap0 = priority_baseaddr + x_start; + u8 *pmap0 = priority_baseaddr ? (priority_baseaddr + x_start) : nullptr; // if we were opaque, use the opaque renderer if (prev_trans == WHOLLY_OPAQUE) @@ -1226,7 +1283,7 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b dest0 += dest_rowpixels; source0 += m_pixmap.rowpixels(); - pmap0 += priority_bitmap.rowpixels(); + pmap0 += prio_rowpixels; } } @@ -1248,7 +1305,7 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b dest0 += dest_rowpixels; source0 += m_pixmap.rowpixels(); mask0 += m_flagsmap.rowpixels(); - pmap0 += priority_bitmap.rowpixels(); + pmap0 += prio_rowpixels; } } } @@ -1263,7 +1320,7 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b break; // advance to the next row on all our bitmaps - priority_baseaddr += priority_bitmap.rowpixels() * (nexty - y); + priority_baseaddr += prio_rowpixels * (nexty - y); source_baseaddr += m_pixmap.rowpixels() * (nexty - y); mask_baseaddr += m_flagsmap.rowpixels() * (nexty - y); dest_baseaddr += dest_rowpixels * (nexty - y); @@ -1303,7 +1360,7 @@ void tilemap_t::draw_roz_core(screen_device &screen, _BitmapClass &destbitmap, c const int ymask = m_pixmap.height() - 1; const int widthshifted = m_pixmap.width() << 16; const int heightshifted = m_pixmap.height() << 16; - u32 priority = blit.tilemap_priority_code; + const u32 priority = blit.tilemap_priority_code; u8 mask = blit.mask; u8 value = blit.value; u8 alpha = blit.alpha; @@ -1344,9 +1401,9 @@ void tilemap_t::draw_roz_core(screen_device &screen, _BitmapClass &destbitmap, c u32 cy = starty >> 16; // get source and priority pointers - u8 *pri = &priority_bitmap.pix8(sy, sx); - const u16 *src = &m_pixmap.pix16(cy); - const u8 *maskptr = &m_flagsmap.pix8(cy); + u8 *pri = (priority != 0xff00) ? &priority_bitmap.pix(sy, sx) : nullptr; + const u16 *src = &m_pixmap.pix(cy); + const u8 *maskptr = &m_flagsmap.pix(cy); typename _BitmapClass::pixel_t *dest = &destbitmap.pix(sy, sx); // loop over columns @@ -1356,14 +1413,16 @@ void tilemap_t::draw_roz_core(screen_device &screen, _BitmapClass &destbitmap, c if ((maskptr[cx >> 16] & mask) == value) { ROZ_PLOT_PIXEL(src[cx >> 16]); - *pri = (*pri & (priority >> 8)) | priority; + if (priority != 0xff00) + *pri = (*pri & (priority >> 8)) | priority; } // advance in X cx += incxx; x++; ++dest; - pri++; + if (priority != 0xff00) + pri++; } } @@ -1386,16 +1445,17 @@ void tilemap_t::draw_roz_core(screen_device &screen, _BitmapClass &destbitmap, c // get dest and priority pointers typename _BitmapClass::pixel_t *dest = &destbitmap.pix(sy, sx); - u8 *pri = &priority_bitmap.pix8(sy, sx); + u8 *pri = (priority != 0xff00) ? &priority_bitmap.pix(sy, sx) : nullptr; // loop over columns while (x <= ex) { // plot if we match the mask - if ((m_flagsmap.pix8((cy >> 16) & ymask, (cx >> 16) & xmask) & mask) == value) + if ((m_flagsmap.pix((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; + ROZ_PLOT_PIXEL(m_pixmap.pix((cy >> 16) & ymask, (cx >> 16) & xmask)); + if (priority != 0xff00) + *pri = (*pri & (priority >> 8)) | priority; } // advance in X @@ -1403,7 +1463,8 @@ void tilemap_t::draw_roz_core(screen_device &screen, _BitmapClass &destbitmap, c cy += incxy; x++; ++dest; - pri++; + if (priority != 0xff00) + pri++; } // advance in Y @@ -1426,17 +1487,18 @@ void tilemap_t::draw_roz_core(screen_device &screen, _BitmapClass &destbitmap, c // get dest and priority pointers typename _BitmapClass::pixel_t *dest = &destbitmap.pix(sy, sx); - u8 *pri = &priority_bitmap.pix8(sy, sx); + u8 *pri = (priority != 0xff00) ? &priority_bitmap.pix(sy, sx) : nullptr; // 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) + if ((m_flagsmap.pix(cy >> 16, cx >> 16) & mask) == value) { - ROZ_PLOT_PIXEL(m_pixmap.pix16(cy >> 16, cx >> 16)); - *pri = (*pri & (priority >> 8)) | priority; + ROZ_PLOT_PIXEL(m_pixmap.pix(cy >> 16, cx >> 16)); + if (priority != 0xff00) + *pri = (*pri & (priority >> 8)) | priority; } // advance in X @@ -1444,7 +1506,8 @@ void tilemap_t::draw_roz_core(screen_device &screen, _BitmapClass &destbitmap, c cy += incxy; x++; ++dest; - pri++; + if (priority != 0xff00) + pri++; } // advance in Y @@ -1493,6 +1556,10 @@ void tilemap_t::draw_debug(screen_device &screen, bitmap_rgb32 &dest, u32 scroll void tilemap_t::get_info_debug(u32 col, u32 row, u8 &gfxnum, u32 &code, u32 &color) { // first map to the memory index + if (m_attributes & TILEMAP_FLIPX) + col = (m_cols - 1) - col; + if (m_attributes & TILEMAP_FLIPY) + row = (m_rows - 1) - row; tilemap_memory_index memindex = memory_index(col, row); // next invoke the get info callback @@ -1501,10 +1568,14 @@ void tilemap_t::get_info_debug(u32 col, u32 row, u8 &gfxnum, u32 &code, u32 &col // get the GFX number and code gfxnum = m_tileinfo.gfxnum; code = m_tileinfo.code; + color = m_tileinfo.palette_base; - // work back from the palette base to get the color - const gfx_element &gfx = *m_tileinfo.decoder->gfx(gfxnum); - color = (m_tileinfo.palette_base - gfx.colorbase()) / gfx.granularity(); + if (gfxnum != 0xff) + { + // work back from the palette base to get the color + const gfx_element &gfx = *m_tileinfo.decoder->gfx(gfxnum); + color = (color - gfx.colorbase()) / gfx.granularity(); + } } @@ -1529,14 +1600,13 @@ tilemap_manager::tilemap_manager(running_machine &machine) tilemap_manager::~tilemap_manager() { - // detach all device tilemaps since they will be destroyed - // as subdevices elsewhere + // 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) - if (tmap.device() != nullptr) + if (tmap.m_device) { found = true; m_tilemap_list.detach(tmap); @@ -1547,34 +1617,21 @@ tilemap_manager::~tilemap_manager() //------------------------------------------------- -// set_flip_all - set a global flip for all the -// tilemaps +// create - allocate a tilemap //------------------------------------------------- tilemap_t &tilemap_manager::create(device_gfx_interface &decoder, tilemap_get_info_delegate tile_get_info, tilemap_mapper_delegate mapper, u16 tilewidth, u16 tileheight, u32 cols, u32 rows, tilemap_t *allocated) { - if (allocated == nullptr) - allocated = global_alloc(tilemap_t); + if (!allocated) + allocated = new tilemap_t(machine().root_device()); 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, u16 tilewidth, u16 tileheight, u32 cols, u32 rows, tilemap_t *allocated) { - if (allocated == nullptr) - allocated = global_alloc(tilemap_t); - - switch (mapper) - { - case TILEMAP_SCAN_ROWS :return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, tilemap_mapper_delegate(FUNC(tilemap_t::scan_rows), allocated), tilewidth, tileheight, cols, rows)); - case TILEMAP_SCAN_ROWS_FLIP_X:return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, tilemap_mapper_delegate(FUNC(tilemap_t::scan_rows_flip_x), allocated), tilewidth, tileheight, cols, rows)); - case TILEMAP_SCAN_ROWS_FLIP_Y:return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, tilemap_mapper_delegate(FUNC(tilemap_t::scan_rows_flip_y), allocated), tilewidth, tileheight, cols, rows)); - case TILEMAP_SCAN_ROWS_FLIP_XY:return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, tilemap_mapper_delegate(FUNC(tilemap_t::scan_rows_flip_xy),allocated), tilewidth, tileheight, cols, rows)); - case TILEMAP_SCAN_COLS:return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, tilemap_mapper_delegate(FUNC(tilemap_t::scan_cols),allocated), tilewidth, tileheight, cols, rows)); - case TILEMAP_SCAN_COLS_FLIP_X:return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, tilemap_mapper_delegate(FUNC(tilemap_t::scan_cols_flip_x),allocated), tilewidth, tileheight, cols, rows)); - case TILEMAP_SCAN_COLS_FLIP_Y:return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, tilemap_mapper_delegate(FUNC(tilemap_t::scan_cols_flip_y),allocated), tilewidth, tileheight, cols, rows)); - case TILEMAP_SCAN_COLS_FLIP_XY:return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, tilemap_mapper_delegate(FUNC(tilemap_t::scan_cols_flip_xy),allocated), tilewidth, tileheight, cols, rows)); - default: throw emu_fatalerror("Tilemap manager create unknown mapper %d", mapper); - } + if (!allocated) + allocated = new tilemap_t(machine().root_device()); + return m_tilemap_list.append(allocated->init(*this, decoder, tile_get_info, mapper, tilewidth, tileheight, cols, rows)); } @@ -1615,16 +1672,19 @@ DEFINE_DEVICE_TYPE(TILEMAP, tilemap_device, "tilemap", "Tilemap") //------------------------------------------------- tilemap_device::tilemap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : device_t(mconfig, TILEMAP, tag, owner, clock), - m_gfxdecode(*this, finder_base::DUMMY_TAG), - m_standard_mapper(TILEMAP_STANDARD_COUNT), - m_bytes_per_entry(0), - 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) + : device_t(mconfig, TILEMAP, tag, owner, clock) + , tilemap_t(static_cast<device_t &>(*this)) + , m_gfxdecode(*this, finder_base::DUMMY_TAG) + , m_get_info(*this) + , m_standard_mapper(TILEMAP_STANDARD_COUNT) + , m_mapper(*this) + , m_bytes_per_entry(0) + , 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) { } @@ -1719,14 +1779,14 @@ void tilemap_device::device_start() throw device_missing_dependencies(); // bind our callbacks - m_get_info.bind_relative_to(*owner()); - m_mapper.bind_relative_to(*owner()); + m_get_info.resolve(); + m_mapper.resolve(); // 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); + 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); + 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()); @@ -1736,7 +1796,7 @@ void tilemap_device::device_start() // look for an extension entry std::string tag_ext = std::string(tag()).append("_ext"); - share = memshare(tag_ext.c_str()); + share = memshare(tag_ext); if (share != nullptr) m_extmem.set(*share, m_bytes_per_entry); } |