menu bg, pc linux build
[picodrive.git] / Pico / sound / ym2612.c
index 56e5312..75d5ad3 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-** This is a bunch of remains of original fm.c from MAME project. All stuff \r
+** This is a bunch of remains of original fm.c from MAME project. All stuff\r
 ** unrelated to ym2612 was removed, multiple chip support was removed,\r
 ** some parts of code were slightly rewritten and tied to the emulator.\r
 **\r
 #include <math.h>\r
 \r
 #include "ym2612.h"\r
+#include "mix.h"\r
 \r
 #ifndef EXTERNAL_YM2612\r
 #include <stdlib.h>\r
@@ -120,7 +121,6 @@ static YM2612 ym2612;
 \r
 #else\r
 extern YM2612 *ym2612_940;\r
-extern int *mix_buffer;\r
 #define ym2612 (*ym2612_940)\r
 \r
 #endif\r
@@ -841,7 +841,7 @@ typedef struct
        UINT32 eg_timer;\r
        UINT32 eg_timer_add;\r
        UINT32 pack;     // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]\r
-       UINT32 algo;     /* 50 */\r
+       UINT32 algo;     /* 50: algo[3], was_update */\r
        INT32  op1_out;\r
 } chan_rend_context;\r
 \r
@@ -1077,6 +1077,7 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
                        } else {\r
                                buffer[scounter] += smp;\r
                        }\r
+                       ct->algo = 8; // algo is only used in asm, here only bit3 is used\r
                }\r
 \r
                /* update phase counters AFTER output calculations */\r
@@ -1091,7 +1092,7 @@ void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length)
 #endif\r
 \r
 \r
-static void chan_render(int *buffer, int length, FM_CH *CH, UINT32 flags) // flags: stereo, lastchan, disabled, ?, pan_r, pan_l\r
+static int chan_render(int *buffer, int length, FM_CH *CH, UINT32 flags) // flags: stereo, lastchan, disabled, ?, pan_r, pan_l\r
 {\r
        chan_rend_context ct;\r
 \r
@@ -1193,6 +1194,8 @@ static void chan_render(int *buffer, int length, FM_CH *CH, UINT32 flags) // fla
        CH->SLOT[SLOT3].phase = ct.phase3;\r
        CH->SLOT[SLOT4].phase = ct.phase4;\r
        CH->mem_value = ct.mem;\r
+\r
+       return (ct.algo & 8) >> 3; // had output\r
 }\r
 \r
 /* update phase increment and envelope generator */\r
@@ -1584,13 +1587,13 @@ INT32 *ym2612_dacout;
 \r
 \r
 /* Generate samples for YM2612 */\r
-void YM2612UpdateOne_(short *buffer, int length, int stereo)\r
+int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)\r
 {\r
        int pan;\r
-#ifndef EXTERNAL_YM2612\r
-       int i;\r
-       static int *mix_buffer = 0, mix_buffer_length = 0;\r
-#endif\r
+       int active_chs = 0;\r
+\r
+       // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash\r
+       if (is_buf_empty) memset32(buffer, 0, length<<stereo);\r
 \r
        /* refresh PG and EG */\r
        refresh_fc_eg_chan( &ym2612.CH[0] );\r
@@ -1613,44 +1616,16 @@ void YM2612UpdateOne_(short *buffer, int length, int stereo)
        pan = ym2612.OPN.pan;\r
        if (stereo) stereo = 1;\r
 \r
-#ifndef EXTERNAL_YM2612\r
-       if (mix_buffer_length < length) {\r
-               mix_buffer = realloc(mix_buffer, length*4<<stereo); // FIXME: need to free this at some point\r
-               if (!mix_buffer) return;\r
-               mix_buffer_length = length;\r
-       }\r
-#endif\r
-       memset(mix_buffer, 0, length*4<<stereo);\r
-\r
-       /* mix to 32bit temporary buffer */\r
-       chan_render(mix_buffer, length, &ym2612.CH[0], stereo|((pan&0x003)<<4)); // flags: stereo, lastchan, disabled, ?, pan_r, pan_l\r
-       chan_render(mix_buffer, length, &ym2612.CH[1], stereo|((pan&0x00c)<<2));\r
-       chan_render(mix_buffer, length, &ym2612.CH[2], stereo|((pan&0x030)   ));\r
-       chan_render(mix_buffer, length, &ym2612.CH[3], stereo|((pan&0x0c0)>>2));\r
-       chan_render(mix_buffer, length, &ym2612.CH[4], stereo|((pan&0x300)>>4));\r
-       chan_render(mix_buffer, length, &ym2612.CH[5], stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)|2);\r
+       /* mix to 32bit dest */\r
+       // flags: stereo, lastchan, disabled, ?, pan_r, pan_l\r
+       active_chs |= chan_render(buffer, length, &ym2612.CH[0], stereo|((pan&0x003)<<4)) << 0;\r
+       active_chs |= chan_render(buffer, length, &ym2612.CH[1], stereo|((pan&0x00c)<<2)) << 1;\r
+       active_chs |= chan_render(buffer, length, &ym2612.CH[2], stereo|((pan&0x030)   )) << 2;\r
+       active_chs |= chan_render(buffer, length, &ym2612.CH[3], stereo|((pan&0x0c0)>>2)) << 3;\r
+       active_chs |= chan_render(buffer, length, &ym2612.CH[4], stereo|((pan&0x300)>>4)) << 4;\r
+       active_chs |= chan_render(buffer, length, &ym2612.CH[5], stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)|2) << 5;\r
 \r
-#ifndef EXTERNAL_YM2612\r
-       /* limit and mix to output buffer */\r
-       if (stereo) {\r
-               int *mb = mix_buffer;\r
-               for (i = length; i > 0; i--) {\r
-                       int l, r;\r
-                       l = r = *buffer;\r
-                       l += *mb++, r += *mb++;\r
-                       Limit( l, MAXOUT, MINOUT );\r
-                       Limit( r, MAXOUT, MINOUT );\r
-                       *buffer++ = l; *buffer++ = r;\r
-               }\r
-       } else {\r
-               for (i = 0; i < length; i++) {\r
-                       int l = mix_buffer[i];\r
-                       l += buffer[i];\r
-                       Limit( l, MAXOUT, MINOUT );\r
-                       buffer[i] = l;\r
-               }\r
-       }\r
-#endif\r
+       return active_chs; // 1 if buffer updated\r
 }\r
 \r
 \r