/* ex2.c - example #2 */

#include <stdio.h>
#include <conio.h>
#include "modplay.h"

#ifdef __BORLANDC__

void waitvr(void)
{
    asm  mov  dx,0x3da
l0: asm  in   al,dx
    asm  test al,8
    asm  jne  l0
l1: asm  in   al,dx
    asm  test al,8
    asm  je   l1
l2: asm  in   al,dx
    asm  test al,1
    asm  jne  l2
}

void setborder(char n)
{
    asm  mov  dx,0x3c0
    asm  mov  al,0x31
    asm  out  dx,al
    asm  mov  al,[n]
    asm  out  dx,al
}

void starttimer(void)
{
    asm  in   al,0x61
    asm  or   al,0x01
    asm  out  0x61,al
    asm  mov  al,0xb4
    asm  out  0x43,al
    asm  mov  al,0xff
    asm  out  0x42,al
    asm  out  0x42,al
}

unsigned short readtimer(void)
{
    asm  mov  al,0xb0
    asm  out  0x43,al
    asm  in   al,0x42
    asm  mov  ah,al
    asm  in   al,0x42
    asm  xchg al,ah
    asm  neg  ax
    return _AX;
}

#else

#pragma aux waitvr =    " mov  dx,3dah "\
                        "L0:           "\
                        " in   al,dx   "\
                        " test al,8    "\
                        " jne  L0      "\
                        "L1:           "\
                        " in   al,dx   "\
                        " test al,8    "\
                        " je   L1      "\
                        "L2:           "\
                        " in   al,dx   "\
                        " test al,1    "\
                        " jne  L2      " parm caller [] modify [ax dx];

#pragma aux setborder = " mov  dx,3c0h "\
                        " mov  al,31h  "\
                        " out  dx,al   "\
                        " mov  al,ah   "\
                        " out  dx,al   " parm caller [ah] modify [ax dx];

#pragma aux starttimer= " in   al,61h  "\
                        " or   al,01h  "\
                        " out  61h,al  "\
                        " mov  al,0b4h "\
                        " out  43h,al  "\
                        " mov  al,0ffh "\
                        " out  42h,al  "\
                        " out  42h,al  " parm caller [] modify [ax];

#pragma aux readtimer = " mov  al,0b0h "\
                        " out  43h,al  "\
                        " in   al,42h  "\
                        " mov  ah,al   "\
                        " in   al,42h  "\
                        " xchg al,ah   "\
                        " neg  ax      " parm caller [] modify [ax];

void waitvr(void);
void setborder(char n);
void starttimer(void);
unsigned short readtimer(void);

#endif

void main(void)
{
    Module *Song;
    word Port;
    byte IRQ,DRQ;
    unsigned long counter,frames;
    unsigned short ticks;

    if (MODDetectCard(&Port,&IRQ,&DRQ)) {
        printf("Sound Blaster not found.\n");
        return;
    }
    printf("Sound Blaster found at Addr:%03x IRQ:%d DMA:%d\n",Port,IRQ,DRQ);
    if ((Song = MODLoadModule("TUNE.MOD")) != NULL) {
        if (MODPlayModule(Song,8,22222,Port,IRQ,DRQ,PM_MANUAL))
            printf("Error initializing the sound system.\n");
        else {
            printf("Press any key to stop ...\n");
            for (frames = counter = 0; !kbhit(); frames++) {
                waitvr();
                setborder(1);
                starttimer();
                MODPoll();
                ticks = readtimer();
                setborder(0);
                counter += (unsigned long)ticks;
                printf("%5u ticks\r", ticks);
            }
            MODStopModule();
            if (frames) {
                printf("%10lu frames\n%10lu ticks per frame (average)\n",
                        frames, counter/frames);
                printf("%4.5f microseconds per frame (average)\n",
                    (((float)counter/(float)frames) / 1193182.0) * 1000000.0);
                printf("\nNOTE: In my 386DX-40 i got 1150us per frame for the 8 channels module.\n");
            }
        }
        MODFreeModule(Song);
    }
    else {
        printf("Error loading modulefile.\n");
    }
    return;
}
