//------------------------------------------------- // transpen_mask - return a mask of pens that // whose indirect values match the given // transcolor //------------------------------------------------- public u32 transpen_mask(gfx_element gfx, u32 color, indirect_pen_t transcolor) { u32 entry = gfx.colorbase() + (color % gfx.colors()) * gfx.granularity(); // make sure we are in range assert(entry < m_indirect_pens.size()); assert(gfx.depth() <= 32); // either gfx->color_depth entries or as many as we can get up until the end int count = (int)Math.Min((UInt32)gfx.depth(), m_indirect_pens.size() - entry); // set a bit anywhere the transcolor matches u32 mask = 0; for (int bit = 0; bit < count; bit++) { if (m_indirect_pens[(int)entry++] == transcolor) { mask |= (UInt32)1 << bit; } } // return the final mask return(mask); }
//------------------------------------------------- // render_object: Internal processing callback // that renders to the backing bitmap and then // copies the result to the destination. //------------------------------------------------- void render_object(bitmap_ind16 bitmap, rectangle cliprect, Pointer <uint16_t> entry) //void atari_motion_objects_device::render_object(bitmap_ind16 &bitmap, const rectangle &cliprect, const uint16_t *entry) { // select the gfx element and save off key information int rawcode = (int)m_codemask.extract(entry); gfx_element gfx = m_gfxdecode.op0.gfx(m_gfxlookup[rawcode >> 8]); int save_granularity = gfx.granularity(); int save_colorbase = (int)gfx.colorbase(); int save_colors = (int)gfx.colors(); gfx.set_granularity(1); gfx.set_colorbase(0); gfx.set_colors(65536); // extract data from the various words int code = (int)m_codelookup[rawcode]; int color = m_colorlookup[m_colormask.extract(entry)]; int xpos = m_xposmask.extract(entry) + m_xoffset; int ypos = -m_yposmask.extract(entry); int hflip = m_hflipmask.extract(entry); int vflip = m_vflipmask.extract(entry); int width = m_widthmask.extract(entry) + 1; int height = m_heightmask.extract(entry) + 1; int priority = m_prioritymask.extract(entry); // compute the effective color, merging in priority color = (color * save_granularity) | (priority << PRIORITY_SHIFT); color += m_atari_motion_objects_config.m_palettebase; // add in the scroll positions if we're not in absolute coordinates if (m_absolutemask.extract(entry) == 0) { xpos -= (int)m_xscroll; ypos -= (int)m_yscroll; } // adjust for height ypos -= height << m_tileyshift; // handle previous hold bits if (m_next_xpos != 123456) { xpos = (int)m_next_xpos; } m_next_xpos = 123456; // check for the hold bit if (m_neighbormask.extract(entry) != 0) { if (!m_atari_motion_objects_config.m_nextneighbor) { xpos = (int)m_last_xpos + m_tilewidth; } else { m_next_xpos = (uint32_t)(xpos + m_tilewidth); } } m_last_xpos = (uint32_t)xpos; // adjust the final coordinates xpos &= m_bitmapxmask; ypos &= m_bitmapymask; if (xpos >= bitmap.width()) { xpos -= m_bitmapwidth; } if (ypos >= bitmap.height()) { ypos -= m_bitmapheight; } // is this one special? if (m_specialmask.mask() == 0 || m_specialmask.extract(entry) != m_atari_motion_objects_config.m_specialvalue) { // adjust for h flip int xadv = m_tilewidth; if (hflip != 0) { xpos += (width - 1) << m_tilexshift; xadv = -xadv; } // adjust for v flip int yadv = m_tileheight; if (vflip != 0) { ypos += (height - 1) << m_tileyshift; yadv = -yadv; } // standard order is: loop over Y first, then X if (!m_atari_motion_objects_config.m_swapxy) { // loop over the height for (int y = 0, sy = ypos; y < height; y++, sy += yadv) { // clip the Y coordinate if (sy <= cliprect.top() - m_tileheight) { code += width; continue; } else if (sy > cliprect.bottom()) { break; } // loop over the width for (int x = 0, sx = xpos; x < width; x++, sx += xadv, code++) { // clip the X coordinate if (sx <= -cliprect.left() - m_tilewidth || sx > cliprect.right()) { continue; } // draw the sprite gfx.transpen_raw(bitmap, cliprect, (u32)code, (u32)color, hflip, vflip, sx, sy, m_atari_motion_objects_config.m_transpen); mark_dirty(sx, sx + m_tilewidth - 1, sy, sy + m_tileheight - 1); } } } // alternative order is swapped else { // loop over the width for (int x = 0, sx = xpos; x < width; x++, sx += xadv) { // clip the X coordinate if (sx <= cliprect.left() - m_tilewidth) { code += height; continue; } else if (sx > cliprect.right()) { break; } // loop over the height for (int y = 0, sy = ypos; y < height; y++, sy += yadv, code++) { // clip the X coordinate if (sy <= -cliprect.top() - m_tileheight || sy > cliprect.bottom()) { continue; } // draw the sprite gfx.transpen_raw(bitmap, cliprect, (u32)code, (u32)color, hflip, vflip, sx, sy, m_atari_motion_objects_config.m_transpen); mark_dirty(sx, sx + m_tilewidth - 1, sy, sy + m_tileheight - 1); } } } } // restore original gfx information gfx.set_granularity((u16)save_granularity); gfx.set_colorbase((u16)save_colorbase); gfx.set_colors((u32)save_colors); }