1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
/* Misc FM chip soundcard routines for sccw */
/* Must compile with -O2 -lm and optionally -DDEBUG_FREQ */
/* Steven J. Merrifield VK3ESM sjm@ee.latrobe.edu.au */
/* Modified by Richard Everitt, G4ZFE (richard@babbage.demon.co.uk */
/* to allow for multiple voices. */
#include <unistd.h>
#include <asm/io.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include "pileup.h"
void wr_register(int index, int data) /* See the PC Game Programmers Encyclopedia */
{
int i,temp;
outb(index,reg_port);
for (i=1;i<7;i++)
temp = inb(reg_port);
outb(data,data_port);
for (i=1;i<36;i++)
temp = inb(reg_port);
}
int AdLib_found(void) /* See the PC Game Programmers Encyclopedia */
{
long temp1,temp2;
wr_register(4,0x60);
wr_register(4,0x80);
temp1 = inb(reg_port);
wr_register(2,0xFF);
wr_register(4,0x21);
sleep(1);
temp2 = inb(reg_port);
wr_register(4,0x60);
wr_register(4,0x80);
if (((temp1 && 0xE0) == 0) && ((temp2 && 0xE0) == 0xC0))
{
return(TRUE);
}
else return(FALSE);
}
void Reset_AdLib(void) /* Set all registers to 0 */
{
int i;
for (i=1;i<245;i++)
wr_register(i,0);
}
void Cleanup ()
{
int voice;
int reg_num;
/* Turn all voices off */
for (voice=0; voice<10; voice++)
{
reg_num =0xB0 + voice % 11;
wr_register (reg_num, 0);
}
}
void Play_sound(int voice,int f, double delay, int vol)
{
int blk = -1;
int f_num;
int A0_reg,B0_reg,B0_reg10,B0_reg432;
int reg_num;
int cell_offset;
reg_num = voice;
reg_num %= 11;
cell_offset = reg_num % 3 + ((reg_num /3) << 3);
wr_register(0x20+cell_offset,1);/* Play sound at fundamental freq. */
wr_register(0x23+cell_offset,1);/* Carrier at specified freq. */
wr_register(0x40+cell_offset,64-vol); /* Volume */
wr_register(0x43+cell_offset,64-vol); /* Volume */
wr_register(0x60+cell_offset,0xF0); /* Carrier attack = fast, decay = slow */
wr_register(0x63+cell_offset,0xF0); /* Carrier attack = fast, decay = slow */
wr_register(0x80+cell_offset,0xFF); /* Carrier sustain = soft, release = fast */
wr_register(0x83+cell_offset,0xFF); /* Carrier sustain = soft, release = fast */
/* Would you belive it took three days to work out how to do this ? */
do
{
blk++;
f_num = (int)(((float)f / 50000.0) / (1/(pow(2,abs(blk-20)))));
} while (f_num > 1023);
A0_reg = f_num & 0x00FF;
B0_reg10 = (f_num & 0x0300) >> 8;
B0_reg432 = (blk << 2) & 0x00FF; /* Do I really need to & 0x00ff ?? */
B0_reg = (32 | B0_reg432 | B0_reg10) & 0x00FF;
reg_num = 0xA0 + voice % 11;
wr_register(reg_num,A0_reg);
reg_num = 0xB0 + voice % 11;
wr_register(reg_num,B0_reg);
#ifdef DEBUG_FREQ
printf("blk = %d f_num = %d\n",blk,f_num);
printf("B0_reg432 = %2x\n",B0_reg432); /* bits 4 3 2 */
printf("B0_reg10 = %2x\n",B0_reg10); /* bits 1 0 */
printf("B0_reg = %2x A0_reg = %2x\n\n\n",B0_reg,A0_reg);
#endif
usleep(delay);
reg_num = 0xB0 + voice % 11;
wr_register(reg_num,0x11);
}
|