Mail Archives: djgpp/1997/04/26/02:21:54
Date: | Sat, 26 Apr 1997 02:17:28 -0400
|
Message-Id: | <199704260617.CAA09891@delorie.com>
|
Newsgroups: | comp.os.msdos.djgpp
|
Subject: | Reeealy stumped with timer handler!
|
From: | cgouldie AT pop3 DOT wt DOT net
|
To: | djgpp AT delorie DOT com
|
DJ-Gateway: | from newsgroup comp.os.msdos.djgpp
|
NNTP-Posting-Host: 206.139.152.228
Message-ID: <33616746 DOT 0 AT news1 DOT wt DOT net>
Date: 26 Apr 97 02:24:06 GMT
Lines: 138
Path: news2.mv.net!mv!news.sprintlink.net!news-fw-22.sprintlink.net!www.nntp.primenet.com!nntp.primenet.com!ix.netcom.com!news-peer.sprintlink.net!news.sprintlink.net!sprint!cpk-news-hub1.bbnplanet.com!news.bbnplanet.com!uunet!in1.uu.net!205.230.159.11!news1.wt.net!206.139.152.228
I want to sync the timer interrupt with the vertical retrace, to avoid the
overhead of waiting for the retrace every time I want to blit the screen.
My solution is to make the timer interrupt just before each retrace, then I
will wait for the retrace, then if the screen is ready to blit, I will write
it out. However, I haven't gotten that far yet, because I have run into a big
snag.
The problem is that if I were to just blit out the screen during the timer
interrupt, this would throw off the timing, and I would end up waiting for
a retrace anyway! So I thought I could instead alter the stack so that it
would return to my own procedure, instead of the point of interruption. This
way, during my blit procedure, the timer could keep going. I could then just
pop the original flags at the end of my blit procedure, and everything should
work fine, right?
Well, easier said than done. I found that I had to call
dpmi_allocate_iret_wrapper () to wrap around my interrupt handler, or the
interrupt wouldn't happen at the correct frequency. Thus, altering the stack
became a much bigger chore. I had to look at the iret wrapper function to
find out the status of the stack before my procedure is called. I don't know
what in the heck the wrapper is doing, but one thing it seems to do is change
the stack selector and address, and push the old stack selector and address,
respectively, just before calling my procedure.
My handler works just fine if I don't mess with the stack.
Without further ado, here is the wrapper function (from fsdb), and my
handler. I have it set up to increment a tick counter. When the tick counter
reaches 2000 ticks, the wrapper function (theoretically) returns to the
function test_alt_ret, which (theoretically) returns to the point of
interruption.
;Written down by hand from fsdb. Reproduced exactly, minus the addresses,
;plus the function name and the label (downthere). Obviously I couldn't
;comment it much, as I did not write it.
wrapper_func proc near
push ds
push es
push fs
push gs
pusha ;48 bytes pushed onto stack? Assumed.
mov ax,247
mov ds,ax
inc [0x68008] ;I wonder what these addresses are?
cmp [0x68004],0
jnz downthere
mov [0x68004],1
mov es,ax
mov fs,ax
mov gs,ax
mov ebx,6fe00
cld
mov ecx,esp
mov dx,ss
mov ss,ax ;new stack address
mov esp,ebx
push edx ;pushing old stack address
push ecx
call _timerhandler ;now it calls my function
pop eax
pop ebx
mov ss,bx
mov esp,eax
mov [0x68004],0
downthere: popa
nop
pop gs
pop fs
pop es
pop ds
iret
wrapper_func endp
.386
.model flat
.code
extrn c ticks
public c timerhandler
;after 2000 ticks, the wrapper should return here.
test_alt_ret proc near
popfd
ret
test_alt_ret endp
;Here's my timer handler. I assumed (since I couldn't really tell from any
;documentation) that 8 bytes are pushed onto the stack before entry into
;the wrapper function (flags, cs, ip). I believe that I also tried it as 12
;bytes.
timerhandler proc near
pushad
cli
inc ticks
cmp ticks, 2000
;If I change jne to jmp, this procedure works just fine. Else: exit code 0xff.
jne nottime
mov eax, [esp+4] ;this should be the old stack address
mov ebx, [esp+8] ;should be old stack selector
mov ebp, esp ;save current stack selector & address
mov dx, ss
mov ss, bx ;change selector and address to old value
mov esp, eax
mov esi, esp
;Next 5 lines add 8 bytes to stack for old return address & flags
sub esp, 8
mov edi, esp
mov ecx, 64
cld
rep movsd
mov ebx, [esp+48] ;save return address
mov [esp+56], ebx
xor ebx,ebx
mov bx, [esp+54] ;save old flags
mov [esp+60], ebx
lea ecx, test_alt_ret ;make wrapper return to my func
mov [esp+48], ecx
mov ss,dx ;restore stack
mov esp,ebp
nottime: mov al, 20h ;acknowledge interrupt
out 20h, al
sti
popad
ret
timerhandler endp
end
Net-Tamer V 1.08 - Test Drive
- Raw text -