scrolling up help

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Matze2002

Re:scrolling up help

Post by Matze2002 »

Hi,
can i use the asm source in Protected Mode ?

What must i do to use this asm source inline ?
I want use this function inline in my c source.

thanks,bye
Matze
PlayOS

Re:scrolling up help

Post by PlayOS »

All you have to do is convert it to gcc inline style asm, you could compile it as is with nasm, and then just link it in to your kernel. It is PMode code and it is ready to be called from C, you just have to change 'RET 4' to 'RET' in both of the functions. This code assumes a zero based data segment, if you use a segment just for video (ie you have a segment with a base of 0xb8000) then just subtract 0xb8000 from all absolute address within the functions.
PlayOS

Re:scrolling up help

Post by PlayOS »

OK, to make it inline you will need to remove some code from the start and end of each function, just the stuff to do with the stack and the argument. I am no good with gcc inline asm so I cannot help you with the conversion, sorry.
Schol-R-LEA

Re:scrolling up help

Post by Schol-R-LEA »

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.
Schol-R-LEA

Re:scrolling up help

Post by Schol-R-LEA »

RE: my last posting: C programmers will probably have noticed by now that this is roughly equivalent to:

Code: Select all

/* assumes page size and other related constants defined elsewhere */

void scrollfwd(int lines)
{
  char* scroll_region;
  long scroll_size;

  memset((void *) SwapPageTop, 0, (size_t) CurrPageSize);
  scroll_size = (lines * ScrWidth) << 1;
  scroll_region = CurrPageTop - scroll_size; 
  memcpy((void *) SwapPageTop, (const void *) scroll_region, (size_t) scroll_size);
  memcpy((void *) CurrPageTop, (const void*) SwapPageTop, (size_t) CurrPageSize);
}
where

void* memcpy(void* to, const void* from, size_t count) and void* memset(void* buf, int ch, size_t cont)

can be more or less implemented in NASM as:

Code: Select all

_memcpy:
   push ebp
   mov ebp, esp
   mov esi, [ebp + 8]    ; first arg - src pointer
   mov edi, [ebp +12]   ; 2nd arg - dest pointer
   mov ecx, [ebp + 16] ; 3rd arg - string size in bytes
   mov eax, edi             ; return value - save now, before EDI gets trashed
   cdl                             ; make sure direction flag set correctly
   rep movsb                 ; block-copy from src to dest
   pop ebp                     ; restore caller's stack frame
   ret

_memset:
   push ebp
   mov ebp, esp
   mov edi, [ebp + 8]    ; first arg - buffer pointer
   mov edi, [ebp +12]   ; 2nd arg - value to write
   mov eax, [ebp + 16] ; 3rd arg - string size in bytes
   push edi             ; return value - save now, before EDI gets trashed
   cdl                      ; make sure direction flag set correctly
   rep stosb
   pop eax              ; recover return value
   pop ebp              ; restore caller's stack frame
   ret
PlayOS

Re:scrolling up help

Post by PlayOS »

After browsing your code, I am not sure but are copying the visible screen to the second text page, scrolling in the process by not copying the lines that are to be scrolled. Then at the end you copy the second page back to the visible page, now the data is scrolled up. But my question is how is this faster or smoother?

You are copying the data two times, and you are copying the data byte by byte, surley this isn't as fast as copying the data once, dword by dword?

Also, to make things look smoother in my code you could just clear each dword after copying it, this only has to be done on the lines that are be exposed after the scroll. There are some optimizations that could be done in the code I posted, however.

Also, even though it is more limited, the ultimate way for speed and smoothness is to do a hardware scroll....

Anyway, the code you have posted should work (as far as I can tell at a glance). But I would divide all of your values by 4 and do a 'rep movsd' instead of 'rep movsb' this of course would be 4 times as fast as your current implementation. :)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:scrolling up help

Post by Pype.Clicker »

want it smoother ? well then just use the VGA registers to move around the video memory or the fine-pitching (pixel-per-pixel scrolling in text mode, hehe :)
Schol-R-LEA

Re:scrolling up help

Post by Schol-R-LEA »

PlayOS wrote: After browsing your code, I am not sure but are copying the visible screen to the second text page, scrolling in the process by not copying the lines that are to be scrolled. Then at the end you copy the second page back to the visible page, now the data is scrolled up. But my question is how is this faster or smoother?
I'm not sure it is, to be honest. If I had been able to use page-flipping, then I'm sure that it would be, as the rep functions are very highly optimized, running much faster than the equivalent loops. The fact that I do it twice probably negates the value, though. You are correct that it should go faster if I moved the data by doubleword increments, and there are certainly other ways I could optimize it, too. I was mostly interested in getting it working, and in seeing if anyone could help with the text-page switching issue.
PlayOS

Re:scrolling up help

Post by PlayOS »

What is meant by page-flipping?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:scrolling up help

Post by Pype.Clicker »

your video memory is larger than a screen (actually, it is about 4 screens large!) thus you can do a scrolling by

Code: Select all

if (even) {
memcpy(screen1+1*LINE,screen2,24*LINE);
show(screen2);
} else {
memcpy(screen2+1*LINE,screen1,24*LINE);
show(screen1);
}
even++;
where screen1 is 0xb8000 and screen2 is, say 0xb9000 :)
Post Reply