home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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" );
- }
-