-
- if (nblines > nbrows)
- nblines = 0;
- u8 cols = lr.x - ul.x + 1;
-
- // Compute the address
- void *address_far = (void*)(SCREEN_MEM_START(nbcols, nbrows, ul.page));
- dprintf(3, "Scroll, address %p (%d %d %02x)\n"
- , address_far, nbrows, nbcols, ul.page);
-
- if (nblines == 0 && ul.y == 0 && ul.x == 0 && lr.y == nbrows - 1
- && lr.x == nbcols - 1) {
- memset16_far(GET_GLOBAL(vmode_g->sstart), address_far
- , (u16)attr * 0x100 + ' ', nbrows * nbcols * 2);
- return;
- }
- if (dir == SCROLL_UP) {
- u16 i;
- for (i = ul.y; i <= lr.y; i++)
- if ((i + nblines > lr.y) || (nblines == 0))
- memset16_far(GET_GLOBAL(vmode_g->sstart)
- , address_far + (i * nbcols + ul.x) * 2
- , (u16)attr * 0x100 + ' ', cols * 2);
- else
- memcpy16_far(GET_GLOBAL(vmode_g->sstart)
- , address_far + (i * nbcols + ul.x) * 2
- , GET_GLOBAL(vmode_g->sstart)
- , (void*)(((i + nblines) * nbcols + ul.x) * 2)
- , cols * 2);
- return;
- }
-
- u16 i;
- for (i = lr.y; i >= ul.y; i--) {
- if ((i < ul.y + nblines) || (nblines == 0))
- memset16_far(GET_GLOBAL(vmode_g->sstart)
- , address_far + (i * nbcols + ul.x) * 2
- , (u16)attr * 0x100 + ' ', cols * 2);
- else
- memcpy16_far(GET_GLOBAL(vmode_g->sstart)
- , address_far + (i * nbcols + ul.x) * 2
- , GET_GLOBAL(vmode_g->sstart)
- , (void*)(((i - nblines) * nbcols + ul.x) * 2)
- , cols * 2);
- if (i > lr.y)
- break;
+ void *src_far, *dest_far = (void*)SCREEN_MEM_START(nbcols, nbrows, ul.page);
+ int stride = nbcols * 2;
+ if (nblines >= 0) {
+ dest_far += ul.y * stride + ul.x * 2;
+ src_far = dest_far + nblines * stride;
+ } else {
+ // Scroll down
+ nblines = -nblines;
+ dest_far += lr.y * stride + ul.x * 2;
+ src_far = dest_far - nblines * stride;
+ stride = -stride;