home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mega CD-ROM 1
/
megacd_rom_1.zip
/
megacd_rom_1
/
MUSIC
/
POLYTC.ZIP
/
POLY_PLA.C
< prev
next >
Wrap
C/C++ Source or Header
|
1987-12-31
|
5KB
|
171 lines
/*
* poly_play - Play a polyphonic tune.
*/
#include <stdio.h>
#define TRUE (1)
#define FALSE (0)
int tune[5000];
char name[80];
FILE *tfp;
int *tunep;
int tempo;
int duration;
main( argc, argv )
int argc;
char *argv[];
{
int tindex;
if( argc != 2 )
{
tfprintf( stderr, "\nUsage: poly_play tunefile\n\n");
exit( 1 );
}
if( !(tfp = fopen(argv[1], "r")) )
{
tfprintf( stderr, "\n*** Unable to open tune file ***\n" );
exit( 2 );
}
fgets( name, 80, tfp );
tindex = 0;
while( tfscanf(tfp, "%d", &tune[tindex++]) != -1)
;
fclose( tfp );
tunep = tune; /* Initialize tune pointer */
tempo = 0x1fff; /* Set up default tempo */
/*
* Now attempt to play the tune...
*/
asm( "push ax" ); /* Save registers */
asm( "push bx" );
asm( "push cx" );
asm( "push dx" );
asm( "push si" );
asm( "push di" );
asm( "push bp" );
asm( "push es" );
asm( "push <tempo>" ); /* Initialize tempo counter */
asm( "xor ax,ax" ); /* Must write 0 into voice count and */
asm( "mov bx,ax" ); /* data registers */
asm( "mov dx,ax" );
asm( "mov si,ax" );
asm( "mov bp,ax" );
asm( "mov di,ax" );
asm( "mov es,ax" );
asm( "mov cx,#12h" ); /* Initialize shift value */
/*
* This section sorts the tune data into the appropriate registers
* Voice period data is stored in ES for voice 1, DI for voice 2,
* and SI for voice 3. The voice period count is stored in BX for
* voice 1, DX for voice 2, and BP for voice 3.
*/
asm( "sort:" );
asm( "push bx" );
asm( "push dx" );
asm( "sort_1:" );
asm( "add <tunep>,#2" );
asm( "mov bx,<tunep>" ); /* Get tune pointer */
asm( "mov ax,[bx]" ); /* Get tune data in AX */
asm( "mov dx,ax" ); /* Make a copy in DX */
asm( "and dx,#1FFFh" ); /* Strip off 3 data type bits */
asm( "shl ax" ); /* Move msb into carry bit */
asm( "jnc sort_4" ); /* Jump if end, duration, or tempo data */
asm( "shl ax" ); /* Move 2nd msb into carry bit */
asm( "jc sort_3" ); /* Jump if voice 3 data */
asm( "shl ax" ); /* Move 3rd msb into carry bit */
asm( "jc sort_2" ); /* Jump if voice 2 data */
asm( "mov es,dx" ); /* Store voice 1 data in ES */
asm( "jmp sort_1" );
asm( "sort_2:" );
asm( "mov di,dx" ); /* Store voice 2 data in DI */
asm( "jmp sort_1" );
asm( "sort_3:" );
asm( "mov si,dx" ); /* Store voice 3 data in SI */
asm( "jmp sort_1" ); /* Ignore */
asm( "sort_4:" );
asm( "shl ax" ); /* Move 2nd msb into carry bit */
asm( "jnc sort_6" ); /* Jump if end or duration data */
asm( "shl ax" );
asm( "jnc sort_5" ); /* Jump if tempo data */
asm( "jmp sort_1" ); /* Ignore */
asm( "sort_5:" );
asm( "mov <tempo>,dx" ); /* Store tempo */
asm( "pop dx" ); /* Restore registers */
asm( "pop bx" );
asm( "pop ax" ); /* Burn the current tempo counter */
asm( "push <tempo>" ); /* and put in the new one */
asm( "push bx" ); /* Save registers again */
asm( "push dx" );
asm( "jmp sort_1" );
asm( "sort_6:" );
asm( "shl ax" ); /* Move 3rd msb into carry */
asm( "jc sort_7" ); /* Jump if duration */
asm( "pop dx" );
asm( "pop bx" );
asm( "pop ax" ); /* Get rid or tempo counter */
asm( "jmp theend" );
asm( "sort_7:" );
asm( "mov <duration>,dx" ); /* Store duration data */
asm( "pop dx" );
asm( "pop bx" );
asm( "theloop:" );
asm( "cli" ); /* Turn off interrupts during note */
asm( "pop ax" ); /* Get tempo counter */
asm( "dec ax" ); /* Decrement it */
asm( "push ax" ); /* Put it back */
asm( "jnz play" ); /* Jump if some tempo remains */
asm( "pop ax" ); /* Get tempo counter */
asm( "mov ax,<tempo>" ); /* Reset tempo counter */
asm( "push ax" ); /* and put it back */
asm( "dec <duration>" ); /* Decrement duration counter */
asm( "jnz play" ); /* Continue if not finished */
asm( "sti" ); /* Turn interrupts back on */
asm( "jmp sort" ); /* Get new tune data if duration up */
/*
* This routine plays the notes until the duration counter
* reaches zero. At that time, the new data is sorted.
*/
asm( "play:" );
asm( "add bx,si" ); /* Add voice 3 data to count */
asm( "rol bx" ); /* Get msb of voice 3 count */
asm( "mov ax,cx" ); /* Keeps keyboard clk on and */
asm( "rcl al" ); /* casette motor relay off */
asm( "rcl al" );
asm( "b out 061h" );
asm( "ror bx" ); /* Restore bx to original state */
asm( "add dx,di" ); /* Add voice 2 data to count */
asm( "rol dx" );
asm( "mov ax,cx" );
asm( "rcl al" );
asm( "rcl al" );
asm( "b out 061h" );
asm( "ror dx" );
asm( "mov ax,es" );
asm( "add bp,ax" ); /* Add voice 1 data to count */
asm( "rol bp" );
asm( "mov ax,cx" );
asm( "rcl al" );
asm( "rcl al" );
asm( "b out 061h" );
asm( "ror bp" );
asm( "jmp theloop" );
asm( "theend:" );
asm( "pop es" ); /* Restore registers */
asm( "pop bp" );
asm( "pop di" );
asm( "pop si" );
asm( "pop dx" );
asm( "pop cx" );
asm( "pop bx" );
asm( "pop ax" );
}