Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop screen refreshing - INT 0x10 (Video Services) - In Assembly

My programming environment is an MS-DOS emulator, and I'm programming in Assembly 16 bit.

I'm using the regular text-mode, where I can print characters and use attributes.

On part of the screen I'm drawing a lot of characters every seconds, thousands of them, this creates a nice animation.

The thing is, in order to create the animation, firstly I have to delete the old one, I'm basically printing the space character around a 1000 times. (!) Now, because I'm doing this, every time I redraw the animation there is a slight blinking issue which is noticeable and very annoying.

I'm using the video services to do all the output and animation things. So my first thought was to somehow stop the screen from refreshing, redraw it all, and let the screen continue refreshing on his own.

Because this procedure occurs many times a second, and it has to occur many times, I've found that any other cleaning methods weren't very helpful.

like image 828
coldnine Avatar asked Feb 07 '23 23:02

coldnine


1 Answers

The basic problem is that, if only for an instant, you're showing the user something that they aren't meant to see, a blank screen full of spaces. This is what causes flicker. You could improve on this by erasing the screen faster using a single BIOS call (eg. INT 10h AX=0600h), but a better solution is to only show the user what they're meant to see.

Overwrite everything from top to bottom

One way to do this would be to to change your code so that when it draws a new frame it completely overwrites the old frame. That way there's no need to erase the screen. So for example instead of jumping around drawing text at different positions on screen, start at the top left and draw your text, left to right, top to bottom. Print spaces to move the cursor from position to position. Pretend that you only have two functions you can use, one that move the cursor to the top left of the screen, and one that prints a character and advances the cursor.

Draw where the user can't see it

If that's too difficult you can use an off-screen buffer to do essentially what you're doing now. Erase the the off-screen buffer, draw your text on it, and then display it. That way users never see the erased screen they were never meant to see. You can either create an off-screen buffer in memory and then copy it to the screen or you can flip between pages in video memory.

Draw to an off-screen buffer in memory

Using a buffer in memory means that you can't use BIOS functions to draw on it, but depending on the circumstances this can be a lot more convenient. You'd use normal memory writes to erase buffer and draw your text and then copy the entire buffer to the screen. Essentially this a way of completely overwriting everything from top to bottom as I described above.

Draw to an inactive video page

Flipping between video pages potentially lets you use the same BIOS functions to draw your text as you're doing now. That is, assuming they take an argument in BH specifying which page to use. Not all BIOS functions have this, notably the BIOS function INT 10h, AH=06h I mentioned earlier doesn't. You'd use two video pages, 0 and 1, and you'd need to keep track of which page is currently active and shown to the user. You'd then erase and draw your text on the inactive page, and when you're done you'd flip pages, making the inactive page the active page. To do this you'd use INT 10h AX=05XX, where XX is the page number to make active.

Writing to video memory directly

A more advanced technique would be to write to video memory directly. Back when MS-DOS was popular PCs were so slow that using the BIOS to draw text was generally way too slow for any sort of practical animation. Instead most applications that did things like this wrote directly to video memory, bypassing the slow BIOS routines. You can use any of the techniques described above in combination with this. For example you can draw to an off-screen buffer in normal memory and then copy ("blit") it to video memory with a REP MOVS instruction.

The downside of bypassing the BIOS it makes your code a bit less portable. For example the original IBM PC Monochrome Display Adapter (MDA) and Color Graphics Adapter (CGA) had their video memory in different locations (B000:0000 and B800:0000 respectively). Other third party not 100% PC compatible computers were even weirder. Some didn't support text modes, the BIOS would draw the text using a bitmapped graphics mode.

like image 177
Ross Ridge Avatar answered Mar 04 '23 09:03

Ross Ridge