Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
716 | lvd | 1 | #include "std.h" |
2 | |||
3 | #include "emul.h" |
||
4 | #include "vars.h" |
||
5 | #include "bass.h" |
||
6 | #include "snd_bass.h" |
||
7 | #include "gshle.h" |
||
8 | #include "gs.h" |
||
9 | #include "sound.h" |
||
10 | |||
11 | #ifdef MOD_GSBASS |
||
12 | void GSHLE::set_busy(unsigned char newval) |
||
13 | { |
||
14 | busy = chan[0].busy = chan[1].busy = chan[2].busy = chan[3].busy = newval; |
||
15 | } |
||
16 | |||
17 | void GSHLE::reset() |
||
18 | { |
||
19 | fxvol = modvol = 0x3F; |
||
20 | make_gs_volume(fxvol); |
||
21 | to_ptr = data_in; mod_playing = 0; |
||
22 | used = 0; mod = 0; modsize = 0; set_busy(0); |
||
23 | resetmod(); total_fx = 1; |
||
24 | memset(sample, 0, sizeof sample); |
||
25 | memset(chan, 0, sizeof chan); |
||
26 | out(0xBB, 0x23); // send 'get pages' command |
||
27 | } |
||
28 | |||
29 | void GSHLE::applyconfig() |
||
30 | { |
||
31 | double period = 6848, mx = 0.943874312682; // mx=1/root(2,12) |
||
32 | double basefq = 7093789.0/2; |
||
33 | int i; //Alone Coder 0.36.7 |
||
34 | for (/*int*/ i = 0; i < 96; i++, period *= mx) |
||
35 | note2rate[i] = (unsigned)(basefq/period); |
||
36 | for (; i < 0x100; i++) note2rate[i] = note2rate[i-1]; |
||
37 | if (BASS::Bass) |
||
38 | setmodvol(modvol); |
||
39 | } |
||
40 | |||
41 | unsigned char GSHLE::in(unsigned char port) |
||
42 | { |
||
43 | if (port == 0xBB) return gsstat; |
||
44 | if (!resptr) return 0xFF; // no data available |
||
45 | unsigned char byte = *resptr; |
||
46 | if (resmode) resptr++, resmode--; // goto next byte |
||
47 | return byte; |
||
48 | } |
||
49 | |||
50 | void GSHLE::out(unsigned char port, unsigned char byte) |
||
51 | { |
||
52 | if (port == 0xB3) { |
||
53 | if (!load_stream) { |
||
54 | *to_ptr = byte; |
||
55 | if (resmod2) to_ptr++, resmod2--; |
||
56 | if (!resmod2) { |
||
57 | if ((gscmd & 0xF8) == 0x88) start_fx(data_in[0], gscmd & 3, 0xFF, data_in[1]); |
||
58 | if ((gscmd & 0xF8) == 0x90) start_fx(data_in[0], gscmd & 3, data_in[1], 0xFF); |
||
59 | if ((gscmd & 0xF8) == 0x98) start_fx(data_in[0], gscmd & 3, data_in[2], data_in[1]); |
||
60 | to_ptr = data_in; |
||
61 | } |
||
62 | } else { |
||
63 | if (load_stream == 4) { // covox |
||
64 | flush_dig_snd(); |
||
65 | covFB_vol = byte*conf.sound.gs_vol/0x100; |
||
66 | return; |
||
67 | } |
||
68 | streamstart[streamsize++] = byte; |
||
69 | if (load_stream == 1) loadmod = 1; |
||
70 | else loadfx = cur_fx; |
||
71 | } |
||
72 | return; |
||
73 | } |
||
74 | // else command |
||
75 | unsigned i; |
||
76 | gsstat = 0x7E; resmode = 0; // default - 1 byte ready |
||
77 | resptr = gstmp; to_ptr = data_in; resmod2 = 0; |
||
78 | gscmd = byte; |
||
79 | if (load_stream == 4) load_stream = 0; // close covox mode |
||
80 | switch (byte) { |
||
81 | case 0x0E: // LPT covox |
||
82 | load_stream = 4; |
||
83 | break; |
||
84 | case 0xF3: case 0xF4: // reset |
||
85 | reset_gs(); |
||
86 | break; |
||
87 | case 0xF5: |
||
88 | set_busy(1); break; |
||
89 | case 0xF6: |
||
90 | set_busy(0); break; |
||
91 | case 0x20: // get total memory |
||
92 | *(unsigned*)gstmp = conf.gs_ramsize*1024-32768-16384; |
||
93 | resmode = 2; gsstat = 0xFE; |
||
94 | break; |
||
95 | case 0x21: // get free memory |
||
96 | *(unsigned*)gstmp = (conf.gs_ramsize*1024-32768-16384) - used; |
||
97 | resmode = 2; gsstat = 0xFE; |
||
98 | break; |
||
99 | case 0x23: // get pages |
||
100 | *gstmp = ((conf.gs_ramsize*1024)/32768)-1; |
||
101 | gsstat = 0xFE; |
||
102 | break; |
||
103 | case 0x2A: // set module vol |
||
104 | case 0x35: |
||
105 | *gstmp = modvol; |
||
106 | modvol = *data_in; |
||
107 | setmodvol(modvol); |
||
108 | break; |
||
109 | case 0x2B: // set FX vol |
||
110 | case 0x3D: |
||
111 | *gstmp = fxvol; |
||
112 | fxvol = *data_in; |
||
113 | make_gs_volume(fxvol); |
||
114 | break; |
||
115 | case 0x2E: // set FX |
||
116 | cur_fx = *data_in; |
||
117 | break; |
||
118 | case 0x30: // load MOD |
||
119 | // if (mod) break; |
||
120 | reset_gs(); |
||
121 | streamstart = mod = GSRAM_M + used; |
||
122 | streamsize = 0; |
||
123 | *gstmp = 1; load_stream = 1; |
||
124 | break; |
||
125 | case 0x31: // play MOD |
||
126 | restart_mod(0,0); |
||
127 | break; |
||
128 | case 0x32: // stop MOD |
||
129 | mod_playing = 0; |
||
130 | stop_mod(); |
||
131 | break; |
||
132 | case 0x33: // continue MOD |
||
133 | if (mod) mod_playing = 1, cont_mod(); |
||
134 | break; |
||
135 | case 0x36: // data = #FF |
||
136 | *gstmp = 0xFF; |
||
137 | break; |
||
138 | case 0x38: // load FX |
||
139 | case 0x3E: |
||
140 | if (total_fx == 64) break; |
||
141 | cur_fx = *gstmp = total_fx; |
||
142 | load_stream = (byte == 0x38) ? 2 : 3; |
||
143 | streamstart = GSRAM_M + used; |
||
144 | sample[total_fx].start = streamstart; |
||
145 | streamsize = 0; |
||
146 | break; |
||
147 | case 0x39: // play FX |
||
148 | start_fx(*data_in, 0xFF, 0xFF, 0xFF); |
||
149 | break; |
||
150 | case 0x3A: // stop fx |
||
151 | for (i = 0; i < 4; i++) |
||
152 | if (*data_in & (1<<i)) chan[i].start = 0; |
||
153 | break; |
||
154 | case 0x40: // set note |
||
155 | sample[cur_fx].note = *data_in; |
||
156 | break; |
||
157 | case 0x41: // set vol |
||
158 | sample[cur_fx].volume = *data_in; |
||
159 | break; |
||
160 | case 0x48: // set loop start |
||
161 | resmod2 = 2; |
||
162 | *(unsigned char*)&sample[cur_fx].loop = *data_in; |
||
163 | to_ptr = 1+(unsigned char*)&sample[cur_fx].loop; |
||
164 | break; |
||
165 | case 0x49: // set loop end |
||
166 | resmod2 = 2; |
||
167 | *(unsigned char*)&sample[cur_fx].end = *data_in; |
||
168 | to_ptr = 1+(unsigned char*)&sample[cur_fx].end; |
||
169 | break; |
||
170 | case 0x60: // get song pos |
||
171 | *gstmp = (unsigned char)modgetpos(); |
||
172 | break; |
||
173 | case 0x61: // get pattern pos |
||
174 | *gstmp = (unsigned char)(modgetpos() >> 16); |
||
175 | break; |
||
176 | case 0x62: // get mixed pos |
||
177 | i = modgetpos(); |
||
178 | *gstmp = ((i>>16) & 0x3F) | (i << 6); |
||
179 | break; |
||
180 | case 0x63: // get module notes |
||
181 | resmode = 3; gsstat = 0xFE; |
||
182 | break; |
||
183 | case 0x64: // get module vols |
||
184 | *(unsigned*)gstmp = 0; |
||
185 | resmode = 3; gsstat = 0xFE; |
||
186 | break; |
||
187 | case 0x65: // jmp to pos |
||
188 | restart_mod(*data_in,0); |
||
189 | break; |
||
190 | case 0x80: // direct play 1 |
||
191 | case 0x81: |
||
192 | case 0x82: |
||
193 | case 0x83: |
||
194 | start_fx(*data_in, byte & 3, 0xFF, 0xFF); |
||
195 | break; |
||
196 | case 0x88: // direct play 2 |
||
197 | case 0x89: |
||
198 | case 0x8A: |
||
199 | case 0x8B: |
||
200 | case 0x90: // direct play 3 |
||
201 | case 0x91: |
||
202 | case 0x92: |
||
203 | case 0x93: |
||
204 | resmod2 = 1; to_ptr++; |
||
205 | break; |
||
206 | case 0x98: // direct play 4 |
||
207 | case 0x99: |
||
208 | case 0x9A: |
||
209 | case 0x9B: |
||
210 | resmod2 = 2; to_ptr++; |
||
211 | break; |
||
212 | |||
213 | case 0xD2: // close stream |
||
214 | if (!load_stream) break; |
||
215 | // bug?? command #3E loads unsigned samples (REX 1,2) |
||
216 | // if (load_stream == 3) // unsigned sample -> convert to unsigned |
||
217 | // for (unsigned ptr = 0; ptr < streamsize; sample[total_fx].start[ptr++] ^= 0x80); |
||
218 | if (load_stream == 1) { modsize = streamsize, init_mod(); } |
||
219 | else { |
||
220 | sample[total_fx].end = streamsize; |
||
221 | sample[total_fx].loop = 0xFFFFFF; |
||
222 | sample[total_fx].volume = 0x40; |
||
223 | sample[total_fx].note = 60; |
||
224 | //{char fn[200];sprintf(fn,"s-%d.raw",total_fx); FILE*ff=fopen(fn,"wb");fwrite(sample[total_fx].start,1,streamsize,ff);fclose(ff);} |
||
225 | total_fx++; |
||
226 | } |
||
227 | used += streamsize; |
||
228 | load_stream = 0; |
||
229 | break; |
||
230 | |||
231 | case 0x00: // reset flags - already done |
||
232 | case 0x08: |
||
233 | case 0xD1: // start stream |
||
234 | break; |
||
235 | default: |
||
236 | badgs[byte] = 1; |
||
237 | break; |
||
238 | } |
||
239 | } |
||
240 | |||
241 | void GSHLE::start_fx(unsigned fx, unsigned ch, unsigned char vol, unsigned char note) |
||
242 | { |
||
243 | unsigned i; //Alone Coder 0.36.7 |
||
244 | if (!fx) fx = cur_fx; // fx=0 - use default |
||
245 | if (vol == 0xFF) vol = sample[fx].volume; |
||
246 | if (note == 0xFF) note = sample[fx].note; |
||
247 | if (ch == 0xFF) { // find free channel |
||
248 | for (/*unsigned*/ i = 0; i < 4; i++) |
||
249 | if (!chan[i].start) ch = i; |
||
250 | if (ch == 0xFF) |
||
251 | for (i = 1, ch = 0; i < 4; i++) |
||
252 | if (chan[i].ptr > chan[ch].ptr) ch = i; |
||
253 | } |
||
254 | chan[ch].volume = vol; |
||
255 | chan[ch].start = sample[fx].start; |
||
256 | chan[ch].loop = sample[fx].loop; |
||
257 | chan[ch].end = sample[fx].end; |
||
258 | chan[ch].ptr = 0; |
||
259 | chan[ch].freq = note2rate[note]; |
||
260 | // ch0,1 - left, ch2,3 - right |
||
261 | startfx(&chan[ch], (ch & 2)? 1.0f : -1.0f); |
||
262 | } |
||
263 | |||
264 | DWORD CALLBACK gs_render(HSTREAM handle, void *buffer, DWORD length, void *user) |
||
265 | { |
||
266 | GSHLE::CHANNEL *ch = (GSHLE::CHANNEL*)user; |
||
267 | |||
268 | if (!ch->start) |
||
269 | return BASS_STREAMPROC_END; |
||
270 | if (ch->busy) |
||
271 | { |
||
272 | memset(buffer, 0, length); |
||
273 | return length; |
||
274 | } |
||
275 | unsigned sample_pos = 0; |
||
276 | for (unsigned i = 0; i < length; i++) |
||
277 | { |
||
278 | ((BYTE*)buffer)[i] = ch->start[ch->ptr++]; |
||
279 | if (ch->ptr >= ch->end) |
||
280 | { |
||
281 | if (ch->end < ch->loop) |
||
282 | { |
||
283 | ch->start = 0; |
||
284 | return i + BASS_STREAMPROC_END; |
||
285 | } |
||
286 | else |
||
287 | ch->ptr = ch->loop; |
||
288 | } |
||
289 | } |
||
290 | return length; |
||
291 | } |
||
292 | #endif |