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 Precedence: bulk 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