I think I know why the GR screen wiggles when the screen scrolls.

The scroll routine hits softswitches c054 and c055 which causes partial updating to occur.

I put a little printf to show me what was happening:

In the apple2e_state:screen_update routine:
Code
       else    // lo-res
                {
                        if (m_video->m_mix)
                        {
                                if ((m_video->m_dhires) && (m_video->m_80col))
                                {
                                        m_video->dlores_update(screen, bitmap, cliprect, 0, 159);
                                }
                                else
                                {       if (m_joybuttons->read() & 0x40) printf("cliprect = top bot %d,%d, left rt %d,%d  wid ht  %d,%d\n",cliprect.top(),cliprect.bottom(),cliprect.left(),cliprect.right(),cliprect.width(),cliprect.height());
                                        m_video->lores_update(screen, bitmap, cliprect, 0, 159);
                                }


Code
cliprect = top bot 0,85, left rt 0,559  wid ht  560,86
cliprect = top bot 86,86, left rt 0,254  wid ht  255,1
getting to the switch  offset=54
cliprect = top bot 86,86, left rt 254,559  wid ht  306,1
cliprect = top bot 87,191, left rt 0,559  wid ht  560,105
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
getting to the switch  offset=55
cliprect = top bot 0,19, left rt 0,559  wid ht  560,20
cliprect = top bot 20,20, left rt 0,2  wid ht  3,1
getting to the switch  offset=54
cliprect = top bot 20,20, left rt 2,366  wid ht  365,1
cliprect = top bot 20,191, left rt 0,559  wid ht  560,172
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
getting to the switch  offset=55
getting to the switch  offset=54

and when it hits the softswitch, it triggers a partial update

Code
 
              case 0x54:  // set page 1
                        if (!m_video->m_80col)
                        {
                                m_screen->update_now();   // This must trigger the partial update
                        }
                        m_page2 = false;
                        m_video->m_page2 = false;
                        auxbank_update();
                        break;

                case 0x55:  // set page 2
                        if (!m_video->m_80col)
                        {
                                m_screen->update_now();
                        }
                        m_page2 = true;
                        m_video->m_page2 = true;
                        auxbank_update();
                        break;


without the switches being hit, it will do an update all at once:
Code
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192

So I think what's happening is that it's coming into the lores_update with a non multiple of 8 as the top of the cliprect.

If we and the row with 0xf8 we can lock it to a multiple of 8 and set our starty to row % 8. That seems to fix the wiggle (just in my limited testing.)


Code
  beginrow = (std::max)(beginrow, cliprect.top());
        endrow = (std::min)(endrow, cliprect.bottom());

        if (!(m_sysconfig & 0x03))
        {
                for (row = beginrow; row <= endrow; row += 8)
                {
                        for (col = 0; col < 40; col++)
                        {
                                /* calculate adderss */      // adderss 8-)
                                address = start_address + ((((row/8) & 0x07) << 7) | (((row/8) & 0x18) * 5 + col));

                                /* perform the lookup */
                                code = m_ram_ptr[address];

                                int starty = row % 8;   // get the low three bits

                                /* and now draw */
                                for (y = starty; y < 4; y++)   // start from starty
                                {
                                        if ((row + y) <= endrow)
                                        {
                                                for (x = 0; x < 14; x++)
                                                {
                                                        bitmap.pix16((row & 0xf8) + y, col * 14 + x) = (code >> 0) & 0x0F;    // and the row with 0xf8
                                                }
                                        }
                                }
                                for (y = starty+4; y < 8; y++)  // start from starty + 4
                                {
                                        if ((row + y) <= endrow)
                                        {
                                                for (x = 0; x < 14; x++)
                                                {
                                                        bitmap.pix16((row & 0xf8) + y, col * 14 + x) = (code >> 4) & 0x0F;
                                                }
                                        }
                                }
                        }
                }
        }



That got me to thinking, maybe the hgr_update routine is getting a little confused with getting different cliprects coming in, this modification seems to solve most of the glitching (though I did see a little speckle now and then).

(I don't completely understand the routine, so my assumptions may be wrong)

Code
void a2_video_device::hgr_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
...

      for (row = beginrow; row <= endrow; row++)
        {
                for (col = begincol; col < endcol; col++)
                {
                        offset = ((((row/8) & 0x07) << 7) | (((row/8) & 0x18) * 5 + col)) | ((row & 7) << 10);
                        vram_row[1+col] = vram[offset];
                }

//              p = &bitmap.pix16(row);
//              for (col = 0; col < 40; col++)

                for (col = begincol; col < endcol; col++)     // if we wanted to limit it to the cliprect start at begincol and end at endcol
                {
                p = &bitmap.pix16(row,col*14);  // update the p pointer for the start of our row and col


                        w =     (((uint32_t) vram_row[col+0] & 0x7f) <<  0)
                                |   (((uint32_t) vram_row[col+1] & 0x7f) <<  7)
                                |   (((uint32_t) vram_row[col+2] & 0x7f) << 14);



Last edited by Golden Child; 05/12/19 11:01 PM.