示例#1
0
        //-------------------------------------------------
        //  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);
        }
示例#2
0
        }                                                                                                //void set_config(const atari_motion_objects_config &config) { static_cast<atari_motion_objects_config &>(*this) = config; }

        //void set_xoffset(int xoffset) { m_xoffset = xoffset; }


        // getters
        //int bank() const { return m_bank; }
        //int xscroll() const { return m_xscroll; }
        //int yscroll() const { return m_yscroll; }
        //std::vector<uint32_t> &code_lookup() { return m_codelookup; }
        //std::vector<uint8_t> &color_lookup() { return m_colorlookup; }
        //std::vector<uint8_t> &gfx_lookup() { return m_gfxlookup; }

        // setters
        //void set_bank(int bank) { m_bank = bank; }
        //void set_xscroll(int xscroll) { m_xscroll = xscroll & m_bitmapxmask; }
        //void set_yscroll(int yscroll) { m_yscroll = yscroll & m_bitmapymask; }
        //void set_scroll(int xscroll, int yscroll) { set_xscroll(xscroll); set_yscroll(yscroll); }
        //void set_slipram(uint16_t *ram) { m_slipram = ram; }


        // rendering
        //-------------------------------------------------
        //  draw: Render the motion objects to the
        //  destination bitmap.
        //-------------------------------------------------
        protected override void draw(bitmap_ind16 bitmap, rectangle cliprect)
        {
            // compute start/stop bands
            int startband = ((cliprect.top() + (int)m_yscroll - m_atari_motion_objects_config.m_slipoffset) & m_bitmapymask) >> m_slipshift;
            int stopband  = ((cliprect.bottom() + (int)m_yscroll - m_atari_motion_objects_config.m_slipoffset) & m_bitmapymask) >> m_slipshift;

            if (startband > stopband)
            {
                startband -= m_bitmapheight >> m_slipshift;
            }
            if (m_slipshift == 0)
            {
                stopband = startband;
            }

            // loop over SLIP bands
            for (int band = startband; band <= stopband; band++)
            {
                // compute the starting link and clip for the current band
                rectangle bandclip = cliprect;
                int       link     = 0;
                if (m_slipshift != 0)
                {
                    // extract the link from the SLIP RAM
                    link = (m_slipram[band & m_sliprammask] >> m_linkmask.shift()) & m_linkmask.mask();

                    // compute minimum Y and wrap around if necessary
                    bandclip.min_y = ((band << m_slipshift) - (int)m_yscroll + m_atari_motion_objects_config.m_slipoffset) & m_bitmapymask;
                    if (bandclip.min_y >= bitmap.height())
                    {
                        bandclip.min_y -= m_bitmapheight;
                    }

                    // maximum Y is based on the minimum
                    bandclip.set_height(1 << m_slipshift);

                    // keep within the cliprect
                    bandclip &= cliprect;
                }

                // if this matches the last link, we don't need to re-process the list
                build_active_list(link);

                // initialize the parameters
                m_next_xpos = 123456;

                // safety check
                if (m_activelist == m_activelast.Buffer && m_activelast.Offset == 0)  //if (m_activelist == m_activelast)
                {
                    continue;
                }

                // set the start and end points
                Pointer <uint16_t> first;  //uint16_t *first, *last;
                Pointer <uint16_t> last;
                int step;
                if (m_atari_motion_objects_config.m_reverse)
                {
                    first = m_activelast - 4;
                    last  = new Pointer <uint16_t>(m_activelist);
                    step  = -4;
                }
                else
                {
                    first = new Pointer <uint16_t>(m_activelist);
                    last  = m_activelast - 4;
                    step  = 4;
                }

                // render the mos
                for (Pointer <uint16_t> current = new Pointer <uint16_t>(first); ; current += step)  //for (uint16_t *current = first; ; current += step)
                {
                    render_object(bitmap, bandclip, current);
                    if (current.Buffer == last.Buffer && current.Offset == last.Offset)  //if (current == last)
                    {
                        break;
                    }
                }
            }
        }