Glancing through this thread, it occured to me that an alternative approach simply cries out for consideration: block-move the contents of the current text page below the point to be scrolled to to one of the other three text pages, then page-flip. It would be both faster and smoother than the code I see above. I should have realized that there was a reason no one had mentioned this idea...
In researching this, I found that there seemed to be little if any information on swapping text pages without using a BIOS call. Still, the idea had some merit - if nothing else, the unsed text pages could still be used as temporary space. So I came up with this code and got it to work well enough to post:
Code: Select all
;; scrollfwd - moves text n lines up.
;; arguments -
;; ah = number of rows to scroll
scrollfwd:
pushad ; save the registers to be used
cld ; make sure direction flag is set to increment
mov cx, CurrPageSize ; get the size of the text pages in bytes
mov di, SwapPageTop ; set the destination to the new text screen
push cx ; CX, and DI need to have same values
push di ; used and modified in two different places
mov al, 0 ; clear the swap page of any garbage
rep stosb ; copy zero into every byte of the swap text page
pop di
pop cx
mov al, ah ; put parameter into al, where it can be used
mov bl, ScrWidth
shl bl, 1 ; multiply by two to get size of line in bytes
mul bl ; multiply total columns by rows to scroll
mov si, ax
add si, CurrPageTop ; get the new top of the screen
sub cx, ax ; and subtract by the removed section to get
; the size of the block to be moved
rep movsb ; copy scrolled block to new text screen
mov cx, CurrPageSize ; reset the size of the buffer for swapping back
mov si, SwapPageTop
mov di, CurrPageTop
rep movsb ; move the data back to the current page, shifted up n lines
popad ; restore used registers
ret
While it is not quite perfected, it appears to be rather simpler than most of the alternatives, if nothing else. Note that it does not reset the hardware cursor; this is a Feature, not a bug, as many times you will want to scroll text relative to a stationary cursor. Adding a gotoxy call is no big problem, I hope. Also, while I tested it in real mode, it should work in p-mode without any modifications; if any has the chance to test it out, please let me know.
Scrolling backwards (moving the text down the page) is a fairly trivial modification. Scrolling a text window (that is, moving text in a rectangular area of the screen without moving the text around it) is a fairly serious one (you'd have to first move the whole text page to the swap page, then scroll the changed part line by line between the edges of the window, then copy the modified screen back to the current page).
If anyone has a good reason why this might cause problems - or knows what values to tickle which I/O port with to swap text pages - please let me know.
(EDIT: I have added a bit of code to clear the swap page first, in case there was an material left over from a previous swap. While it makes the code a bit harder to follow, it should be fairly straightforward.)
Assuming Mode 3, then the values should be
ScrWidth == 80,
CurrPageTop == 0xb8000,
CurrPageSize == 0x1000, and
SwapPageTop == 0xb9000 (the beginning of the second text page in mode 3).
C&CW.