1 /***************************************************************************
2 polepos.c
3 Sound handler
4 ****************************************************************************/
5 #include "driver.h"
6
7 static int sample_msb = 0;
8 static int sample_lsb = 0;
9 static int sample_enable = 0;
10
11 static int current_position;
12 static int sound_stream;
13
14 /* speech section */
15 static int channel;
16 static INT8 *speech;
17 /* macro to convert 4-bit unsigned samples to 8-bit signed samples */
18 #define SAMPLE_CONV4(a) (0x11*((a&0x0f))-0x80)
19 #define SAMPLE_SIZE 0x8000
20
21 #define AMP(r) (r*128/10100)
22 static int volume_table[8] =
23 {
24 AMP(2200), AMP(3200), AMP(4400), AMP(5400),
25 AMP(6900), AMP(7900), AMP(9100), AMP(10100)
26 };
27 static int sample_offsets[5];
28
29 /************************************/
30 /* Stream updater */
31 /************************************/
engine_sound_update(int num,INT16 * buffer,int length)32 static void engine_sound_update(int num, INT16 *buffer, int length)
33 {
34 UINT32 current = current_position, step, clock, slot, volume;
35 UINT8 *base;
36
37
38 /* if we're not enabled, just fill with 0 */
39 if (!sample_enable || Machine->sample_rate == 0)
40 {
41 memset(buffer, 0, length * sizeof(INT16));
42 return;
43 }
44
45 /* determine the effective clock rate */
46 clock = (Machine->drv->cpu[0].cpu_clock / 64) * ((sample_msb + 1) * 64 + sample_lsb + 1) / (16*64);
47 step = (clock << 12) / Machine->sample_rate;
48
49 /* determine the volume */
50 slot = (sample_msb >> 3) & 7;
51 volume = volume_table[slot];
52 base = &memory_region(REGION_SOUND1)[0x1000 + slot * 0x800];
53
54 /* fill in the sample */
55 while (length--)
56 {
57 *buffer++ = (base[(current >> 12) & 0x7ff] * volume);
58 current += step;
59 }
60
61 current_position = current;
62 }
63
64 /************************************/
65 /* Sound handler start */
66 /************************************/
polepos_sh_start(const struct MachineSound * msound)67 int polepos_sh_start(const struct MachineSound *msound)
68 {
69 int i, bits, last=0;
70
71 channel = mixer_allocate_channel(25);
72 mixer_set_name(channel,"Speech");
73
74 speech = (INT8*)malloc(16*SAMPLE_SIZE);
75 if (!speech)
76 return 1;
77
78 /* decode the rom samples, interpolating to make it sound a little better */
79 for (i = 0;i < SAMPLE_SIZE;i++)
80 {
81 bits = memory_region(REGION_SOUND1)[0x5000+i] & 0x0f;
82 bits = SAMPLE_CONV4(bits);
83 speech[16*i+0] = (7 * last + 1 * bits) / 8;
84 speech[16*i+1] = (6 * last + 2 * bits) / 8;
85 speech[16*i+2] = (5 * last + 3 * bits) / 8;
86 speech[16*i+3] = (4 * last + 4 * bits) / 8;
87 speech[16*i+4] = (3 * last + 5 * bits) / 8;
88 speech[16*i+5] = (2 * last + 6 * bits) / 8;
89 speech[16*i+6] = (1 * last + 7 * bits) / 8;
90 speech[16*i+7] = bits;
91 last = bits;
92
93 bits = (memory_region(REGION_SOUND1)[0x5000+i] & 0xf0) >> 4;
94 bits = SAMPLE_CONV4(bits);
95 speech[16*i+8] = (7 * last + 1 * bits) / 8;
96 speech[16*i+9] = (6 * last + 2 * bits) / 8;
97 speech[16*i+10] = (5 * last + 3 * bits) / 8;
98 speech[16*i+11] = (4 * last + 4 * bits) / 8;
99 speech[16*i+12] = (3 * last + 5 * bits) / 8;
100 speech[16*i+13] = (2 * last + 6 * bits) / 8;
101 speech[16*i+14] = (1 * last + 7 * bits) / 8;
102 speech[16*i+15] = bits;
103 last = bits;
104 }
105
106 /* Japanese or US PROM? */
107 if (memory_region(REGION_SOUND1)[0x5000] == 0)
108 {
109 /* US */
110 sample_offsets[0] = 0x0020;
111 sample_offsets[1] = 0x0c00;
112 sample_offsets[2] = 0x1c00;
113 sample_offsets[3] = 0x2000;
114 sample_offsets[4] = 0x2000;
115 }
116 else
117 {
118 /* Japan */
119 sample_offsets[0] = 0x0020;
120 sample_offsets[1] = 0x0900;
121 sample_offsets[2] = 0x1f00;
122 sample_offsets[3] = 0x4000;
123 sample_offsets[4] = 0x6000; /* How is this triggered? */
124 }
125
126 sound_stream = stream_init("Engine Sound", 50, Machine->sample_rate, 0, engine_sound_update);
127 current_position = 0;
128 sample_msb = sample_lsb = 0;
129 sample_enable = 0;
130 return 0;
131 }
132
133 /************************************/
134 /* Sound handler stop */
135 /************************************/
polepos_sh_stop(void)136 void polepos_sh_stop(void)
137 {
138 if (speech)
139 free(speech);
140 speech = NULL;
141 }
142
143 /************************************/
144 /* Sound handler update */
145 /************************************/
polepos_sh_update(void)146 void polepos_sh_update(void)
147 {
148 }
149
150 /************************************/
151 /* Write LSB of engine sound */
152 /************************************/
WRITE_HANDLER(polepos_engine_sound_lsb_w)153 WRITE_HANDLER( polepos_engine_sound_lsb_w )
154 {
155 stream_update(sound_stream, 0);
156 sample_lsb = data & 62;
157 sample_enable = data & 1;
158 }
159
160 /************************************/
161 /* Write MSB of engine sound */
162 /************************************/
WRITE_HANDLER(polepos_engine_sound_msb_w)163 WRITE_HANDLER( polepos_engine_sound_msb_w )
164 {
165 stream_update(sound_stream, 0);
166 sample_msb = data & 63;
167 }
168
169 /************************************/
170 /* Play speech sample */
171 /************************************/
polepos_sample_play(int sample)172 void polepos_sample_play(int sample)
173 {
174 int start = sample_offsets[sample];
175 int len = sample_offsets[sample + 1] - start;
176
177 if (Machine->sample_rate == 0)
178 return;
179
180 mixer_play_sample(channel, speech + start * 16, len * 16, 4000*8, 0);
181 }
182