• C

DOS TSR: How to set active video page?

I am writing a DOS TSR program that writes to video page 1 of the video memory. The problem is that upon certain conditions the TSR should switch the current video page (normally 0) to the video page that the TSR has been writing screen data to (in this case video page 1).
Normally to switch video pages I would invoke BIOS interrupt 0x10, Function 5 (AH), and video page number in AL.
However, calling the video interrupt always corrupts the screen when invoked from an interrupt handler routine.
Thus, I am forced to look for ways to change the active video page without using the BIOS functions.
Can anyone suggest a way of achieving this from an Interrupt Service Routine?
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

I believe that in txt-mode multiple pages are achieved by putting the pages after eachother. That is, page 0 stars at offset 0 and ends at offset 3999 (80x25 mode), page 1 starts at 4000 ...

When the page is changed with an interrupt the start-offset of the videocard is changed. The start-offset is the the offset in memory that holds the pixel/character in the upper left corner.

I haven't actually tried this in text-mode, but since it worx fine in graphics (booth chained and unchained) I don't see why it wouldn't work here.

The start-offset register resides at register 0x3d4 index 0xc (high byte) and 0xd (low byte).

Here is a short code-sample that demonstrates the technique:

unsinged int offset;
offset=page*4000;                   /* Assuming 80x25 mode */
outpw(0x3d4, offset&0xff00 | 0xc);  /* Set offset high byte */
outp(0x3d5,offset&0x00ff);          /*Set offset low byte */

I hope this helps, otherwise you're welcome to mail me.
/Johan <johan@technologist.com>
Hey, that should be an answer!


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
idek1Author Commented:
Yes that was the solution I was looking for.
Note though, that the offset is measured in words, not bytes, and so therefore offset line should read:
Otherwise I kept switching to the video page after the one I was actually writing to (Page 2 instead of 1).

Thanks For your help. Also, just out of interests sake, would you know the reason why calling ROM-BIOS interrupts during an ISR stuffs the computer up?

Powerful Yet Easy-to-Use Network Monitoring

Identify excessive bandwidth utilization or unexpected application traffic with SolarWinds Bandwidth Analyzer Pack.

Re page*2000:
OK, I didn't know. I've mainly been coding for 320x240x256 unchained. That mode uses bytemode. (There are byte, word and dword modes.)

Re: BIOS in ISRs.
I don't know a general answer, no. DOS' function are known to mess up TSRs, but I don't think I've had any trouble with BIOS functions.

If e.g. youre code is invoked from within int 10h you can not call the same int 10h functions again.
(And to be on the safe side, don't call any int 10h function from there.)

How is your isr invoked? Is it a hardware IRQ or software int? And what interrupt(s) are you hooking?

idek1Author Commented:
Well, my ISR is hooked on timer interrupt 0x1C,
and whevever I attempt to execute say interrupt 0x10, from within this ISR, the screen is totally mangled, producing different results each time the interupt is executed.

I was aware that certain DOS functions were not allowed during ISRs, however, I didn't hear about BIOS interrupts being disallowed also.

Int 0x1c can be invoked at any time, whenever the PIT-vhip feels like signalling an irq 0.
This can very well happend when execution is inside a int 10h. If int 10h is called recursively there is a fairly big chance it'll hang the computer or at least produce unexpected output.

This occurs e.g. because the static variables that int 10h functions use contain temporary values while int 10h is executing and not the values thet the new instance expects.

To work around this you can chain interrupt 10h.
When a int 10h is called you set a flag in memory that indicates that int 10h is beeing executed.

Your ISR then checks for this flag and acts acordingly. If no int 10h is in progress you just go ahead and call your real function. Otherwise you set an other flag in memory.

Your int 10h routine does in turn check for this second flag when exiting. If it's set then it calls your function.

I'm sure that this is the simplies way to solve the problem (or if it at all will solve it), but it's the best I can think of.

You're welcome to send me a mail and tell me your results.

idek1Author Commented:
Thanks Johan,

This sounds the right way to go about this problem, and I recall reading something like this ages ago, but couldn't remember exactly how it works. In any case, the immediate problem was solved by writing directly to video ports to switch video pages.
Once again, thank you for your answer.

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.