Subversion Repositories pentevo

Rev

Rev 1099 | Rev 1147 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. // From https://github.com/tslabs/zx-evo/blob/master/pentevo/unreal/Unreal/sound/dev_moonsound.cpp
  2.  
  3. #include "../std.h"
  4. #include "../emul.h"
  5. #include "../vars.h"
  6. #include "../util.h"
  7. #include "dev_moonsound.h"
  8.  
  9. #include "ymf262.h"
  10. #include "ymf278.h"
  11.  
  12. #define MASTER_CLOCK 33868800
  13.  
  14. struct ZXMMoonSound_priv
  15. {
  16. friend class ZXMMoonSound;
  17.  
  18. public:
  19.         ZXMMoonSound_priv();
  20.         ~ZXMMoonSound_priv();
  21.  
  22. private:
  23.         YMF262 *ymf262;
  24.         int opl3latch;
  25.  
  26.         YMF278 *ymf278;
  27.         int opl4latch;
  28. };
  29.  
  30. inline EmuTime SystemTime()
  31. {
  32.         return cpu.t + comp.frame_counter * conf.frame;
  33. }
  34.  
  35. ZXMMoonSound_priv::ZXMMoonSound_priv()
  36. {
  37.         EmuTime systemTime = 0;
  38.  
  39.         ymf262 = new YMF262(0, systemTime);
  40.         ymf262->setSampleRate(44100, 1);
  41.         ymf262->setVolume(32767 * 2 / 10);
  42.  
  43.         ymf278 = new YMF278(0, 4096, 2048*1024, systemTime);
  44.         ymf278->setSampleRate(44100, 1);
  45.         ymf278->setVolume(32767 * 2 / 10);
  46. }
  47.  
  48. ZXMMoonSound_priv::~ZXMMoonSound_priv()
  49. {
  50.         delete ymf262;
  51.         delete ymf278;
  52. }
  53.  
  54. /*  */
  55. ZXMMoonSound::ZXMMoonSound() :
  56.         system_clock_rate( 0 )
  57. {
  58.         d = new ZXMMoonSound_priv();
  59.         reset();
  60. }
  61.  
  62. int ZXMMoonSound::load_rom(char *path)
  63. {
  64.         FILE *fp = fopen( path, "rb" );
  65.         if ( !fp )
  66.         {
  67.                 return -1;
  68.         }
  69.  
  70.         fread( d->ymf278->getRom(), 1, d->ymf278->getRomSize(), fp );
  71.  
  72.         fclose( fp );
  73.  
  74.         return 0;
  75. }
  76.  
  77. void ZXMMoonSound::reset()
  78. {
  79.         unsigned tStatesPerSecond = conf.frame * conf.intfq;
  80.         EmuTime systemTime = SystemTime();
  81.  
  82.         d->ymf262->reset( systemTime, tStatesPerSecond );
  83.         d->ymf278->reset( systemTime );
  84. }
  85.  
  86. bool ZXMMoonSound::write( u8 port, u8 val )
  87. {
  88.         //printf("ZXM-MoonSound write(%.2x, %.2x)\n", port, val);
  89.  
  90.         EmuTime systemTime = SystemTime();
  91.  
  92.         if ( (port & 0xFE) == 0xC2 )
  93.         {
  94.                 switch (port & 0x01) {
  95.                 case 0: // select register
  96.                         d->opl4latch = val;
  97.                         break;
  98.                 case 1:
  99.                         d->ymf278->writeRegOPL4(d->opl4latch, val, systemTime);
  100.                         break;
  101.                 }
  102.  
  103.                 return true;
  104.         }
  105.         else if ( (port & 0xFC) == 0xC4 )
  106.         {
  107.                 switch (port & 0x03) {
  108.                 case 0:
  109.                         d->opl3latch = val;
  110.                         break;
  111.                 case 2: // select register bank 1
  112.                         d->opl3latch = val | 0x100;
  113.                         break;
  114.                 case 1:
  115.                 case 3: // write fm register
  116.                         d->ymf262->writeReg(d->opl3latch, val, systemTime);
  117.                         break;
  118.                 }
  119.  
  120.                 return true;
  121.         }
  122.  
  123.         return false;
  124. }
  125.  
  126. bool ZXMMoonSound::read( u8 port, u8 &val )
  127. {
  128.         //printf("ZXM-MoonSound read(%.2x)\n", port);
  129.  
  130.         EmuTime systemTime = SystemTime();
  131.  
  132.         if ( (port & 0xFE) == 0xC2 )
  133.         {
  134.                 switch (port & 0x01) {
  135.                 case 1: // read wave register
  136.                         val = d->ymf278->readRegOPL4(d->opl4latch, systemTime);
  137.                         break;
  138.                 }
  139.  
  140.                 return true;
  141.         }
  142.         else if( (port & 0xFC) == 0xC4 )
  143.         {
  144.                 switch (port & 0x03) {
  145.                 case 0: // read status
  146.                 case 2:
  147.                         val = d->ymf262->readStatus(systemTime) | d->ymf278->readStatus(systemTime);
  148.                         break;
  149.                 case 1:
  150.                 case 3: // read fm register
  151.                         val = d->ymf262->readReg(d->opl3latch);
  152.                         break;
  153.                 }
  154.  
  155.                 return true;
  156.         }
  157.  
  158.         return false;
  159. }
  160.  
  161.  
  162. void ZXMMoonSound::set_timings(unsigned system_clock_rate, unsigned chip_clock_rate, unsigned sample_rate)
  163. {
  164.         d->ymf262->setSampleRate( sample_rate, 1 );
  165.         d->ymf262->setVolume((u16)(1 * (conf.sound.moonsound_vol / 8192.0))); // doesn't work
  166.         d->ymf278->setSampleRate( sample_rate, 1 );
  167.         d->ymf278->setVolume((u16)(2000 * (conf.sound.moonsound_vol / 8192.0)));
  168.        
  169.         chip_clock_rate = sample_rate;
  170.  
  171.         ZXMMoonSound::system_clock_rate = system_clock_rate;
  172.         ZXMMoonSound::chip_clock_rate = chip_clock_rate;
  173.  
  174.         SNDRENDER::set_timings(chip_clock_rate, sample_rate);
  175.         passed_chip_ticks = passed_clk_ticks = 0;
  176.         t = 0;
  177. }
  178.  
  179. void ZXMMoonSound::start_frame(bufptr_t dst)
  180. {
  181.     SNDRENDER::start_frame(dst);
  182. }
  183.  
  184. unsigned ZXMMoonSound::end_frame(unsigned clk_ticks)
  185. {
  186.         u64 end_chip_tick = ((passed_clk_ticks + clk_ticks) * chip_clock_rate) / system_clock_rate;
  187.  
  188.         flush((unsigned)(end_chip_tick - passed_chip_ticks));
  189.  
  190.     unsigned Val = SNDRENDER::end_frame(t);
  191.         passed_clk_ticks += clk_ticks;
  192.     passed_chip_ticks += t;
  193.     t = 0;
  194.  
  195.     return Val;
  196. }
  197.  
  198. void ZXMMoonSound::flush(unsigned chiptick)
  199. {
  200.         while (t < chiptick)
  201.     {
  202.                 int buffer[2] = { 0, 0 };
  203.                 int *buf;
  204.  
  205.                 t++;
  206.  
  207.                 buf = d->ymf262->updateBuffer(1);
  208.                 if ( buf )
  209.                 {
  210.                         buffer[0] += buf[0] / 10;
  211.                         buffer[1] += buf[1] / 10;
  212.                 }
  213.  
  214.                 buf = d->ymf278->updateBuffer(1);
  215.                 if ( buf )
  216.                 {
  217.                         buffer[0] += buf[0];
  218.                         buffer[1] += buf[1];
  219.                 }
  220.                
  221.                 SNDRENDER::update( t, buffer[0], buffer[1] );
  222.         }
  223. }
  224.  
  225. ZXMMoonSound zxmmoonsound;