Subversion Repositories Kolibri OS

Rev

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

  1. /***************************************************************************
  2.  
  3.   sn76496.c
  4.  
  5.   Routines to emulate the Texas Instruments SN76489 / SN76496 programmable
  6.   tone /noise generator. Also known as (or at least compatible with) TMS9919.
  7.  
  8.   Noise emulation is not accurate due to lack of documentation. The noise
  9.   generator uses a shift register with a XOR-feedback network, but the exact
  10.   layout is unknown. It can be set for either period or white noise; again,
  11.   the details are unknown.
  12.  
  13. ***************************************************************************/
  14.  
  15. #include <stdint.h>
  16. #include <string.h>
  17. #include "system.h"
  18. #include "sn76496.h"
  19.  
  20.  
  21. #define MAX_OUTPUT 0x7fff
  22. #define AUDIO_CONV(A) (A)
  23.  
  24. #define STEP 0x10000
  25.  
  26.  
  27. /* Formulas for noise generator */
  28. /* bit0 = output */
  29.  
  30. /* noise feedback for white noise mode */
  31. #define FB_WNOISE 0x12000   /* bit15.d(16bits) = bit0(out) ^ bit2 */
  32. //#define FB_WNOISE 0x14000 /* bit15.d(16bits) = bit0(out) ^ bit1 */
  33. //#define FB_WNOISE 0x28000 /* bit16.d(17bits) = bit0(out) ^ bit2 (same to AY-3-8910) */
  34. //#define FB_WNOISE 0x50000 /* bit17.d(18bits) = bit0(out) ^ bit2 */
  35.  
  36. /* noise feedback for periodic noise mode */
  37. /* it is correct maybe (it was in the Megadrive sound manual) */
  38. //#define FB_PNOISE 0x10000 /* 16bit rorate */
  39. #define FB_PNOISE 0x08000   /* JH 981127 - fixes Do Run Run */
  40.  
  41. /* noise generator start preset (for periodic noise) */
  42. #define NG_PRESET 0x0f35
  43.  
  44.  
  45. struct SN76496
  46. {
  47.     int Channel;
  48.     int SampleRate;
  49.     unsigned int UpdateStep;
  50.     int VolTable[16];   /* volume table         */
  51.     int Register[8];    /* registers */
  52.     int LastRegister;   /* last register written */
  53.     int Volume[4];      /* volume of voice 0-2 and noise */
  54.     unsigned int RNG;       /* noise generator      */
  55.     int NoiseFB;        /* noise feedback mask */
  56.     unsigned int Period[4];
  57.     int Count[4];
  58.     int Output[4];
  59. };
  60.  
  61.  
  62. static struct SN76496 sn[MAX_76496];
  63.  
  64. void SN76496_dump(int chip, uint8_t buf[16])
  65. {
  66.         struct SN76496 *R = &sn[chip];
  67.         uint16_t tmp;
  68.         unsigned int i;
  69.  
  70.         for (i = 0; (i < 8); ++i) {
  71.                 tmp = h2le16(R->Register[i]);
  72.                 memcpy(&buf[(i * 2)], &tmp, 2);
  73.         }
  74. }
  75.  
  76. void SN76496_restore(int chip, uint8_t buf[16])
  77. {
  78.         struct SN76496 *R = &sn[chip];
  79.         uint16_t tmp;
  80.         unsigned int i;
  81.  
  82.         for (i = 0; (i < 8); ++i) {
  83.                 memcpy(&tmp, &buf[(i * 2)], 2);
  84.                 R->Register[i] = le2h16(tmp);
  85.         }
  86. }
  87.  
  88. void SN76496Write(int chip,int data)
  89. {
  90.     struct SN76496 *R = &sn[chip];
  91.  
  92.  
  93.     /* update the output buffer before changing the registers */
  94.     ///// commented out by starshine
  95.     //stream_update(R->Channel,0);
  96.  
  97.     if (data & 0x80)
  98.     {
  99.         int r = (data & 0x70) >> 4;
  100.         int c = r/2;
  101.  
  102.         R->LastRegister = r;
  103.         R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f);
  104.         switch (r)
  105.         {
  106.             case 0: /* tone 0 : frequency */
  107.             case 2: /* tone 1 : frequency */
  108.             case 4: /* tone 2 : frequency */
  109.                 R->Period[c] = R->UpdateStep * R->Register[r];
  110.                 if (R->Period[c] == 0) R->Period[c] = R->UpdateStep;
  111.                 if (r == 4)
  112.                 {
  113.                     /* update noise shift frequency */
  114.                     if ((R->Register[6] & 0x03) == 0x03)
  115.                         R->Period[3] = 2 * R->Period[2];
  116.                 }
  117.                 break;
  118.             case 1: /* tone 0 : volume */
  119.             case 3: /* tone 1 : volume */
  120.             case 5: /* tone 2 : volume */
  121.             case 7: /* noise  : volume */
  122.                 R->Volume[c] = R->VolTable[data & 0x0f];
  123.                 break;
  124.             case 6: /* noise  : frequency, mode */
  125.                 {
  126.                     int n = R->Register[6];
  127.                     R->NoiseFB = (n & 4) ? FB_WNOISE : FB_PNOISE;
  128.                     n &= 3;
  129.                     /* N/512,N/1024,N/2048,Tone #3 output */
  130.                     R->Period[3] = (n == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5+n));
  131.  
  132.                     /* reset noise shifter */
  133.                     R->RNG = NG_PRESET;
  134.                     R->Output[3] = R->RNG & 1;
  135.                 }
  136.                 break;
  137.         }
  138.     }
  139.     else
  140.     {
  141.         int r = R->LastRegister;
  142.         int c = r/2;
  143.  
  144.         switch (r)
  145.         {
  146.             case 0: /* tone 0 : frequency */
  147.             case 2: /* tone 1 : frequency */
  148.             case 4: /* tone 2 : frequency */
  149.                 R->Register[r] = (R->Register[r] & 0x0f) | ((data & 0x3f) << 4);
  150.                 R->Period[c] = R->UpdateStep * R->Register[r];
  151.                 if (R->Period[c] == 0) R->Period[c] = R->UpdateStep;
  152.                 if (r == 4)
  153.                 {
  154.                     /* update noise shift frequency */
  155.                     if ((R->Register[6] & 0x03) == 0x03)
  156.                         R->Period[3] = 2 * R->Period[2];
  157.                 }
  158.                 break;
  159.         }
  160.     }
  161. }
  162.  
  163.  
  164. void SN76496_0_w(int offset, int data) { (void)offset; SN76496Write(0, data); }
  165. void SN76496_1_w(int offset, int data) { (void)offset; SN76496Write(1, data); }
  166. void SN76496_2_w(int offset, int data) { (void)offset; SN76496Write(2, data); }
  167. void SN76496_3_w(int offset, int data) { (void)offset; SN76496Write(3, data); }
  168.  
  169.  
  170.  
  171. void SN76496Update_8_2(int chip,void *buffer,int length)
  172. {
  173. #define DATATYPE unsigned char
  174. #define DATACONV(A) AUDIO_CONV((A) / (STEP * 256))
  175. #include "sn76496u.c"
  176. #undef DATATYPE
  177. #undef DATACONV
  178. }
  179.  
  180. void SN76496Update_16_2(int chip,void *buffer,int length)
  181. {
  182. #define DATATYPE unsigned short
  183. #define DATACONV(A) ((A) / STEP)
  184. #include "sn76496u.c"
  185. #undef DATATYPE
  186. #undef DATACONV
  187. }
  188.  
  189.  
  190.  
  191. void SN76496_set_clock(int chip,int clock)
  192. {
  193.     struct SN76496 *R = &sn[chip];
  194.  
  195.  
  196.     /* the base clock for the tone generators is the chip clock divided by 16; */
  197.     /* for the noise generator, it is clock / 256. */
  198.     /* Here we calculate the number of steps which happen during one sample */
  199.     /* at the given sample rate. No. of events = sample rate / (clock/16). */
  200.     /* STEP is a multiplier used to turn the fraction into a fixed point */
  201.     /* number. */
  202.     R->UpdateStep = ((double)STEP * R->SampleRate * 16) / clock;
  203. }
  204.  
  205.  
  206.  
  207. static void SN76496_set_volume(int chip,int volume,int gain)
  208. {
  209.     struct SN76496 *R = &sn[chip];
  210.     int i;
  211.     double out;
  212.  
  213.     (void)volume;
  214.     ///// commented out by starshine
  215.     //stream_set_volume(R->Channel,volume);
  216.  
  217.     gain &= 0xff;
  218.  
  219.     /* increase max output basing on gain (0.2 dB per step) */
  220.     out = MAX_OUTPUT / 3;
  221.     while (gain-- > 0)
  222.         out *= 1.023292992; /* = (10 ^ (0.2/20)) */
  223.  
  224.     /* build volume table (2dB per step) */
  225.     for (i = 0;i < 15;i++)
  226.     {
  227.         /* limit volume to avoid clipping */
  228.         if (out > MAX_OUTPUT / 3) R->VolTable[i] = MAX_OUTPUT / 3;
  229.         else R->VolTable[i] = out;
  230.  
  231.         out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */
  232.     }
  233.     R->VolTable[15] = 0;
  234. }
  235.  
  236.  
  237.  
  238. int SN76496_init(int chip,int clock,int sample_rate,int sample_bits)
  239. {
  240.     int i;
  241.     struct SN76496 *R = &sn[chip];
  242.     /* char name[40]; */
  243.  
  244.     (void)sample_bits;
  245.     ////// commented out by starshine
  246.     //sprintf(name,"SN76496 #%d",chip);
  247.     //R->Channel = stream_init(msound,
  248.     //        name,sample_rate,sample_bits,
  249.     //        chip,(sample_bits == 16) ? SN76496Update_16 : SN76496Update_8);
  250.  
  251.     if (R->Channel == -1)
  252.         return 1;
  253.  
  254.     R->SampleRate = sample_rate;
  255.     SN76496_set_clock(chip,clock);
  256.     SN76496_set_volume(chip,255,0);
  257.  
  258.     for (i = 0;i < 4;i++) R->Volume[i] = 0;
  259.  
  260.     R->LastRegister = 0;
  261.     for (i = 0;i < 8;i+=2)
  262.     {
  263.         R->Register[i] = 0;
  264.         R->Register[i + 1] = 0x0f;  /* volume = 0 */
  265.     }
  266.  
  267.     for (i = 0;i < 4;i++)
  268.     {
  269.         R->Output[i] = 0;
  270.         R->Period[i] = R->Count[i] = R->UpdateStep;
  271.     }
  272.     R->RNG = NG_PRESET;
  273.     R->Output[3] = R->RNG & 1;
  274.  
  275.     return 0;
  276. }
  277.  
  278.  
  279.  
  280. int SN76496_sh_start()
  281. {
  282.     ///// total commenting out by starshine
  283.     //int chip;
  284.     //const struct SN76496interface *intf = msound->sound_interface;
  285.  
  286.  
  287.     //for (chip = 0;chip < intf->num;chip++)
  288.     //{
  289.     //    if (SN76496_init(msound,chip,intf->baseclock,Machine->sample_rate,Machine->sample_bits) != 0)
  290.     //        return 1;
  291.  
  292.     //    SN76496_set_volume(chip,intf->volume[chip] & 0xff,(intf->volume[chip] >> 8) & 0xff);
  293.     //}
  294.     return 0;
  295. }
  296.