home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 11 / CD_ASCQ_11_0294.iso / maj / 666 / xvsync.asm < prev    next >
Assembly Source File  |  1993-10-07  |  8KB  |  312 lines

  1. ; MODULE XVSYNC
  2. ; Xlib comptible vsync handler
  3. ; Written by Tore Bastiansen
  4. ; based on REND386 by Dave Stampe and Bernie Roehl
  5.  
  6. include xlib.inc
  7. include xmain.inc
  8. include xvsync.inc
  9.  
  10.  
  11. TIMER_VECT                      equ 08h
  12.  
  13. PIC_CMD                         equ 20h
  14. NONSPEC_EOI                     equ 20h
  15. TIMER_MODE                      equ 34h
  16. TIMER_CONTROL                   equ 43h
  17. TIMER_0                         equ 40h
  18.  
  19. LATCH_COUNT                     equ 00h
  20.  
  21. INT_IN_ADVANCE                  equ 100
  22.  
  23. DOS_GETVECT                     equ 3500h
  24. DOS_SETVECT                     equ 2500h
  25.  
  26.  
  27. .data
  28. _TicksPerSecond         dw 0
  29. _VsyncIntTicks          label dword
  30. VsyncIntTicksLo         dw 0
  31. VsyncIntTicksHi         dw 0
  32. _VsyncPeriod            dw 0             ;Time (in clicks) between each vsync
  33.                                      ;1 click = 1.193 microseconds
  34.  
  35. ClockRate               dw 0             ;Clock rate (in clicks) for timer 0
  36. ClockCounter            dw 0             ;Counts total clicks modulo 65536
  37. UserVsyncHandler        label dword      ;Pointer to user routine called
  38. UserVsyncOffs           dw 0             ;called once each vsync period.
  39. UserVsyncSeg            dw 0
  40. InUserHandler           dw 0
  41.             db 100h dup(?)
  42. LocalStack              label byte       ;Local stack for user handler
  43. StackSeg                dw 0
  44. StackPtr                dw 0
  45.  
  46.  
  47. ElapsedVrts            dw 0
  48. VrtsToSkip             dw 1
  49.  
  50. .code
  51. get_vsync_period proc near
  52.     mov    al,TIMER_MODE            ;Start timer
  53.     out    TIMER_CONTROL,al
  54.     mov    al,0
  55.     out    TIMER_0,al
  56.     out    TIMER_0,al
  57.  
  58.     WaitVsyncStart
  59.  
  60.     mov    al,LATCH_COUNT
  61.     out    TIMER_CONTROL,al
  62.     in     al,TIMER_0
  63.     mov    cl,al
  64.     in     al,TIMER_0
  65.     mov    ch,al                    ;cx=65536-clicks
  66.  
  67.     WaitVsyncStart
  68.  
  69.     mov    al,LATCH_COUNT
  70.     out    TIMER_CONTROL,al
  71.     in     al,TIMER_0
  72.     mov    dl,al
  73.     in     al,TIMER_0
  74.     mov    dh,al                    ;dx=65536-clicks
  75.  
  76.     sub    cx,dx                    ;cx=clicks between two vsyncs
  77.     mov    ax,cx                    ;return in ax
  78.     ret
  79. get_vsync_period endp
  80.  
  81. vsync_int proc far
  82.     pusha                            ;Save regs
  83.     push   ds
  84.     push   es
  85.  
  86.     mov    ax,@data                 ;Set the right datasegment
  87.     mov    ds,ax
  88.     add    [VsyncIntTicksLo],1      ;Increment _VsyncIntTicks
  89.     adc    [VsyncIntTicksHi],0
  90.  
  91.         inc    [ElapsedVrts]
  92.         mov    cx,[ElapsedVrts]
  93.         cmp    cx,[VrtsToSkip]
  94.         jl     @@StopClock
  95.  
  96.     cmp    [_StartAddressFlag],1    ;Change in start address
  97.     jne    @@StopClock
  98.  
  99.     mov    dx,CRTC_INDEX            ;Yes, set start address
  100.     mov    ax,[_WaitingStartLow]
  101.     mov    bx,[_WaitingStartHigh]
  102.     out    dx,ax
  103.     mov    ax,bx
  104.     out    dx,ax
  105.  
  106. @@StopClock:
  107.     cli
  108.     mov    al,TIMER_MODE            ;Stop the timer
  109.     out    TIMER_CONTROL,al         ;Dont want any interrupts
  110.     mov    al,255
  111.     out    TIMER_0,al
  112.     out    TIMER_0,al
  113.     sti
  114.  
  115.     cli
  116.     mov    dx,INPUT_STATUS_0                   ;Wait for vsync
  117. @@WaitVS:
  118.     in     al,dx
  119.     test   al,08h
  120.     jz     @@WaitVS
  121.  
  122.     mov    al,TIMER_MODE            ;Start timer again
  123.     out    TIMER_CONTROL,al
  124.     mov    ax,[ClockRate]
  125.     out    TIMER_0,al
  126.     mov    al,ah
  127.     out    TIMER_0,al
  128.  
  129.         cmp    cx,[VrtsToSkip]
  130.         jl     @@PaletteInt
  131.  
  132.     cmp    [_StartAddressFlag],1    ;Any change in start address ?
  133.     jne    @@PaletteInt
  134.  
  135.         xor    cx,cx
  136.         mov    [ElapsedVrts],cx
  137.  
  138.     mov    ax,[_WaitingPelPan]      ;Yes, set pel pan register
  139.     mov    dx,AC_INDEX
  140.     out    dx,al
  141.     mov    al,ah
  142.     out    dx,al
  143.     mov    [_StartAddressFlag],0
  144.  
  145. @@PaletteInt:
  146.     cmp    [_VsyncPaletteCount],0   ;Any changes in the palette
  147.     je     @@MouseInt
  148.     mov    si, offset _VsyncPaletteBuffer  ;Yes
  149.     mov    cx, [_VsyncPaletteCount]
  150.     mov    ax, [_VsyncPaletteStart]
  151.     mov    dx, DAC_WRITE_INDEX
  152.     out    dx, al
  153.     mov    dx, DAC_DATA
  154.  
  155. @@DacOutLoop:
  156.     outsb
  157.     outsb
  158.     outsb
  159.     loop    @@DacOutLoop
  160.     mov     [_VsyncPaletteCount],0
  161.  
  162. @@MouseInt:
  163.     cmp    [_MouseRefreshFlag],1             ; Does the mouse need refresh
  164.     jne    @@UserInt
  165.     call   dword ptr [_MouseVsyncHandler]    ; Yes
  166.                                               ;(this is not yet implemented)
  167.  
  168. @@UserInt:
  169.     cmp    [UserVsyncSeg], 0       ;Is the a user interrupt routine?
  170.     je     short @@Sim182
  171.     cmp    [InUserHandler],0       ;Yes, but is it already active?
  172.     jne    short @@Sim182
  173.     mov    [InUserHandler],1       ;No, mark it as active
  174.     mov    [StackSeg],ss           ;make a local stack
  175.     mov    [StackPtr],sp
  176.     push    ds
  177.     pop     ss
  178.     mov     sp, offset LocalStack
  179.     sti
  180.     call    dword ptr [UserVsyncHandler]
  181.     cli
  182.     mov     sp, [StackPtr]          ;Restore old stack
  183.     mov     ss, [StackSeg]
  184.     mov     [InUserHandler],0       ;Mark as not active
  185.  
  186. ;       SIM 18.2 Hz
  187. @@Sim182:
  188.     mov     ax,[_VsyncPeriod]       ;Count number of clicks
  189.     add     [ClockCounter],ax       ;If it is bigger than 65536
  190.     jnc     short @@DontChainOld
  191.     pop     es                      ;more than 1/18.2 secs has gone
  192.     pop     ds
  193.     popa
  194.     sti
  195.     db     0eah                    ; jmp instruction
  196.     OldTimerInt    dd 0            ; Pointer to old int8 routine
  197.                        ;  Selfmodyfiing code
  198.     ;jmp    dword ptr [OldTimerInt] Chain to old
  199. @@DontChainOld:
  200.  
  201. ; CLEAN UP AND RETURN
  202.     mov    al,NONSPEC_EOI
  203.     out    PIC_CMD,al
  204.  
  205.  
  206.     pop    es
  207.     pop    ds
  208.     popa
  209.     sti
  210.     iret
  211. vsync_int endp
  212.  
  213.  
  214. _x_install_vsync_handler proc
  215. ARG VrtSkipCount:word
  216.         push    bp
  217.         mov     bp,sp
  218.         mov     ax,[VrtSkipCount]
  219.         or      ax,ax
  220.         jnz     @@NonZeroCount
  221.         mov     ax,1
  222. @@NonZeroCount:
  223.         mov     [VrtsToSkip],ax
  224.         mov     [ElapsedVrts],0
  225.     cmp     [_VsyncHandlerActive],TRUE      ;Is it already active
  226.     je      short @@Return
  227.     call    get_vsync_period                ;no, get the vsync period
  228.  
  229.     mov     [_VsyncPeriod],ax
  230.     sub     ax,INT_IN_ADVANCE               ;We need a little extra
  231.     mov     [ClockRate],ax                  ;time
  232.  
  233.     mov     dx,18                           ;dx:ax=1193000
  234.     mov     ax,13352
  235.     idiv    [_VsyncPeriod]
  236.     mov     [_TicksPerSecond],ax            ;1193/_VsyncPeriod
  237.  
  238.     mov     word ptr [_VsyncIntTicks],0
  239.     mov     word ptr [_VsyncIntTicks+2],0
  240.  
  241.     cli
  242.     mov     ax, DOS_GETVECT+TIMER_VECT      ;Get address of old timer int
  243.     int     21h
  244.     mov     ax,es
  245.     mov     word ptr cs:[OldTimerInt],bx       ;Store in OldTimerInt
  246.     mov     word ptr cs:[OldTimerInt+2],ax
  247.  
  248.     mov     [_VsyncHandlerActive],TRUE      ;Mark handler as active
  249.     mov     ax,DOS_SETVECT+TIMER_VECT       ;Set the new timer int
  250.     push    ds
  251.     mov     dx,seg vsync_int
  252.     mov     ds,dx
  253.     mov     dx,offset vsync_int
  254.     int     21h
  255.     pop     ds
  256.  
  257.     mov     al,TIMER_MODE                   ;Reprogram timer 0
  258.     out     TIMER_CONTROL,al
  259.     mov     ax,ClockRate
  260.     out     TIMER_0,al
  261.     mov     al,ah
  262.     out     TIMER_0,al
  263.     sti
  264. @@Return:
  265.         pop     bp
  266.     ret
  267. _x_install_vsync_handler endp
  268.  
  269. _x_remove_vsync_handler proc
  270.     cmp     [_VsyncHandlerActive],FALSE
  271.     je      short @@Return
  272.     mov     dx, word ptr cs:[OldTimerInt]
  273.     mov     ax, word ptr cs:[OldTimerInt+2]
  274.     push    ds
  275.     mov     ds,ax
  276.     mov     ax,DOS_SETVECT+TIMER_VECT       ;Restore the old timer int
  277.     cli
  278.     int     21h
  279.     pop     ds
  280.     mov     al,TIMER_MODE                   ;Restore timer 0
  281.     out     TIMER_CONTROL,al
  282.     mov     al,0
  283.     out     TIMER_0,al
  284.     out     TIMER_0,al
  285.     sti
  286. @@Return:
  287.     ret
  288. _x_remove_vsync_handler endp
  289.  
  290.  
  291. ; WARNING:  The user vsync handler cannot use the 386 specific registers
  292. ;           (EAX,EBX,ECX,EDX,ESI,EDI,ESP,EBP,FS,GS)
  293. ;                       whithout saving them first.
  294. ;                       It must not do any drawing.
  295. ;                       Only 256 butes of stack is provided.
  296.  
  297. _x_set_user_vsync_handler proc
  298. ARG handler_proc:dword
  299.     push    bp
  300.     mov     bp,sp
  301.     mov     ax, word ptr [handler_proc]
  302.     mov     dx, word ptr [handler_proc+2]
  303.     cli
  304.     mov     word ptr [UserVsyncHandler],ax
  305.     mov     word ptr [UserVsyncHandler+2],dx
  306.     sti
  307.     pop     bp
  308.     ret
  309. _x_set_user_vsync_handler endp
  310.  
  311. end
  312.