;***************************************
;*   VRrate by Tom Marshall - 08/18/94
;*    Released into the public domain
;***************************************
;* Calculates the frame rate (refresh
;* rate) of the specified video mode.
;* Executes in one refresh period.
;***************************************
                MODEL   TINY

VIDMODE         EQU     12h                     ;Video mode to test

                CODESEG
                ORG     0100h

Start:          mov     al,VIDMODE              ;Set video mode via BIOS
                mov     ah,0
                int     10h

                cli
                call    SyncVR                  ;Wait til start of VR
                mov     al,36h                  ;Reset 8253 counter
                out     43h,al
                xor     al,al
                out     40h,al
                out     40h,al
                call    SyncVR                  ;Wait for start of next VR

                mov     al,00h                  ;Read latch counter
                out     43h,al
                in      al,40h
                mov     ah,al
                in      al,40h
                xchg    al,ah
                neg     ax                      ;Cvt countdown => elapsed
                shr     ax,1                    ;Divide (why?)
                sti

                mov     bx,ax                   ;Calc frame rate
                mov     dx,0012h                ;Calc FPS = 1193180/Count
                mov     ax,34DCh
                shr     bx,1                    ;Get 2*FPS = DX:AX/(BX\2) so
                div     bx                      ;  we can round it
                shr     ax,1                    ;2*FPS => FPS and round
                adc     ax,0

                mov     si,OFFSET NumBuf
                call    Hex2ASCII

                mov     ax,0003h                ;Set 80x25 color text
                int     10h

                mov     dx,OFFSET Info1$        ;Tell 'em what you know
                call    PrintString
                mov     dx,OFFSET NumBuf
                call    PrintString
                mov     dx,OFFSET Info2$
                call    PrintString

                mov     ax,4C00h
                int     21h

;***************************************
;* SyncVR - Wait for start of VR
;* Entry: None
;* Exit : None
;* Regs : None
;***************************************
SyncVR          PROC
                push    ax dx

                mov     dx,03DAh                ;b3=1=VR
@@Loop1:        in      al,dx
        test    al,8
                jnz     @@Loop1
@@Loop2:        in      al,dx
        test    al,8
                jz      @@Loop2

                pop     dx ax
                ret
SyncVR          ENDP

;***************************************
;* Convert word to ASCII
;* Entry: AX = Word
;*        SI = Buffer
;* Exit : SI points to null terminator
;* Regs : BX, CX, DX destroyed
;***************************************
Hex2ASCII       PROC
                mov     bx,10                   ;Init divisor
                xor     cx,cx                   ;Init counter

DivLoop:        xor     dx,dx                   ;Prepare for divide
                div     bx                      ; DX:AX / 10 => AX r DX
                push    dx                      ;Save digit on stack
                inc     cx                      ;Bump counter
                or      ax,ax
                jnz     DivLoop

OutLoop:        pop     ax                      ;Get digit
                add     al,'0'                  ;Convert to ASCII
                mov     [si],al                 ;Store in buffer
                inc     si
                loop    OutLoop

                mov     BYTE PTR [si],0         ;Null terminator
                ret
Hex2ASCII       ENDP

;***************************************
;* Print ASCIIZ string to STDOUT
;* Entry: DS:DX = Address of string
;* Exit : CF, AX as set by 21/40
;* Regs : All general regs destroyed
;*        except DX
;***************************************
PrintString     PROC
                push    dx
                push    es

                push    ds                      ;Setup ES:DI
                pop     es
                mov     di,dx
                mov     cx,0FFFFh               ;Find length of string
                xor     al,al
                cld
                repne scasb
                neg     cx
                sub     cx,2
                mov     bx,1                    ;Write string to STDOUT
                mov     ah,40h
                int     21h

                pop     es
                pop     dx
                ret
PrintString     ENDP

Info1$          DB      13,10,13,10,'Frame rate is about ',0
Info2$          DB      ' per second.',13,10,0
NumBuf          DB      6 dup (?)

                END     Start

