File: AdLib.c

package info (click to toggle)
pileup 1.1-3
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 264 kB
  • ctags: 113
  • sloc: ansic: 704; makefile: 50
file content (124 lines) | stat: -rwxr-xr-x 2,995 bytes parent folder | download | duplicates (4)
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);		
}