Link to home
Start Free TrialLog in
Avatar of idek1
idek1

asked on

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?
Avatar of Levin
Levin

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(0x3d4,0xd);
outp(0x3d5,offset&0x00ff);          /*Set offset low byte */

I hope this helps, otherwise you're welcome to mail me.
/Johan <johan@technologist.com>
ASKER CERTIFIED SOLUTION
Avatar of Levin
Levin

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of idek1

ASKER

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:
                        offset=page*2000;
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?

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.)

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

/Johan
Avatar of idek1

ASKER

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.
mailto:johan@technologist.com

/Johan
Avatar of idek1

ASKER

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.