I am writing a bootsector game which attempts to copy the chrome dinosaur game you can play when you have no internet.
To do this, I must run from left to right until the player hits a cactus.
How do I achieve this? (How do I make the terminal scroll from right to left so that it looks like I am moving?) So instead of scrolling up and down, I need to scroll from right to left and left to right. I am in 16 bit real mode (BIOS), and I am using nasm / intel syntax.
In CGA-compatible text modes, the screen contents are stored in a 4000 byte buffer starting at B800:000
(unless you change the active display page, but I'll just assume you don't). Each line contains 80 characters and is stored in 160 bytes with 25 lines in total for a resolution of 80×25.
So to scroll the screen left, you have to move the characters of the screen left by the desired number of columns and fill the right hand side of the screen with blank characters. This can be achieved easily using a series of rep movsw
instructions to move the characters followed by rep stosw
instructions to fill the right hand side. Assuming ds = es = b800
and assuming ds:di
points to the beginning of the line, the code for shifting a single line left by c
columns looks like this:
lea si, [di+2*c] ; set up SI to the column that is scrolled
; into the first column of the line
mov cx, 80-c ; copy all columns beginning at that column
; to the end of the row
rep movsw ; scroll row to the left
mov cx, c ; need to blank that many columns
rep stosw ; blank remaining columns
After this code sequence, DI
points to the beginning of the next row. So by iterating this sequence 25 times, we can easily scroll the entire screen:
mov ax, 0xb800 ; screen segment
mov ds, ax ; set up segments
mov es, ax
xor di, di ; point to the beginning of the screen
mov dx, 25 ; process 25 lines
mov ax, 0x0700 ; what to scroll in (grey on black blanks)
.loop: lea si, [di+2*c] ; set up SI to the column that is scrolled
; into the first column of the line
mov cx, 80-c ; copy all columns beginning at that column
; to the end of the row
rep movsw ; scroll row to the left
mov cx, c ; need to blank that many columns
rep stosw ; blank remaining columns
dec dx ; decrement loop counter
jnz .loop ; loop until we're done
And that's really all there is to it. Of course, if c
is variable instead of a constant, the code becomes slightly more complicated. But I'm confident you'll figure it out.
Also note that you seem to refer to the screen as the “BIOS terminal” or something like this. That's not correct. The screen is drawn by the graphics card and can in fact by changed entirely without the BIOS. The BIOS is a set of routines provided in a ROM on your computer. These include some routines to configure graphics modes and to print characters and so on. However, that's purely for convenience. You don't actually need to go through the BIOS to do any of this.