void ditherAndClamp(int32_t* out, const int32_t *sums, size_t c)
{
    size_t i;
    for (i=0 ; i<c ; i++) {
        int32_t l = *sums++;
        int32_t r = *sums++;
        int32_t nl = l >> 12;
        int32_t nr = r >> 12;
        l = clamp16(nl);
        r = clamp16(nr);
        *out++ = (r<<16) | (l & 0xFFFF);
    }
}
Beispiel #2
0
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
    int i;
    int32_t sample_count;
    int32_t hist1 = stream->adpcm_history1_16;
    uint32_t step_size = stream->adpcm_step_index;

    for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
        int sample_nibble =
                (
                 (unsigned)read_8bit(stream->offset+i/2,stream->streamfile) >>
                 (i&1?4:0)
                )&0xf;

        int32_t sample_delta = (int32_t)step_size * scale_delta[sample_nibble];
        int32_t new_sample;

        new_sample = hist1 + sample_delta/8;

        outbuf[sample_count] = clamp16(new_sample);

        hist1 = outbuf[sample_count];

        step_size = (step_size * scale_step[sample_nibble])/0x100;
        if (step_size < 0x7f) step_size = 0x7f;
        if (step_size > 0x6000) step_size = 0x6000;
    }

    stream->adpcm_history1_16 = hist1;
    stream->adpcm_step_index = step_size;
}
static inline int getInt(int y, int u, int v) {
    int i;
    int yc=298 * (y-16)+128;
    u-=128;
    v-=128;
    i= clamp(( yc           + 409 * v ) >> 8);//&0xff;
    i|=clamp8(( yc - 100 * u - 208 * v ));//&0xff00;
    i|=clamp16(( yc + 516 * u           )<<8);//&0xff0000;

    return i;//(int)(byte)(r&0xff)|((int)((byte)g&0xff)<<8)|((int)((byte)b&0xff)<<16);//(int)((byte)(i&0xff));//(y)|(u<<8)|(v<<16);//i;
}
Beispiel #4
0
void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian) {
    int i, sample_count;
    int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE;

    for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
        uint32_t sample_int = read_32bit(stream->offset+i*4,stream->streamfile);
        float* sample_float;
        int sample_pcm;

        sample_float = (float*)&sample_int;
        sample_pcm = (int)floor((*sample_float) * 32767.f + .5f);

        outbuf[sample_count] = clamp16(sample_pcm);
    }
}
static inline void getSI(unsigned short &rs, int &ri, int y, int u, int v) {
    int c1,c2,c3;
    int yc=298 * (y-16)+128;
    u-=128;
    v-=128;
    c1= clamp(( yc           + 409 * v ) >> 8);//&0xff;
    c2=clamp8(( yc - 100 * u - 208 * v ));//&0xff00;
    c3=clamp16(( yc + 516 * u           )<<8);//&0xff0000;
    ri=c1|c2|c3;
    c1>>=3;
    c2>>=(5);
    c2&=0x07e0;
    c3>>=8;//3+2,3+2+3
    c3&=0xf800;
    c3|=(c2|c1);
    rs=c3;

}
Beispiel #6
0
void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {

	int32_t hist = stream->adpcm_history1_32;

	int i;
	int32_t sample_count;
	
	for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
        int8_t sample_byte = read_8bit(stream->offset+i*channelspacing,stream->streamfile);
        int16_t sample;

        if (!(sample_byte & 1)) hist = 0;
        sample = hist + squares[sample_byte+128];

		hist = outbuf[sample_count] = clamp16(sample);
	}
	stream->adpcm_history1_32=hist;
}
Beispiel #7
0
/* Xilam DERF DPCM for Stupid Invaders (PC), decompiled from the exe */
void decode_derf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
    int i, sample_pos = 0, index;
    int32_t hist = stream->adpcm_history1_32;
    off_t frame_offset = stream->offset; /* frame size is 1 */

    for(i = first_sample; i < first_sample + samples_to_do; i++) {
        uint8_t code = (uint8_t)read_8bit(frame_offset+i,stream->streamfile);

        /* original exe doesn't clamp the index, so presumably codes can't over it */
        index = code & 0x7f;
        if (index > 95) index = 95;

        if (code & 0x80)
            hist -= derf_steps[index];
        else
            hist += derf_steps[index];

        outbuf[sample_pos] = clamp16(hist);
        sample_pos += channelspacing;
    }

    stream->adpcm_history1_32 = hist;
}
void GSDrawScanlineCodeGenerator::ColorTFX()
{
	if(!m_sel.fwrite)
	{
		return;
	}

	switch(m_sel.tfx)
	{
	case TFX_MODULATE:

		// rbt = rbt.modulate16<1>(rb).clamp8();

		modulate16(xmm2, xmm13, 1);

		clamp16(xmm2, xmm0);

		break;

	case TFX_DECAL:

		break;

	case TFX_HIGHLIGHT:
	case TFX_HIGHLIGHT2:

		// gat = gat.modulate16<1>(ga).add16(af).clamp8().mix16(gat);

		vmovdqa(xmm1, xmm3);

		modulate16(xmm3, xmm14, 1);

		vpshuflw(xmm6, xmm14, _MM_SHUFFLE(3, 3, 1, 1));
		vpshufhw(xmm6, xmm6, _MM_SHUFFLE(3, 3, 1, 1));
		vpsrlw(xmm6, 7);

		vpaddw(xmm3, xmm6);

		clamp16(xmm3, xmm0);
		
		mix16(xmm3, xmm1, xmm0);

		// rbt = rbt.modulate16<1>(rb).add16(af).clamp8();

		modulate16(xmm2, xmm13, 1);

		vpaddw(xmm2, xmm6);
		
		clamp16(xmm2, xmm0);

		break;

	case TFX_NONE:

		// rbt = iip ? rb.srl16(7) : rb;

		if(m_sel.iip)
		{
			vpsrlw(xmm2, xmm13, 7);
		}

		break;
	}
}
void GSDrawScanlineCodeGenerator::AlphaTFX()
{
	if(!m_sel.fb)
	{
		return;
	}

	switch(m_sel.tfx)
	{
	case TFX_MODULATE:

		// gat = gat.modulate16<1>(ga).clamp8();

		modulate16(xmm3, xmm14, 1);

		clamp16(xmm3, xmm0);

		// if(!tcc) gat = gat.mix16(ga.srl16(7));

		if(!m_sel.tcc)
		{
			vpsrlw(xmm1, xmm14, 7);

			mix16(xmm3, xmm1, xmm0);
		}

		break;

	case TFX_DECAL:

		// if(!tcc) gat = gat.mix16(ga.srl16(7));

		if(!m_sel.tcc)
		{
			vpsrlw(xmm1, xmm14, 7);

			mix16(xmm3, xmm1, xmm0);
		}

		break;

	case TFX_HIGHLIGHT:

		// gat = gat.mix16(!tcc ? ga.srl16(7) : gat.addus8(ga.srl16(7)));

		vpsrlw(xmm1, xmm14, 7);

		if(m_sel.tcc) 
		{
			vpaddusb(xmm1, xmm3);
		}

		mix16(xmm3, xmm1, xmm0);

		break;

	case TFX_HIGHLIGHT2:

		// if(!tcc) gat = gat.mix16(ga.srl16(7));

		if(!m_sel.tcc)
		{
			vpsrlw(xmm1, xmm14, 7);

			mix16(xmm3, xmm1, xmm0);
		}

		break;

	case TFX_NONE:

		// gat = iip ? ga.srl16(7) : ga;

		if(m_sel.iip)
		{
			vpsrlw(xmm3, xmm14, 7);
		}

		break;
	}

	// TODO: aa1
}
void GSDrawScanlineCodeGenerator::ColorTFX()
{
    if(!m_sel.fwrite)
    {
        return;
    }

    switch(m_sel.tfx)
    {
    case TFX_MODULATE:

        // GSVector4i rb = iip ? rbf : m_env.c.rb;

        // rbt = rbt.modulate16<1>(rb).clamp8();

        modulate16<1>(xmm5, xmmword[m_sel.iip ? &m_env.temp.rb : &m_env.c.rb]);

        clamp16(xmm5, xmm1);

        break;

    case TFX_DECAL:

        break;

    case TFX_HIGHLIGHT:
    case TFX_HIGHLIGHT2:

        if(m_sel.tfx == TFX_HIGHLIGHT2 && m_sel.tcc)
        {
            // GSVector4i ga = iip ? gaf : m_env.c.ga;

            movdqa(xmm2, xmmword[m_sel.iip ? &m_env.temp.ga : &m_env.c.ga]);
        }

        // gat = gat.modulate16<1>(ga).add16(af).clamp8().mix16(gat);

        movdqa(xmm1, xmm6);

        modulate16<1>(xmm6, xmm2);

        pshuflw(xmm2, xmm2, _MM_SHUFFLE(3, 3, 1, 1));
        pshufhw(xmm2, xmm2, _MM_SHUFFLE(3, 3, 1, 1));
        psrlw(xmm2, 7);

        paddw(xmm6, xmm2);

        clamp16(xmm6, xmm0);

        mix16(xmm6, xmm1, xmm0);

        // GSVector4i rb = iip ? rbf : m_env.c.rb;

        // rbt = rbt.modulate16<1>(rb).add16(af).clamp8();

        modulate16<1>(xmm5, xmmword[m_sel.iip ? &m_env.temp.rb : &m_env.c.rb]);

        paddw(xmm5, xmm2);

        clamp16(xmm5, xmm0);

        break;

    case TFX_NONE:

        // rbt = iip ? rb.srl16(7) : rb;

        if(m_sel.iip)
        {
            psrlw(xmm5, 7);
        }

        break;
    }
}
void GSDrawScanlineCodeGenerator::AlphaTFX()
{
    if(!m_sel.fb)
    {
        return;
    }

    switch(m_sel.tfx)
    {
    case TFX_MODULATE:

        // GSVector4i ga = iip ? gaf : m_env.c.ga;

        movdqa(xmm4, xmmword[m_sel.iip ? &m_env.temp.ga : &m_env.c.ga]);

        // gat = gat.modulate16<1>(ga).clamp8();

        modulate16<1>(xmm6, xmm4);

        clamp16(xmm6, xmm3);

        // if(!tcc) gat = gat.mix16(ga.srl16(7));

        if(!m_sel.tcc)
        {
            psrlw(xmm4, 7);

            mix16(xmm6, xmm4, xmm3);
        }

        break;

    case TFX_DECAL:

        // if(!tcc) gat = gat.mix16(ga.srl16(7));

        if(!m_sel.tcc)
        {
            // GSVector4i ga = iip ? gaf : m_env.c.ga;

            movdqa(xmm4, xmmword[m_sel.iip ? &m_env.temp.ga : &m_env.c.ga]);

            psrlw(xmm4, 7);

            mix16(xmm6, xmm4, xmm3);
        }

        break;

    case TFX_HIGHLIGHT:

        // GSVector4i ga = iip ? gaf : m_env.c.ga;

        movdqa(xmm4, xmmword[m_sel.iip ? &m_env.temp.ga : &m_env.c.ga]);
        movdqa(xmm2, xmm4);

        // gat = gat.mix16(!tcc ? ga.srl16(7) : gat.addus8(ga.srl16(7)));

        psrlw(xmm4, 7);

        if(m_sel.tcc)
        {
            paddusb(xmm4, xmm6);
        }

        mix16(xmm6, xmm4, xmm3);

        break;

    case TFX_HIGHLIGHT2:

        // if(!tcc) gat = gat.mix16(ga.srl16(7));

        if(!m_sel.tcc)
        {
            // GSVector4i ga = iip ? gaf : m_env.c.ga;

            movdqa(xmm4, xmmword[m_sel.iip ? &m_env.temp.ga : &m_env.c.ga]);
            movdqa(xmm2, xmm4);

            psrlw(xmm4, 7);

            mix16(xmm6, xmm4, xmm3);
        }

        break;

    case TFX_NONE:

        // gat = iip ? ga.srl16(7) : ga;

        if(m_sel.iip)
        {
            psrlw(xmm6, 7);
        }

        break;
    }

    if(m_sel.aa1)
    {
        // gs_user figure 3-2: anti-aliasing after tfx, before tests, modifies alpha

        // FIXME: bios config screen cubes

        if(!m_sel.abe)
        {
            // a = cov

            if(m_sel.edge)
            {
                movdqa(xmm0, xmmword[&m_env.temp.cov]);
            }
            else
            {
                pcmpeqd(xmm0, xmm0);
                psllw(xmm0, 15);
                psrlw(xmm0, 8);
            }

            mix16(xmm6, xmm0, xmm1);
        }
        else
        {
            // a = a == 0x80 ? cov : a

            pcmpeqd(xmm0, xmm0);
            psllw(xmm0, 15);
            psrlw(xmm0, 8);

            if(m_sel.edge)
            {
                movdqa(xmm1, xmmword[&m_env.temp.cov]);
            }
            else
            {
                movdqa(xmm1, xmm0);
            }

            pcmpeqw(xmm0, xmm6);
            psrld(xmm0, 16);
            pslld(xmm0, 16);

            blend8(xmm6, xmm1);
        }
    }
}
Beispiel #12
0
            if (i & 1) {/* odd/even nibble */
                scale = byte >> 4;
            } else {
                byte = read_8bit(stream->offset+(framesin*16)+2+i/2,stream->streamfile);
                scale = byte & 0x0f;
            }
            if (scale > 7) { /* sign extend */
                scale = scale - 16;
            }

            sample = (hist1 * HEVAG_coefs[predict_nr][0] +
                      hist2 * HEVAG_coefs[predict_nr][1] +
                      hist3 * HEVAG_coefs[predict_nr][2] +
                      hist4 * HEVAG_coefs[predict_nr][3] ) / 32;
            sample = (sample + (scale << (20 - shift)) + 128) >> 8;
        }

        outbuf[sample_count] = clamp16(sample);
        hist4 = hist3;
        hist3 = hist2;
        hist2 = hist1;
        hist1 = sample;
    }

    stream->adpcm_history1_32 = hist1;
    stream->adpcm_history2_32 = hist2;
    stream->adpcm_history3_32 = hist3;
    stream->adpcm_history4_32 = hist4;
}
Beispiel #13
0
void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do) {
    VGMSTREAMCHANNEL *ch1,*ch2;
    int i;
    int framesin;
    STREAMFILE *streamfile;
    off_t offset;

    framesin = first_sample/get_vgmstream_samples_per_frame(vgmstream);
    first_sample = first_sample%get_vgmstream_samples_per_frame(vgmstream);

    ch1 = &vgmstream->ch[0];
    ch2 = &vgmstream->ch[1];
    streamfile = ch1->streamfile;
    offset = ch1->offset+framesin*get_vgmstream_frame_size(vgmstream);

    if (first_sample==0) {
        ch1->adpcm_coef[0] = ADPCMCoeffs[read_8bit(offset,streamfile)][0];
        ch1->adpcm_coef[1] = ADPCMCoeffs[read_8bit(offset,streamfile)][1];
        ch2->adpcm_coef[0] = ADPCMCoeffs[read_8bit(offset+1,streamfile)][0];
        ch2->adpcm_coef[1] = ADPCMCoeffs[read_8bit(offset+1,streamfile)][1];
        ch1->adpcm_scale = read_16bitLE(offset+2,streamfile);
        ch2->adpcm_scale = read_16bitLE(offset+4,streamfile);
        ch1->adpcm_history1_16 = read_16bitLE(offset+6,streamfile);
        ch2->adpcm_history1_16 = read_16bitLE(offset+8,streamfile);
        ch1->adpcm_history2_16 = read_16bitLE(offset+10,streamfile);
        ch2->adpcm_history2_16 = read_16bitLE(offset+12,streamfile);

        outbuf[0] = ch1->adpcm_history2_16;
        outbuf[1] = ch2->adpcm_history2_16;

        outbuf+=2;
        first_sample++;
        samples_to_do--;
    }
    if (first_sample==1 && samples_to_do > 0) {
        outbuf[0] = ch1->adpcm_history1_16;
        outbuf[1] = ch2->adpcm_history1_16;

        outbuf+=2;
        first_sample++;
        samples_to_do--;
    }

    for (i=first_sample; i<first_sample+samples_to_do; i++) {
        int j;

        for (j=0; j<2; j++)
        {
            VGMSTREAMCHANNEL *ch = &vgmstream->ch[j];
            int sample_nibble =
                (j == 0 ?
                 get_high_nibble_signed(read_8bit(offset+14+i-2,streamfile)) :
                 get_low_nibble_signed(read_8bit(offset+14+i-2,streamfile))
                );
            int32_t hist1,hist2;
            int32_t predicted;

            hist1 = ch->adpcm_history1_16;
            hist2 = ch->adpcm_history2_16;
            predicted = hist1 * ch->adpcm_coef[0] + hist2 * ch->adpcm_coef[1];
            predicted /= 256;
            predicted += sample_nibble*ch->adpcm_scale;
            outbuf[0] = clamp16(predicted);
            ch->adpcm_history2_16 = ch->adpcm_history1_16;
            ch->adpcm_history1_16 = outbuf[0];
            ch->adpcm_scale = (ADPCMTable[sample_nibble&0xf] *
                               ch->adpcm_scale) / 256;
            if (ch->adpcm_scale < 0x10) ch->adpcm_scale = 0x10;

            outbuf++;
        }
    }
}