Subversion Repositories pentevo

Rev

Rev 716 | Blame | Last modification | View Log | Download | RSS feed

  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
  293.