示例#1
0
        public override int start(Mame.MachineSound msound)
        {
            string snd_name = "K005289";
            //k005289_sound_channel voice=channel_list;
            k005289_interface intf = (k005289_interface)msound.sound_interface;

            /* get stream channels */
            stream = Mame.stream_init(snd_name, intf.volume, Mame.Machine.sample_rate, 0, K005289_update);
            mclock = intf.master_clock;
            rate = Mame.Machine.sample_rate;

            /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
            mixer_buffer = new _ShortPtr(2 * sizeof(short) * Mame.Machine.sample_rate);

            /* build the mixer table */
            if (make_mixer_table(2) != 0)
            {
                mixer_buffer = null;
                return 1;
            }

            sound_prom = Mame.memory_region(intf.region);

            /* reset all the voices */
            channel_list[0].frequency = 0;
            channel_list[0].volume = 0;
            channel_list[0].wave = new _BytePtr(sound_prom);
            channel_list[0].counter = 0;
            channel_list[1].frequency = 0;
            channel_list[1].volume = 0;
            channel_list[1].wave = new _BytePtr(sound_prom, 0x100);
            channel_list[1].counter = 0;

            return 0;
        }
示例#2
0
        public static int stream_init_multi(int channels, string[] names, int[] default_mixing_levels, int sample_rate, int param, _stream_callback_multi callback)
        {
            int channel = mixer_allocate_channels(channels, default_mixing_levels);

            stream_joined_channels[channel] = channels;

            for (int i = 0; i < channels; i++)
            {
                mixer_set_name(channel + i, names[i]);

                stream_buffer[channel + i] = new _ShortPtr(sizeof(short) * BUFFER_LEN);

                stream_sample_rate[channel + i] = sample_rate;
                stream_buffer_pos[channel + i] = 0;
                if (sample_rate!=0)
                    stream_sample_length[channel + i] = 1000000 / sample_rate;
                else
                    stream_sample_length[channel + i] = 0;
            }

            stream_param[channel] = param;
            stream_callback_multi[channel] = callback;
            set_RC_filter(channel, 0, 0, 0, 0);

            return channel;
        }
示例#3
0
        public static void overlay_draw(osd_bitmap dest, artwork overlay)
        {
            int i, j;
            int height, width;
            osd_bitmap o = null;
            int black;

            o = overlay._artwork;
            height = overlay._artwork.height;
            width = overlay._artwork.width;
            black = Machine.pens[0];

            if (dest.depth == 8)
            {
                _BytePtr dst, ovr;

                for (j = 0; j < height; j++)
                {
                    dst = new _BytePtr(dest.line[j]);
                    ovr = new _BytePtr(o.line[j]);
                    for (i = 0; i < width; i++)
                    {
                        if (dst[0] != black)
                            dst[0] = ovr[0];
                        dst.offset++;
                        ovr.offset++;
                    }
                }
            }
            else
            {
                _ShortPtr dst, ovr;

                for (j = 0; j < height; j++)
                {
                    dst = new _ShortPtr(dest.line[j]);
                    ovr = new _ShortPtr(o.line[j]);
                    for (i = 0; i < width; i++)
                    {
                        if (dst.read16(0) != black)
                            dst.write16(0, ovr.read16(0));
                        dst.offset += 2;
                        ovr.offset += 2;
                    }
                }
            }
        }
示例#4
0
        public static int stream_init(string name, int default_mixing_level, int sample_rate, int param, _stream_callback callback)
        {
            int channel = mixer_allocate_channel(default_mixing_level);

            stream_joined_channels[channel] = 1;

            mixer_set_name(channel, name);

            stream_buffer[channel] = new _ShortPtr(sizeof(short) * BUFFER_LEN);

            stream_sample_rate[channel] = sample_rate;
            stream_buffer_pos[channel] = 0;
            if (sample_rate != 0)
                stream_sample_length[channel] = 1000000 / sample_rate;
            else
                stream_sample_length[channel] = 0;
            stream_param[channel] = param;
            stream_callback[channel] = callback;
            set_RC_filter(channel, 0, 0, 0, 0);

            return channel;
        }
示例#5
0
        static int make_mixer_table(int voices)
        {
            int count = voices * 128;
            int i;
            int gain = 16;

            /* allocate memory */
            mixer_table = new _ShortPtr(256 * voices * sizeof(short));

            /* find the middle of the table */
            mixer_lookup = new _ShortPtr(mixer_table, (128 * voices) * 2);

            /* fill in the table - 16 bit case */
            for (i = 0; i < count; i++)
            {
                int val = i * gain * 16 / voices;
                if (val > 32767) val = 32767;
                mixer_lookup.write16(i, (ushort)val);
                mixer_lookup.write16(-i, (ushort)-val);
            }

            return 0;
        }
示例#6
0
        static void generate_adpcm(ADPCMVoice voice, _ShortPtr buffer, int samples)
        {
            /* if this voice is active */
            if (voice.playing != 0)
            {
                _BytePtr _base = voice._base;
                int sample = (int)voice.sample;
                int signal = (int)voice.signal;
                int count = (int)voice.count;
                int step = (int)voice.step;
                int val;

                /* loop while we still have samples to generate */
                while (samples != 0)
                {
                    /* compute the new amplitude and update the current step */
                    val = _base[sample / 2] >> (((sample & 1) << 2) ^ 4);
                    signal += diff_lookup[step * 16 + (val & 15)];

                    /* clamp to the maximum */
                    if (signal > 2047)
                        signal = 2047;
                    else if (signal < -2048)
                        signal = -2048;

                    /* adjust the step size and clamp */
                    step += index_shift[val & 7];
                    if (step > 48)
                        step = 48;
                    else if (step < 0)
                        step = 0;

                    /* output to the buffer, scaling by the volume */
                    buffer.write16(0, (ushort)(signal * voice.volume / 16));
                    buffer.offset += 2;
                    samples--;

                    /* next! */
                    if (++sample > count)
                    {
                        voice.playing = 0;
                        break;
                    }
                }

                /* update the parameters */
                voice.sample = (uint)sample;
                voice.signal = (uint)signal;
                voice.step = (uint)step;
            }

            /* fill the rest with silence */
            while (samples-- != 0)
            {
                buffer.write16(0, 0);
                buffer.offset += 2;
            }
        }
示例#7
0
        public static void adpcm_update(int num, _ShortPtr buffer, int length)
        {
            ADPCMVoice voice = _adpcm[num];
            _ShortPtr sample_data = new _ShortPtr(MAX_SAMPLE_CHUNK * 2), curr_data = new _ShortPtr(sample_data);
            short prev = voice.last_sample, curr = voice.curr_sample;
            uint final_pos;
            uint new_samples;

            /* finish off the current sample */
            if (voice.source_pos > 0)
            {
                /* interpolate */
                while (length > 0 && voice.source_pos < FRAC_ONE)
                {
                    buffer.write16(0, (ushort)((((int)prev * (FRAC_ONE - voice.source_pos)) + ((int)curr * voice.source_pos)) >> FRAC_BITS));
                    buffer.offset += 2;
                    voice.source_pos += voice.source_step;
                    length--;
                }

                /* if we're over, continue; otherwise, we're done */
                if (voice.source_pos >= FRAC_ONE)
                    voice.source_pos -= FRAC_ONE;
                else
                    return;
            }

            /* compute how many new samples we need */
            final_pos = (uint)(voice.source_pos + length * voice.source_step);
            new_samples = (final_pos + FRAC_ONE - 1) >> FRAC_BITS;
            if (new_samples > MAX_SAMPLE_CHUNK)
                new_samples = MAX_SAMPLE_CHUNK;

            /* generate them into our buffer */
            generate_adpcm(voice, sample_data, (int)new_samples);
            prev = curr;
            curr = (short)curr_data.read16(0); curr_data.offset += 2;

            /* then sample-rate convert with linear interpolation */
            while (length > 0)
            {
                /* interpolate */
                while (length > 0 && voice.source_pos < FRAC_ONE)
                {
                    buffer.write16(0, (ushort)((((int)prev * (FRAC_ONE - voice.source_pos)) + ((int)curr * voice.source_pos)) >> FRAC_BITS));
                    buffer.offset += 2;
                    voice.source_pos += voice.source_step;
                    length--;
                }

                /* if we're over, grab the next samples */
                if (voice.source_pos >= FRAC_ONE)
                {
                    voice.source_pos -= FRAC_ONE;
                    prev = curr;
                    curr = (short)curr_data.read16(0); curr_data.offset += 2;
                }
            }

            /* remember the last samples */
            voice.last_sample = prev;
            voice.curr_sample = curr;
        }
示例#8
0
 void namco_update_stereo(int ch, _ShortPtr[] buffer, int length)
 {
     throw new Exception();
 }
示例#9
0
        public static void stream_update(int channel, int min_interval)
        {
            if (Machine.sample_rate == 0 || stream_buffer[channel] == null)
                return;

            /* get current position based on the timer */
            int newpos = sound_scalebufferpos(mixer_need_samples_this_frame(channel, stream_sample_rate[channel]));//SAMPLES_THIS_FRAME(channel));

            int buflen = newpos - stream_buffer_pos[channel];

            if (buflen * stream_sample_length[channel] > min_interval)
            {
                if (stream_joined_channels[channel] > 1)
                {
                    _ShortPtr[] buf = new _ShortPtr[MIXER_MAX_CHANNELS];

                    for (int i = 0; i < stream_joined_channels[channel]; i++)
                        buf[i] = new _ShortPtr(stream_buffer[channel + i], stream_buffer_pos[channel + i] * sizeof(short));

                    stream_callback_multi[channel](stream_param[channel], buf, buflen);

                    for (int i = 0; i < stream_joined_channels[channel]; i++)
                        stream_buffer_pos[channel + i] += buflen;
                }
                else
                {
                    _ShortPtr buf = new _ShortPtr(stream_buffer[channel], stream_buffer_pos[channel] * sizeof(short));

                    stream_callback[channel](stream_param[channel], buf, buflen);

                    stream_buffer_pos[channel] += buflen;
                }
            }
        }
示例#10
0
        static void blockmove_opaque16(_BytePtr srcdata, int srcwidth, int srcheight, int srcmodulo, _ShortPtr dstdata, int dstmodulo, UShortSubArray paldata)
        {
            //blockmove_opaque8(srcdata, srcwidth, srcheight, srcmodulo, (_BytePtr)dstdata, dstmodulo, paldata);
            //return;
            int end;
            srcmodulo -= srcwidth;
            dstmodulo -= srcwidth;
            while (srcheight != 0)
            {
                end = dstdata.offset + srcwidth;
                while (dstdata.offset <= end - 8)
                {
                    dstdata.write16(0, paldata[srcdata[0]]);
                    dstdata.write16(1, paldata[srcdata[1]]);
                    dstdata.write16(2, paldata[srcdata[2]]);
                    dstdata.write16(3, paldata[srcdata[3]]);
                    dstdata.write16(4, paldata[srcdata[4]]);
                    dstdata.write16(5, paldata[srcdata[5]]);
                    dstdata.write16(6, paldata[srcdata[6]]);
                    dstdata.write16(7, paldata[srcdata[7]]);
                    dstdata.offset += 8 * 2;
                    srcdata.offset++;
                }
                while (dstdata.offset < end)
                {
                    dstdata.write16(0, paldata[srcdata[0]]);
                    srcdata.offset++;
                    dstdata.offset += 2;
                }
                srcdata.inc(srcmodulo);
                dstdata.inc(dstmodulo);
                srcheight--;
            }

        }
示例#11
0
 static void blockmove_transmask16(_BytePtr srcdata, int srcwidth, int srcheight, int srcmodulo, _ShortPtr dstdata, int dstmodulo, UShortSubArray paldata, int transmask) { throw new Exception(); }
示例#12
0
        public static void tms5220_update(int ch, _ShortPtr buffer, int length)
        {
            short[] sample_data = new short[MAX_SAMPLE_CHUNK];
            ShortSubArray curr_data = new ShortSubArray(sample_data);
            short prev = last_sample, curr = curr_sample;
            uint final_pos;
            uint new_samples;

            /* finish off the current sample */
            if (source_pos > 0)
            {
                /* interpolate */
                while (length > 0 && source_pos < FRAC_ONE)
                {
                    buffer.write16(0, (ushort)((((int)prev * (FRAC_ONE - source_pos)) + ((int)curr * source_pos)) >> FRAC_BITS));
                    buffer.offset += 2;
                    source_pos += source_step;
                    length--;
                }

                /* if we're over, continue; otherwise, we're done */
                if (source_pos >= FRAC_ONE)
                    source_pos -= FRAC_ONE;
                else
                    return;
            }

            /* compute how many new samples we need */
            final_pos = (uint)(source_pos + length * source_step);
            new_samples = (final_pos + FRAC_ONE - 1) >> FRAC_BITS;
            if (new_samples > MAX_SAMPLE_CHUNK)
                new_samples = MAX_SAMPLE_CHUNK;

            /* generate them into our buffer */
            tms5220_process(sample_data, new_samples);
            prev = curr;
            curr = curr_data[0]; curr_data.offset++;

            /* then sample-rate convert with linear interpolation */
            while (length > 0)
            {
                /* interpolate */
                while (length > 0 && source_pos < FRAC_ONE)
                {
                    buffer.write16(0, (ushort)((((int)prev * (FRAC_ONE - source_pos)) + ((int)curr * source_pos)) >> FRAC_BITS));
                    source_pos += source_step;
                    length--;
                }

                /* if we're over, grab the next samples */
                if (source_pos >= FRAC_ONE)
                {
                    source_pos -= FRAC_ONE;
                    prev = curr;
                    curr = curr_data[0]; curr_data.offset++;
                }
            }

            /* remember the last samples */
            last_sample = prev;
            curr_sample = curr;
        }
示例#13
0
        public static void drawgfxzoom(osd_bitmap dest_bmp, GfxElement gfx, uint code, uint color, bool flipx, bool flipy, int sx, int sy, rectangle clip, int transparency, int transparent_color, int scalex, int scaley)
        {
            FuncDict["drawgfxzoom"] = "drawgfxzoom";
            rectangle myclip = new rectangle();


            /* only support TRANSPARENCY_PEN and TRANSPARENCY_COLOR */
            if (transparency != TRANSPARENCY_PEN && transparency != TRANSPARENCY_COLOR)
                return;

            if (transparency == TRANSPARENCY_COLOR)
                transparent_color = Machine.pens[transparent_color];


            /*
            scalex and scaley are 16.16 fixed point numbers
            1<<15 : shrink to 50%
            1<<16 : uniform scale
            1<<17 : double to 200%
            */


            if ((Machine.orientation & ORIENTATION_SWAP_XY) != 0)
            {
                int temp;

                temp = sx;
                sx = sy;
                sy = temp;

                var tempb = flipx;
                flipx = flipy;
                flipy = tempb;

                temp = scalex;
                scalex = scaley;
                scaley = temp;

                if (clip != null)
                {
                    /* clip and myclip might be the same, so we need a temporary storage */
                    temp = clip.min_x;
                    myclip.min_x = clip.min_y;
                    myclip.min_y = temp;
                    temp = clip.max_x;
                    myclip.max_x = clip.max_y;
                    myclip.max_y = temp;
                    clip = myclip;
                }
            }
            if ((Machine.orientation & ORIENTATION_FLIP_X) != 0)
            {
                sx = dest_bmp.width - ((gfx.width * scalex + 0x7fff) >> 16) - sx;
                if (clip != null)
                {
                    int temp;


                    /* clip and myclip might be the same, so we need a temporary storage */
                    temp = clip.min_x;
                    myclip.min_x = dest_bmp.width - 1 - clip.max_x;
                    myclip.max_x = dest_bmp.width - 1 - temp;
                    myclip.min_y = clip.min_y;
                    myclip.max_y = clip.max_y;
                    clip = myclip;
                }
#if !PREROTATE_GFX
                flipx = !flipx;
#endif
            }
            if ((Machine.orientation & ORIENTATION_FLIP_Y) != 0)
            {
                sy = dest_bmp.height - ((gfx.height * scaley + 0x7fff) >> 16) - sy;
                if (clip != null)
                {
                    int temp;


                    myclip.min_x = clip.min_x;
                    myclip.max_x = clip.max_x;
                    /* clip and myclip might be the same, so we need a temporary storage */
                    temp = clip.min_y;
                    myclip.min_y = dest_bmp.height - 1 - clip.max_y;
                    myclip.max_y = dest_bmp.height - 1 - temp;
                    clip = myclip;
                }
#if !PREROTATE_GFX
                flipy = !flipy;
#endif
            }

            /* KW 991012 -- Added code to force clip to bitmap boundary */
            if (clip != null)
            {
                myclip.min_x = clip.min_x;
                myclip.max_x = clip.max_x;
                myclip.min_y = clip.min_y;
                myclip.max_y = clip.max_y;

                if (myclip.min_x < 0) myclip.min_x = 0;
                if (myclip.max_x >= dest_bmp.width) myclip.max_x = dest_bmp.width - 1;
                if (myclip.min_y < 0) myclip.min_y = 0;
                if (myclip.max_y >= dest_bmp.height) myclip.max_y = dest_bmp.height - 1;

                clip = myclip;
            }


            /* ASG 980209 -- added 16-bit version */
            if (dest_bmp.depth != 16)
            {
                if (gfx != null && gfx.colortable != null)
                {
                    UShortSubArray pal = new UShortSubArray(gfx.colortable, (int)(gfx.color_granularity * (color % gfx.total_colors))); /* ASG 980209 */
                    int source_base = (int)((code % gfx.total_elements) * gfx.height);

                    int sprite_screen_height = (scaley * gfx.height + 0x8000) >> 16;
                    int sprite_screen_width = (scalex * gfx.width + 0x8000) >> 16;

                    /* compute sprite increment per screen pixel */
                    int dx = (gfx.width << 16) / sprite_screen_width;
                    int dy = (gfx.height << 16) / sprite_screen_height;

                    int ex = sx + sprite_screen_width;
                    int ey = sy + sprite_screen_height;

                    int x_index_base;
                    int y_index;

                    if (flipx)
                    {
                        x_index_base = (sprite_screen_width - 1) * dx;
                        dx = -dx;
                    }
                    else
                    {
                        x_index_base = 0;
                    }

                    if (flipy)
                    {
                        y_index = (sprite_screen_height - 1) * dy;
                        dy = -dy;
                    }
                    else
                    {
                        y_index = 0;
                    }

                    if (clip != null)
                    {
                        if (sx < clip.min_x)
                        { /* clip left */
                            int pixels = clip.min_x - sx;
                            sx += pixels;
                            x_index_base += pixels * dx;
                        }
                        if (sy < clip.min_y)
                        { /* clip top */
                            int pixels = clip.min_y - sy;
                            sy += pixels;
                            y_index += pixels * dy;
                        }
                        /* NS 980211 - fixed incorrect clipping */
                        if (ex > clip.max_x + 1)
                        { /* clip right */
                            int pixels = ex - clip.max_x - 1;
                            ex -= pixels;
                        }
                        if (ey > clip.max_y + 1)
                        { /* clip bottom */
                            int pixels = ey - clip.max_y - 1;
                            ey -= pixels;
                        }
                    }

                    if (ex > sx)
                    { /* skip if inner loop doesn't draw anything */
                        int y;

                        /* case 1: TRANSPARENCY_PEN */
                        if (transparency == TRANSPARENCY_PEN)
                        {
                            for (y = sy; y < ey; y++)
                            {
                                _BytePtr source = new _BytePtr(gfx.gfxdata, (source_base + (y_index >> 16)) * gfx.line_modulo);
                                _BytePtr dest = dest_bmp.line[y];

                                int x, x_index = x_index_base;
                                for (x = sx; x < ex; x++)
                                {
                                    int c = source[x_index >> 16];
                                    if (c != transparent_color) dest[x] = (byte)pal[c];
                                    x_index += dx;
                                }

                                y_index += dy;
                            }
                        }

                        /* case 2: TRANSPARENCY_COLOR */
                        else if (transparency == TRANSPARENCY_COLOR)
                        {
                            for (y = sy; y < ey; y++)
                            {
                                _BytePtr source = new _BytePtr(gfx.gfxdata, (source_base + (y_index >> 16)) * gfx.line_modulo);
                                _BytePtr dest = dest_bmp.line[y];

                                int x, x_index = x_index_base;
                                for (x = sx; x < ex; x++)
                                {
                                    int c = pal[source[x_index >> 16]];
                                    if (c != transparent_color) dest[x] = (byte)c;
                                    x_index += dx;
                                }

                                y_index += dy;
                            }
                        }
                    }

                }
            }

            /* ASG 980209 -- new 16-bit part */
            else
            {
                if (gfx != null && gfx.colortable != null)
                {
                    UShortSubArray pal = new UShortSubArray(gfx.colortable, (int)(gfx.color_granularity * (color % gfx.total_colors))); /* ASG 980209 */
                    int source_base = (int)((code % gfx.total_elements) * gfx.height);

                    int sprite_screen_height = (scaley * gfx.height + 0x8000) >> 16;
                    int sprite_screen_width = (scalex * gfx.width + 0x8000) >> 16;

                    /* compute sprite increment per screen pixel */
                    int dx = (gfx.width << 16) / sprite_screen_width;
                    int dy = (gfx.height << 16) / sprite_screen_height;

                    int ex = sx + sprite_screen_width;
                    int ey = sy + sprite_screen_height;

                    int x_index_base;
                    int y_index;

                    if (flipx)
                    {
                        x_index_base = (sprite_screen_width - 1) * dx;
                        dx = -dx;
                    }
                    else
                    {
                        x_index_base = 0;
                    }

                    if (flipy)
                    {
                        y_index = (sprite_screen_height - 1) * dy;
                        dy = -dy;
                    }
                    else
                    {
                        y_index = 0;
                    }

                    if (clip != null)
                    {
                        if (sx < clip.min_x)
                        { /* clip left */
                            int pixels = clip.min_x - sx;
                            sx += pixels;
                            x_index_base += pixels * dx;
                        }
                        if (sy < clip.min_y)
                        { /* clip top */
                            int pixels = clip.min_y - sy;
                            sy += pixels;
                            y_index += pixels * dy;
                        }
                        /* NS 980211 - fixed incorrect clipping */
                        if (ex > clip.max_x + 1)
                        { /* clip right */
                            int pixels = ex - clip.max_x - 1;
                            ex -= pixels;
                        }
                        if (ey > clip.max_y + 1)
                        { /* clip bottom */
                            int pixels = ey - clip.max_y - 1;
                            ey -= pixels;
                        }
                    }

                    if (ex > sx)
                    { /* skip if inner loop doesn't draw anything */
                        int y;

                        /* case 1: TRANSPARENCY_PEN */
                        if (transparency == TRANSPARENCY_PEN)
                        {
                            for (y = sy; y < ey; y++)
                            {
                                _BytePtr source = new _BytePtr(gfx.gfxdata, (source_base + (y_index >> 16)) * gfx.line_modulo);
                                _ShortPtr dest = new _ShortPtr(dest_bmp.line[y]);

                                int x, x_index = x_index_base;
                                for (x = sx; x < ex; x++)
                                {
                                    int c = source[x_index >> 16];
                                    if (c != transparent_color) dest[x] = (byte)pal[c];
                                    x_index += dx;
                                }

                                y_index += dy;
                            }
                        }

                        /* case 2: TRANSPARENCY_COLOR */
                        else if (transparency == TRANSPARENCY_COLOR)
                        {
                            for (y = sy; y < ey; y++)
                            {
                                _BytePtr source = new _BytePtr(gfx.gfxdata, (source_base + (y_index >> 16)) * gfx.line_modulo);
                                _ShortPtr dest = new _ShortPtr(dest_bmp.line[y]);

                                int x, x_index = x_index_base;
                                for (x = sx; x < ex; x++)
                                {
                                    int c = pal[source[x_index >> 16]];
                                    if (c != transparent_color) dest.write16(x, (ushort)c);
                                    x_index += dx;
                                }

                                y_index += dy;
                            }
                        }
                    }
                }
            }
        }
示例#14
0
 static void SEGAPCMUpdate(int num, _ShortPtr[] buffer, int length)
 {
     throw new Exception();
 }
示例#15
0
        static void draw_tile(osd_bitmap pixmap, int col, int row, int tile_width, int tile_height, _BytePtr pendata, UShortSubArray paldata, byte flags)
        {
            int x, sx = tile_width * col;
            int sy, y1, y2, dy;
            int pi = 0;
            if (Machine.scrbitmap.depth == 16)
            {
                if ((flags & TILE_FLIPY) != 0)
                {
                    y1 = tile_height * row + tile_height - 1;
                    y2 = y1 - tile_height;
                    dy = -1;
                }
                else
                {
                    y1 = tile_height * row;
                    y2 = y1 + tile_height;
                    dy = 1;
                }

                if ((flags & TILE_FLIPX) != 0)
                {
                    tile_width--;
                    for (sy = y1; sy != y2; sy += dy)
                    {
                        _ShortPtr dest = new _ShortPtr(pixmap.line[sy], sx);
                        for (x = tile_width; x >= 0; x--)
                        {
                            dest.write16(x, paldata[pendata[pi++]]);
                        }
                    }
                }
                else
                {
                    for (sy = y1; sy != y2; sy += dy)
                    {
                        _ShortPtr dest = new _ShortPtr(pixmap.line[sy], sx);
                        for (x = 0; x < tile_width; x++)
                        {
                            dest.write16(x, paldata[pendata[pi++]]);
                        }
                    }
                }
            }
            else
            {
                if ((flags & TILE_FLIPY) != 0)
                {
                    y1 = tile_height * row + tile_height - 1;
                    y2 = y1 - tile_height;
                    dy = -1;
                }
                else
                {
                    y1 = tile_height * row;
                    y2 = y1 + tile_height;
                    dy = 1;
                }

                if ((flags & TILE_FLIPX) != 0)
                {
                    tile_width--;
                    for (sy = y1; sy != y2; sy += dy)
                    {
                        _BytePtr dest = new _BytePtr(pixmap.line[sy], sx);
                        for (x = tile_width; x >= 0; x--)
                        { dest[x] = (byte)paldata[pendata[pi++]]; }
                    }
                }
                else
                {
                    for (sy = y1; sy != y2; sy += dy)
                    {
                        _BytePtr dest = new _BytePtr(pixmap.line[sy], sx);
                        for (x = 0; x < tile_width; x++)
                        { dest[x] = (byte)paldata[pendata[pi++]]; }
                    }
                }
            }
        }
示例#16
0
        public static void YM3812UpdateOne(FM_OPL OPL, _ShortPtr buffer, int length)
        {
            int i;
            int data;
            _ShortPtr buf = buffer;
            uint amsCnt = (uint)OPL.amsCnt;
            uint vibCnt = (uint)OPL.vibCnt;
            byte rythm = (byte)(OPL.rythm & 0x20);
            OPL_CH CH;
            int R_CH;

            if ((object)OPL != cur_chip)
            {
                cur_chip = OPL;
                /* channel pointers */
                S_CH = OPL.P_CH;
                E_CH = 9;// S_CH[9];
                /* rythm slot */
                SLOT7_1 = S_CH[7].SLOT[SLOT1];
                SLOT7_2 = S_CH[7].SLOT[SLOT2];
                SLOT8_1 = S_CH[8].SLOT[SLOT1];
                SLOT8_2 = S_CH[8].SLOT[SLOT2];
                /* LFO state */
                amsIncr = OPL.amsIncr;
                vibIncr = OPL.vibIncr;
                ams_table = OPL.ams_table;
                vib_table = OPL.vib_table;
            }
            R_CH = rythm != 0 ? 6 : E_CH;
            for (i = 0; i < length; i++)
            {
                /*            channel A         channel B         channel C      */
                /* LFO */
                ams = ams_table[(int)((amsCnt += (uint)amsIncr) >> AMS_SHIFT)];
                vib = vib_table[(int)((vibCnt += (uint)vibIncr) >> VIB_SHIFT)];
                outd[0] = 0;
                /* FM part */
                for (int k = 0; k != R_CH; k++)
                {
                    CH = S_CH[k];
                    //for(CH=S_CH ; CH < R_CH ; CH++)
                    OPL_CALC_CH(CH);
                }
                /* Rythn part */
                if (rythm != 0)
                    OPL_CALC_RH(S_CH);
                /* limit check */
                data = Limit(outd[0], OPL_MAXOUT, OPL_MINOUT);
                /* store to sound buffer */
                buf.write16(i, (ushort)(data >> OPL_OUTSB));
            }

            OPL.amsCnt = (int)amsCnt;
            OPL.vibCnt = (int)vibCnt;
        }
示例#17
0
        public static void YM2203UpdateOne(int num, _ShortPtr buffer, int length)
        {
            YM2203 F2203 = (FM2203[num]);
            FM_OPN OPN = (FM2203[num].OPN);
            int i;
            FM_CH ch;
            _ShortPtr buf = new _ShortPtr(buffer);

            cur_chip = F2203;
            State = F2203.OPN.ST;
            cch[0] = F2203.CH[0];
            cch[1] = F2203.CH[1];
            cch[2] = F2203.CH[2];
#if FM_LFO_SUPPORT
            /* LFO */
            lfo_amd = 0;
            lfo_pmd = 0;
#endif
            /* frequency counter channel A */
            CALC_FCOUNT(cch[0]);
            /* frequency counter channel B */
            CALC_FCOUNT(cch[1]);
            /* frequency counter channel C */
            if ((State.mode & 0xc0) != 0)
            {
                /* 3SLOT MODE */
                if (cch[2].SLOT[SLOT1].Incr == unchecked((uint)-1))
                {
                    /* 3 slot mode */
                    CALC_FCSLOT(cch[2].SLOT[SLOT1], (int)OPN.SL3.fc[1], OPN.SL3.kcode[1]);
                    CALC_FCSLOT(cch[2].SLOT[SLOT2], (int)OPN.SL3.fc[2], OPN.SL3.kcode[2]);
                    CALC_FCSLOT(cch[2].SLOT[SLOT3], (int)OPN.SL3.fc[0], OPN.SL3.kcode[0]);
                    CALC_FCSLOT(cch[2].SLOT[SLOT4], (int)cch[2].fc, cch[2].kcode);
                }
            }
            else CALC_FCOUNT(cch[2]);

            for (i = 0; i < length; i++)
            {
                /*            channel A         channel B         channel C      */
                out_ch[OUTD_CENTER] = 0;
                /* calcrate FM */
                //for( ch=cch[0] ; ch <= cch[2] ; ch++)
                for (int kk = 0; kk < 2; kk++)

                    FM_CALC_CH(cch[kk]);
                /* limit check */
                Limit(ref out_ch[OUTD_CENTER], FM_MAXOUT, FM_MINOUT);
                /* store to sound buffer */
                buf.write16(i, (ushort)(out_ch[OUTD_CENTER] >> FM_OUTSB));
                /* timer controll */
                INTERNAL_TIMER_A(State, cch[2]);
            }
            INTERNAL_TIMER_B(State, length);
        }
示例#18
0
        public static void OPMUpdateOne(int num, _ShortPtr[] buffer, int length)
        {
            YM2151 OPM = (FMOPM[num]);
            int i;
            int amd, pmd;
            FM_CH ch;
            _ShortPtr bufL, bufR;

            /* set bufer */
            bufL = buffer[0];
            bufR = buffer[1];

            if ((object)OPM != cur_chip)
            {
                cur_chip = OPM;

                State = OPM.ST;
                /* channel pointer */
                cch[0] = OPM.CH[0];
                cch[1] = OPM.CH[1];
                cch[2] = OPM.CH[2];
                cch[3] = OPM.CH[3];
                cch[4] = OPM.CH[4];
                cch[5] = OPM.CH[5];
                cch[6] = OPM.CH[6];
                cch[7] = OPM.CH[7];
                /* ch7.op4 noise mode / step */
                NoiseIncr = OPM.NoiseIncr;
                NoiseCnt = OPM.NoiseCnt;
#if FM_LFO_SUPPORT
                /* LFO */
                LFOCnt = OPM.LFOCnt;
                //LFOIncr = OPM.LFOIncr;
                if (LFOIncr == 0) { lfo_amd = 0; lfo_pmd = 0; }
                LFO_wave = OPM.wavetype;
#endif
            }
            amd = OPM.amd;
            pmd = OPM.pmd;
            if (amd == 0 && pmd == 0)
                LFOIncr = 0;
            else
                LFOIncr = OPM.LFOIncr;

            OPM_CALC_FCOUNT(OPM, cch[0]);
            OPM_CALC_FCOUNT(OPM, cch[1]);
            OPM_CALC_FCOUNT(OPM, cch[2]);
            OPM_CALC_FCOUNT(OPM, cch[3]);
            OPM_CALC_FCOUNT(OPM, cch[4]);
            OPM_CALC_FCOUNT(OPM, cch[5]);
            OPM_CALC_FCOUNT(OPM, cch[6]);
            /* CSM check */
            OPM_CALC_FCOUNT(OPM, cch[7]);

            for (i = 0; i < length; i++)
            {
#if FM_LFO_SUPPORT
                /* LFO */
                if (LFOIncr != 0)
                {
                    int depth = LFO_wave[(int)((LFOCnt += LFOIncr) >> LFO_SHIFT)];
                    lfo_amd = (uint)(depth * amd);
                    lfo_pmd = (depth - (LFO_RATE / 127 / 2)) * pmd;
                }
#endif
                /* clear output acc. */
                out_ch[OUTD_LEFT] = out_ch[OUTD_RIGHT] = out_ch[OUTD_CENTER] = 0;
                /* calcrate channel output */
                //for(ch = cch[0] ; ch <= cch[6] ; ch++)
                for (int k = 0; k < 6; k++)
                {
                    ch = cch[k];
                    FM_CALC_CH(ch);
                    OPM_CALC_CH7(cch[7]);
                    /* buffering */
                    //FM_BUFFERING_STEREO;
#if FM_STEREO_MIX
/* stereo mixing */
{														
	/* get left & right output with clipping */			
	out_ch[OUTD_LEFT]  += out_ch[OUTD_CENTER];				
	Limit( out_ch[OUTD_LEFT] , FM_MAXOUT, FM_MINOUT );	
	out_ch[OUTD_RIGHT] += out_ch[OUTD_CENTER];				
	Limit( out_ch[OUTD_RIGHT], FM_MAXOUT, FM_MINOUT );	
	/* buffering */										
	((FMSAMPLE_MIX *)bufL)[i] = ((out_ch[OUTD_LEFT]>>FM_OUTSB)<<FM_OUTPUT_BIT)|(out_ch[OUTD_RIGHT]>>FM_OUTSB); 
}
#else
                    /* stereo separate */
                    {
                        /* get left & right output with clipping */
                        out_ch[OUTD_LEFT] += out_ch[OUTD_CENTER];
                        Limit(ref  out_ch[OUTD_LEFT], FM_MAXOUT, FM_MINOUT);
                        out_ch[OUTD_RIGHT] += out_ch[OUTD_CENTER];
                        Limit(ref  out_ch[OUTD_RIGHT], FM_MAXOUT, FM_MINOUT);
                        /* buffering */
                        bufL.write16(i, (ushort)(out_ch[OUTD_LEFT] >> FM_OUTSB));
                        bufR.write16(i, (ushort)(out_ch[OUTD_RIGHT] >> FM_OUTSB));
                    }
#endif
                    /* timer A controll */
                    INTERNAL_TIMER_A(State, cch[7]);
                }
                INTERNAL_TIMER_B(State, length);
                OPM.NoiseCnt = NoiseCnt;
#if FM_LFO_SUPPORT
                OPM.LFOCnt = LFOCnt;
#endif
            }

        }
示例#19
0
        public void streams_sh_update()
        {
            if (Machine.sample_rate == 0) return;

            /* update all the output buffers */
            for (int channel = 0; channel < MIXER_MAX_CHANNELS; channel += stream_joined_channels[channel])
            {
                if (stream_buffer[channel] != null)
                {
                    int newpos = mixer_need_samples_this_frame(channel, stream_sample_rate[(channel)]);

                    int buflen = newpos - stream_buffer_pos[channel];

                    if (stream_joined_channels[channel] > 1)
                    {
                        _ShortPtr[] buf = new _ShortPtr[MIXER_MAX_CHANNELS];

                        if (buflen > 0)
                        {
                            for (int i = 0; i < stream_joined_channels[channel]; i++)
                                buf[i] = new _ShortPtr(stream_buffer[channel + i], stream_buffer_pos[channel + i]*sizeof(short));

                            stream_callback_multi[channel](stream_param[channel], buf, buflen);
                        }

                        for (int i = 0; i < stream_joined_channels[channel]; i++)
                            stream_buffer_pos[channel + i] = 0;

                        for (int i = 0; i < stream_joined_channels[channel]; i++)
                            apply_RC_filter(channel + i, stream_buffer[channel + i], buflen, stream_sample_rate[channel + i]);
                    }
                    else
                    {
                        if (buflen > 0)
                        {
                            _ShortPtr buf= new _ShortPtr(stream_buffer[channel], stream_buffer_pos[channel]*sizeof(short));

                            stream_callback[channel](stream_param[channel], buf, buflen);
                        }

                        stream_buffer_pos[channel] = 0;

                        apply_RC_filter(channel, stream_buffer[channel], buflen, stream_sample_rate[channel]);
                    }
                }
            }

            for (int channel = 0; channel < MIXER_MAX_CHANNELS; channel += stream_joined_channels[channel])
            {
                if (stream_buffer[channel] != null)
                {
                    for (int i = 0; i < stream_joined_channels[channel]; i++)
                        mixer_play_streamed_sample_16(channel + i,
                                stream_buffer[channel + i], sizeof(short) *
                                mixer_need_samples_this_frame((channel + i), stream_sample_rate[(channel + i)]),
                                stream_sample_rate[channel]);
                }
            }
        }
示例#20
0
 static void YM3812UpdateHandler(int n, _ShortPtr buf, int length)
 { 
     FMOPL.YM3812UpdateOne(F3812[n], buf, length); 
 }
示例#21
0
        public static void fillbitmap(osd_bitmap dest, int pen, rectangle clip)
        {
            FuncDict["fillbitmap"] = "fillbitmap";
            rectangle myclip = new rectangle();

            if ((Machine.orientation & ORIENTATION_SWAP_XY) != 0)
            {
                if (clip != null)
                {
                    myclip.min_x = clip.min_y;
                    myclip.max_x = clip.max_y;
                    myclip.min_y = clip.min_x;
                    myclip.max_y = clip.max_x;
                    clip = myclip;
                }
            }
            if ((Machine.orientation & ORIENTATION_FLIP_X) != 0)
            {
                if (clip != null)
                {
                    int temp = clip.min_x;
                    myclip.min_x = dest.width - 1 - clip.max_x;
                    myclip.max_x = dest.width - 1 - temp;
                    myclip.min_y = clip.min_y;
                    myclip.max_y = clip.max_y;
                    clip = myclip;
                }
            }
            if ((Machine.orientation & ORIENTATION_FLIP_Y) != 0)
            {
                if (clip != null)
                {
                    myclip.min_x = clip.min_x;
                    myclip.max_x = clip.max_x;
                    int temp = clip.min_y;
                    myclip.min_y = dest.height - 1 - clip.max_y;
                    myclip.max_y = dest.height - 1 - temp;
                    clip = myclip;
                }
            }

            int sx = 0;
            int ex = dest.width - 1;
            int sy = 0;
            int ey = dest.height - 1;

            if (clip != null && sx < clip.min_x) sx = clip.min_x;
            if (clip != null && ex > clip.max_x) ex = clip.max_x;
            if (sx > ex) return;
            if (clip != null && sy < clip.min_y) sy = clip.min_y;
            if (clip != null && ey > clip.max_y) ey = clip.max_y;
            if (sy > ey) return;

            osd_mark_dirty(sx, sy, ex, ey, 0);	/* ASG 971011 */

            /* ASG 980211 */
            if (dest.depth == 16)
            {
                if ((pen >> 8) == (pen & 0xff))
                {
                    for (int y = sy; y <= ey; y++)
                    {
                        for (int k = 0; k < (ex - sx + 1) * 2; k++)
                            dest.line[y][sx * 2 + k] = (byte)(pen & 0xff);
                    }
                    //memset(&dest.line[y][sx*2],pen&0xff,(ex-sx+1)*2);
                }
                else
                {
                    _ShortPtr sp = new _ShortPtr(dest.line[sy]);
                    int x;

                    for (x = sx; x <= ex; x++)
                        sp.write16(x, (ushort)pen);
                    sp.offset += sx * 2;
                    for (int y = sy + 1; y <= ey; y++)
                    {
                        Buffer.BlockCopy(sp.buffer, sp.offset, dest.line[y].buffer, sx * 2, (ex - sx + 1) * 2);
                    }
                    //memcpy(&dest.line[y][sx*2],sp,(ex-sx+1)*2);
                }
            }
            else
            {
                for (int y = sy; y <= ey; y++)
                {
                    for (int k = 0; k < ex - sx + 1; k++) dest.line[y][sx + k] = (byte)pen;
                }
            }
        }
示例#22
0
 static void blockmove_opaque_noremap_flipx16(_ShortPtr srcdata, int srcwidth, int srcheight, int srcmodulo, _ShortPtr dstdata, int dstmodulo) { throw new Exception(); }
示例#23
0
 static void drawgfx_core16(osd_bitmap dest, GfxElement gfx, uint code, uint color, bool flipx, bool flipy, int sx, int sy, rectangle clip, int transparency, int transparent_color)
 {
     int ox; int oy; int ex; int ey;
     /* check bounds */
     ox = sx; oy = sy;
     ex = sx + gfx.width - 1; if (sx < 0) sx = 0;
     if (clip != null && sx < clip.min_x) sx = clip.min_x;
     if (ex >= dest.width) ex = dest.width - 1;
     if (clip != null && ex > clip.max_x) ex = clip.max_x;
     if (sx > ex) return; ey = sy + gfx.height - 1;
     if (sy < 0) sy = 0;
     if (clip != null && sy < clip.min_y) sy = clip.min_y;
     if (ey >= dest.height) ey = dest.height - 1;
     if (clip != null && ey > clip.max_y) ey = clip.max_y;
     if (sy > ey) return; osd_mark_dirty(sx, sy, ex, ey, 0); /* ASG 971011 */
     {
         _BytePtr sd = new _BytePtr(gfx.gfxdata, (int)(code * gfx.char_modulo)); /* source data */
         int sw = ex - sx + 1; /* source width */
         int sh = ey - sy + 1; /* source height */
         int sm = gfx.line_modulo; /* source modulo */
         _ShortPtr dd = new _ShortPtr(dest.line[sy], sx); /* dest data */
         int dm = dest.line[1].offset - dest.line[0].offset; /* dest modulo */
         UShortSubArray paldata = new UShortSubArray(gfx.colortable, (int)((gfx.color_granularity * color)));
         if (flipx)
         {
             sd.offset += gfx.width - 1 - (sx - ox);
         }
         else
             sd.offset += (sx - ox); if (flipy)
         {
             sd.offset += sm * (gfx.height - 1 - (sy - oy));
             sm = -sm;
         }
         else
             sd.offset += sm * (sy - oy); switch (transparency)
         {
             case TRANSPARENCY_NONE:
                 if (flipx) blockmove_opaque_flipx16(sd, sw, sh, sm, dd, dm, paldata);
                 else
                     blockmove_opaque16(sd, sw, sh, sm, dd, dm, paldata);
                 break;
             case TRANSPARENCY_PEN:
                 if (flipx)
                     blockmove_transpen_flipx16(sd, sw, sh, sm, dd, dm, paldata, transparent_color);
                 else
                     blockmove_transpen16(sd, sw, sh, sm, dd, dm, paldata, transparent_color);
                 break;
             case TRANSPARENCY_PENS: if (flipx)
                     blockmove_transmask_flipx16(sd, sw, sh, sm, dd, dm, paldata, transparent_color);
                 else
                     blockmove_transmask16(sd, sw, sh, sm, dd, dm, paldata, transparent_color);
                 break;
             case TRANSPARENCY_COLOR: if (flipx)
                     blockmove_transcolor_flipx16(sd, sw, sh, sm, dd, dm, paldata, transparent_color);
                 else
                     blockmove_transcolor16(sd, sw, sh, sm, dd, dm, paldata, transparent_color);
                 break;
             case TRANSPARENCY_THROUGH: if (flipx)
                     blockmove_transthrough_flipx16(sd, sw, sh, sm, dd, dm, paldata, transparent_color);
                 else
                     blockmove_transthrough16(sd, sw, sh, sm, dd, dm, paldata, transparent_color);
                 break;
             case TRANSPARENCY_PEN_TABLE: if (flipx)
                     blockmove_pen_table_flipx16(sd, sw, sh, sm, dd, dm, paldata, transparent_color);
                 else
                     blockmove_pen_table16(sd, sw, sh, sm, dd, dm, paldata, transparent_color);
                 break;
         }
     }
 }
示例#24
0
        public override int start(xnamame036.mame.Mame.MachineSound msound)
        {
            string mono_name = "NAMCO sound";
            string[] stereo_names = { "NAMCO sound left", "NAMCO sound right" };

            Namco_interface intf = (Namco_interface)msound.sound_interface;

            namco_clock = intf.samplerate;
            sample_rate = Mame.Machine.sample_rate;

            /* get stream channels */
            if (intf.stereo)
            {
                int[] vol = new int[2];

                vol[1] = Mame.MIXER(intf.volume, Mame.MIXER_PAN_RIGHT);
                vol[0] = Mame.MIXER(intf.volume, Mame.MIXER_PAN_LEFT);
                stream = Mame.stream_init_multi(2, stereo_names, vol, intf.samplerate, 0, namco_update_stereo);
            }
            else
            {
                stream = Mame.stream_init(mono_name, intf.volume, intf.samplerate, 0, namco_update_mono);
            }

            /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
            mixer_buffer = new _ShortPtr(2 * intf.samplerate * sizeof(short) );
            mixer_buffer_2 = new _ShortPtr(mixer_buffer, intf.samplerate * sizeof(short));

            /* build the mixer table */
            make_mixer_table(intf.voices);

            /* extract globals from the interface */
            num_voices = intf.voices;
            last_channel = num_voices;

            if (intf.region == -1)
            {
                sound_prom = namco_wavedata;
                samples_per_byte = 2;	/* first 4 high bits, then low 4 bits */
            }
            else
            {
                sound_prom = Mame.memory_region(intf.region);
                samples_per_byte = 1;	/* use only low 4 bits */
            }

            /* start with sound enabled, many games don't have a sound enable register */
            sound_enable = true;

            /* reset all the voices */
            for (int i = 0; i < last_channel; i++)
            //for (voice = channel_list; voice < last_channel; voice++)
            {
                channel_list[i] = new sound_channel();
                channel_list[i].frequency = 0;
                channel_list[i].volume[0] = channel_list[i].volume[1] = 0;
                channel_list[i].wave = sound_prom;
                channel_list[i].counter = 0;
                channel_list[i].noise_sw = 0;
                channel_list[i].noise_state = 0;
                channel_list[i].noise_seed = 1;
                channel_list[i].noise_counter = 0;
            }

            return 0;
        }
示例#25
0
 static void blockmove_opaque_flipx16(_BytePtr srcdata, int srcwidth, int srcheight, int srcmodulo, _ShortPtr dstdata, int dstmodulo, UShortSubArray paldata) { throw new Exception(); }
示例#26
0
        void apply_RC_filter(int channel, _ShortPtr buf, int len, int sample_rate)
        {
            if (c[channel] == 0) return;	/* filter disabled */

            float R1 = r1[channel];
            float R2 = r2[channel];
            float R3 = r3[channel];
            float C = (float)(c[channel] * 1E-12);	/* convert pF to F */

            /* Cut Frequency = 1/(2*Pi*Req*C) */

            float Req = (R1 * (R2 + R3)) / (R1 + R2 + R3);

            int K = (int)(0x10000 * Math.Exp(-1 / (Req * C) / sample_rate));

            buf.write16(0, (ushort)(buf.read16(0) + (memory[channel] - buf.read16(0)) * K / 0x10000));

            for (int i = 1; i < len; i++)
                buf.write16(i, (ushort)(buf.read16(i) + (buf.read16(i - 1) - buf.read16(i)) * K / 0x10000));

            memory[channel] = buf.read16(len - 1);
        }
示例#27
0
 static void blockmove_pen_table_flipx16(_BytePtr srcdata, int srcwidth, int srcheight, int srcmodulo, _ShortPtr dstdata, int dstmodulo, UShortSubArray paldata, int transcolor) { throw new Exception(); }
示例#28
0
        void namco_update_mono(int ch, _ShortPtr buffer, int length)
        {
            _ShortPtr mix;

            /* if no sound, we're done */
            if (!sound_enable)
            {
                Array.Clear(buffer.buffer, buffer.offset, length*2);
                return;
            }

            /* zap the contents of the mixer buffer */
            Array.Clear(mixer_buffer.buffer, mixer_buffer.offset, length * 2);

            /* loop over each voice and add its contribution */
            
            for (int voice=0;voice<last_channel;voice++)//; voice < last_channel; voice++)
            {
                int f = channel_list[voice].frequency;
                int v = channel_list[voice].volume[0];

                mix = new _ShortPtr(mixer_buffer);

                if (channel_list[voice].noise_sw != 0)
                {
                    /* only update if we have non-zero volume and frequency */
                    if (v != 0 && (f & 0xff) != 0)
                    {
                        float fbase = (float)sample_rate / (float)namco_clock;
                        int delta = (int)((float)((f & 0xff) << 4) * fbase);
                        int c = channel_list[voice].noise_counter;

                        /* add our contribution */
                        for (int i = 0; i < length; i++)
                        {
                            int noise_data;
                            int cnt;

                            if (channel_list[voice].noise_state != 0)
                                noise_data = 0x07;
                            else
                                noise_data = -0x07;
                            mix.write16(0, (ushort)((short)mix.read16(0) + noise_data * (v >> 1)));
                            mix.offset += 2;

                            c += delta;
                            cnt = (c >> 12);
                            c &= (1 << 12) - 1;
                            for (; cnt > 0; cnt--)
                            {
                                if (((channel_list[voice].noise_seed + 1) & 2) != 0) channel_list[voice].noise_state ^= 1;
                                if ((channel_list[voice].noise_seed & 1) != 0) channel_list[voice].noise_seed ^= 0x28000;
                                channel_list[voice].noise_seed >>= 1;
                            }
                        }

                        /* update the counter for this voice */
                        channel_list[voice].noise_counter = c;
                    }
                }
                else
                {
                    /* only update if we have non-zero volume and frequency */
                    if (v != 0 && f != 0)
                    {                        
                        int c = channel_list[voice].counter;

                        /* add our contribution */
                        for (int i = 0; i < length; i++)
                        {
                            c += f;
                            int offs = (c >> 15) & 0x1f;
                            //ushort currentmix = mix.read16(0);
                            if (samples_per_byte == 1)	/* use only low 4 bits */
                            {
                                mix.write16(0, (ushort)((short)mix.read16(0) + ((channel_list[voice].wave[offs] & 0x0f) - 8) * v));
                                mix.offset += 2;
                            }
                            else	/* use full byte, first the high 4 bits, then the low 4 bits */
                            {
                                if ((offs & 1) != 0)
                                {
                                    mix.write16(0, (ushort)((short)mix.read16(0) + ((channel_list[voice].wave[offs >> 1] & 0x0f) - 8) * v));
                                    mix.offset += 2;
                                }
                                else
                                {
                                    mix.write16(0, (ushort)((short)mix.read16(0) + (((channel_list[voice].wave[offs >> 1] >> 4) & 0x0f) - 8) * v));
                                    mix.offset += 2;
                                }
                            }
                        }

                        /* update the counter for this voice */
                        channel_list[voice].counter = c;
                    }
                }
            }

            /* mix it down */
            mix = new _ShortPtr(mixer_buffer);
            for (int i = 0; i < length; i++)
            {
                buffer.write16(0, (ushort)mixer_lookup[mixer_lookup_middle+(short)mix.read16(0)]);
                buffer.offset += 2;
                mix.offset += 2;
            }
        }
示例#29
0
 static void blockmove_transthrough_noremap_flipx16(_ShortPtr srcdata, int srcwidth, int srcheight, int srcmodulo, _ShortPtr dstdata, int dstmodulo, int transcolor) { throw new Exception(); }
示例#30
0
        void AY8910Update(int chip, _ShortPtr[] buffer, int length)
        {
            AY8910 PSG = AYPSG[chip];
            _ShortPtr buf1, buf2, buf3;
            int outn;

            buf1 = buffer[0];
            buf2 = buffer[1];
            buf3 = buffer[2];


            /* The 8910 has three outputs, each output is the mix of one of the three */
            /* tone generators and of the (single) noise generator. The two are mixed */
            /* BEFORE going into the DAC. The formula to mix each channel is: */
            /* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */
            /* Note that this means that if both tone and noise are disabled, the output */
            /* is 1, not 0, and can be modulated changing the volume. */


            /* If the channels are disabled, set their output to 1, and increase the */
            /* counter, if necessary, so they will not be inverted during this update. */
            /* Setting the output to 1 is necessary because a disabled channel is locked */
            /* into the ON state (see above); and it has no effect if the volume is 0. */
            /* If the volume is 0, increase the counter, but don't touch the output. */
            if ((PSG.Regs[AY_ENABLE] & 0x01) != 0)
            {
                if (PSG.CountA <= length * STEP) PSG.CountA += length * STEP;
                PSG.OutputA = 1;
            }
            else if (PSG.Regs[AY_AVOL] == 0)
            {
                /* note that I do count += length, NOT count = length + 1. You might think */
                /* it's the same since the volume is 0, but doing the latter could cause */
                /* interferencies when the program is rapidly modulating the volume. */
                if (PSG.CountA <= length * STEP) PSG.CountA += length * STEP;
            }
            if ((PSG.Regs[AY_ENABLE] & 0x02) != 0)
            {
                if (PSG.CountB <= length * STEP) PSG.CountB += length * STEP;
                PSG.OutputB = 1;
            }
            else if (PSG.Regs[AY_BVOL] == 0)
            {
                if (PSG.CountB <= length * STEP) PSG.CountB += length * STEP;
            }
            if ((PSG.Regs[AY_ENABLE] & 0x04) != 0)
            {
                if (PSG.CountC <= length * STEP) PSG.CountC += length * STEP;
                PSG.OutputC = 1;
            }
            else if (PSG.Regs[AY_CVOL] == 0)
            {
                if (PSG.CountC <= length * STEP) PSG.CountC += length * STEP;
            }

            /* for the noise channel we must not touch OutputN - it's also not necessary */
            /* since we use outn. */
            if ((PSG.Regs[AY_ENABLE] & 0x38) == 0x38)	/* all off */
                if (PSG.CountN <= length * STEP) PSG.CountN += length * STEP;

            outn = (PSG.OutputN | PSG.Regs[AY_ENABLE]);


            /* buffering loop */
            while (length != 0)
            {
                int vola, volb, volc;
                int left;


                /* vola, volb and volc keep track of how long each square wave stays */
                /* in the 1 position during the sample period. */
                vola = volb = volc = 0;

                left = STEP;
                do
                {
                    int nextevent;


                    if (PSG.CountN < left) nextevent = PSG.CountN;
                    else nextevent = left;

                    if ((outn & 0x08) != 0)
                    {
                        if (PSG.OutputA != 0) vola += PSG.CountA;
                        PSG.CountA -= nextevent;
                        /* PeriodA is the half period of the square wave. Here, in each */
                        /* loop I add PeriodA twice, so that at the end of the loop the */
                        /* square wave is in the same status (0 or 1) it was at the start. */
                        /* vola is also incremented by PeriodA, since the wave has been 1 */
                        /* exactly half of the time, regardless of the initial position. */
                        /* If we exit the loop in the middle, OutputA has to be inverted */
                        /* and vola incremented only if the exit status of the square */
                        /* wave is 1. */
                        while (PSG.CountA <= 0)
                        {
                            PSG.CountA += PSG.PeriodA;
                            if (PSG.CountA > 0)
                            {
                                PSG.OutputA ^= 1;
                                if (PSG.OutputA != 0) vola += PSG.PeriodA;
                                break;
                            }
                            PSG.CountA += PSG.PeriodA;
                            vola += PSG.PeriodA;
                        }
                        if (PSG.OutputA != 0) vola -= PSG.CountA;
                    }
                    else
                    {
                        PSG.CountA -= nextevent;
                        while (PSG.CountA <= 0)
                        {
                            PSG.CountA += PSG.PeriodA;
                            if (PSG.CountA > 0)
                            {
                                PSG.OutputA ^= 1;
                                break;
                            }
                            PSG.CountA += PSG.PeriodA;
                        }
                    }

                    if ((outn & 0x10) != 0)
                    {
                        if (PSG.OutputB != 0) volb += PSG.CountB;
                        PSG.CountB -= nextevent;
                        while (PSG.CountB <= 0)
                        {
                            PSG.CountB += PSG.PeriodB;
                            if (PSG.CountB > 0)
                            {
                                PSG.OutputB ^= 1;
                                if (PSG.OutputB != 0) volb += PSG.PeriodB;
                                break;
                            }
                            PSG.CountB += PSG.PeriodB;
                            volb += PSG.PeriodB;
                        }
                        if (PSG.OutputB != 0) volb -= PSG.CountB;
                    }
                    else
                    {
                        PSG.CountB -= nextevent;
                        while (PSG.CountB <= 0)
                        {
                            PSG.CountB += PSG.PeriodB;
                            if (PSG.CountB > 0)
                            {
                                PSG.OutputB ^= 1;
                                break;
                            }
                            PSG.CountB += PSG.PeriodB;
                        }
                    }

                    if ((outn & 0x20) != 0)
                    {
                        if (PSG.OutputC != 0) volc += PSG.CountC;
                        PSG.CountC -= nextevent;
                        while (PSG.CountC <= 0)
                        {
                            PSG.CountC += PSG.PeriodC;
                            if (PSG.CountC > 0)
                            {
                                PSG.OutputC ^= 1;
                                if (PSG.OutputC != 0) volc += PSG.PeriodC;
                                break;
                            }
                            PSG.CountC += PSG.PeriodC;
                            volc += PSG.PeriodC;
                        }
                        if (PSG.OutputC != 0) volc -= PSG.CountC;
                    }
                    else
                    {
                        PSG.CountC -= nextevent;
                        while (PSG.CountC <= 0)
                        {
                            PSG.CountC += PSG.PeriodC;
                            if (PSG.CountC > 0)
                            {
                                PSG.OutputC ^= 1;
                                break;
                            }
                            PSG.CountC += PSG.PeriodC;
                        }
                    }

                    PSG.CountN -= nextevent;
                    if (PSG.CountN <= 0)
                    {
                        /* Is noise output going to change? */
                        if (((PSG.RNG + 1) & 2) != 0)	/* (bit0^bit1)? */
                        {
                            PSG.OutputN = (byte)~PSG.OutputN;
                            outn = (PSG.OutputN | PSG.Regs[AY_ENABLE]);
                        }

                        /* The Random Number Generator of the 8910 is a 17-bit shift */
                        /* register. The input to the shift register is bit0 XOR bit2 */
                        /* (bit0 is the output). */

                        /* The following is a fast way to compute bit 17 = bit0^bit2. */
                        /* Instead of doing all the logic operations, we only check */
                        /* bit 0, relying on the fact that after two shifts of the */
                        /* register, what now is bit 2 will become bit 0, and will */
                        /* invert, if necessary, bit 16, which previously was bit 18. */
                        if ((PSG.RNG & 1) != 0) PSG.RNG ^= 0x28000;
                        PSG.RNG >>= 1;
                        PSG.CountN += PSG.PeriodN;
                    }

                    left -= nextevent;
                } while (left > 0);

                /* update envelope */
                if (PSG.Holding == 0)
                {
                    PSG.CountE -= STEP;
                    if (PSG.CountE <= 0)
                    {
                        do
                        {
                            PSG.CountEnv--;
                            PSG.CountE += PSG.PeriodE;
                        } while (PSG.CountE <= 0);

                        /* check envelope current position */
                        if (PSG.CountEnv < 0)
                        {
                            if (PSG.Hold != 0)
                            {
                                if (PSG.Alternate != 0)
                                    PSG.Attack ^= 0x1f;
                                PSG.Holding = 1;
                                PSG.CountEnv = 0;
                            }
                            else
                            {
                                /* if CountEnv has looped an odd number of times (usually 1), */
                                /* invert the output. */
                                if (PSG.Alternate != 0 && (PSG.CountEnv & 0x20) != 0)
                                    PSG.Attack ^= 0x1f;

                                PSG.CountEnv &= 0x1f;
                            }
                        }

                        PSG.VolE = PSG.VolTable[PSG.CountEnv ^ PSG.Attack];
                        /* reload volume */
                        if (PSG.EnvelopeA != 0) PSG.VolA = PSG.VolE;
                        if (PSG.EnvelopeB != 0) PSG.VolB = PSG.VolE;
                        if (PSG.EnvelopeC != 0) PSG.VolC = PSG.VolE;
                    }
                }

                buf1.write16(0, (ushort)((vola * PSG.VolA) / STEP));
                buf2.write16(0, (ushort)((volb * PSG.VolB) / STEP));
                buf3.write16(0, (ushort)((volc * PSG.VolC) / STEP));

                buf1.offset += 2;
                buf2.offset += 2;
                buf3.offset += 2;
                length--;
            }
        }