Subversion Repositories pentevo

Rev

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