/************************************* * * Main refresh * *************************************/ uint32_t screen_update_atarisy2(screen_device screen, bitmap_ind16 bitmap, rectangle cliprect) { // start drawing m_mob.op0.draw_async(cliprect); // reset priorities bitmap_ind8 priority_bitmap = screen.priority(); priority_bitmap.fill(0, cliprect); // draw the playfield m_playfield_tilemap.op0.tilemap.draw(screen, bitmap, cliprect, 0, 0); m_playfield_tilemap.op0.tilemap.draw(screen, bitmap, cliprect, 1, 1); m_playfield_tilemap.op0.tilemap.draw(screen, bitmap, cliprect, 2, 2); m_playfield_tilemap.op0.tilemap.draw(screen, bitmap, cliprect, 3, 3); // draw and merge the MO bitmap_ind16 mobitmap = m_mob.op0.bitmap(); for (sparse_dirty_rect rect = m_mob.op0.first_dirty_rect(cliprect); rect != null; rect = rect.next()) { for (int y = rect.m_rect.top(); y <= rect.m_rect.bottom(); y++) { PointerU16 mo = mobitmap.pix(y); //uint16_t const *const mo = &mobitmap.pix(y); PointerU16 pf = bitmap.pix(y); //uint16_t *const pf = &bitmap.pix(y); PointerU8 pri = priority_bitmap.pix(y); //uint8_t const *const pri = &priority_bitmap.pix(y); for (int x = rect.m_rect.left(); x <= rect.m_rect.right(); x++) { if (mo[x] != 0xffff) { int mopriority = mo[x] >> atari_motion_objects_device.PRIORITY_SHIFT; // high priority PF? if (((mopriority + pri[x]) & 2) != 0) { // only gets priority if PF pen is less than 8 if ((pf[x] & 0x08) == 0) { pf[x] = (uint16_t)(mo[x] & atari_motion_objects_device.DATA_MASK); } } // low priority else { pf[x] = (uint16_t)(mo[x] & atari_motion_objects_device.DATA_MASK); } } } } } // add the alpha on top m_alpha_tilemap.op0.tilemap.draw(screen, bitmap, cliprect, 0, 0); return(0); }
//------------------------------------------------- // first_dirty_rect -- return the first dirty // rectangle in the list //------------------------------------------------- public sparse_dirty_rect first_dirty_rect(rectangle cliprect) { // if what we have is valid, just return it again if (m_rect_list_bounds == cliprect) { return(m_rect_list.empty() ? null : m_rect_list.first()); } // reclaim the dirty list and start over m_rect_allocator.reclaim_all(m_rect_list); // compute dirty space rectangle coordinates int sx = cliprect.min_x >> m_granularity; int ex = cliprect.max_x >> m_granularity; int sy = cliprect.min_y >> m_granularity; int ey = cliprect.max_y >> m_granularity; int tilesize = 1 << m_granularity; // loop over all grid rows that intersect our cliprect for (int y = sy; y <= ey; y++) { PointerU8 dirtybase = m_bitmap.pix(y); //uint8_t *dirtybase = &m_bitmap.pix(y); sparse_dirty_rect currect = null; // loop over all grid columns that intersect our cliprect for (int x = sx; x <= ex; x++) { // if this tile is not dirty, end our current run and continue if (dirtybase[x] == 0) { if (currect != null) { currect.m_rect &= cliprect; //*currect &= cliprect; } currect = null; continue; } // if we can't add to an existing rect, create a new one if (currect == null) { // allocate a new rect and add it to the list currect = m_rect_list.append(m_rect_allocator.alloc()); // make a rect describing this grid square currect.m_rect.min_x = x << m_granularity; currect.m_rect.max_x = currect.m_rect.min_x + tilesize - 1; currect.m_rect.min_y = y << m_granularity; currect.m_rect.max_y = currect.m_rect.min_y + tilesize - 1; } // if we can add to the previous rect, just expand its width else { currect.m_rect.max_x += tilesize; } } // clip the last rect to the cliprect if (currect != null) { currect.m_rect &= cliprect; } } // mark the list as valid m_rect_list_bounds = cliprect; return(m_rect_list.empty() ? null : m_rect_list.first()); }