Add DERF DPCM decoder [Stupid Invaders (PC)]

This commit is contained in:
bnnm 2018-09-06 17:45:34 +02:00
parent 00bec4bd70
commit f519b1ad70
11 changed files with 152 additions and 15 deletions

View File

@ -212,20 +212,21 @@ are used in few games.
- Yamaha AICA ADPCM
- Procyon Studio ADPCM
- Level-5 0x555 ADPCM
- Activision EXAKT SASSC DPCM
- lsf ADPCM
- Konami MTAF ADPCM
- Konami MTA2 ADPCM
- Paradigm MC3 ADPCM
- SDX2 2:1 Squareroot-Delta-Exact compression DPCM
- CBD2 2:1 Cuberoot-Delta-Exact compression DPCM
- InterPlay ACM
- VisualArt's NWA
- CRI HCA
- Electronic Arts MicroTalk a.k.a. UTK or UMT
- FMOD FADPCM 4-bit ADPCM
- Konami XMD 4-bit ADPCM
- Argonaut ASF 4-bit ADPCM
- SDX2 2:1 Squareroot-Delta-Exact compression DPCM
- CBD2 2:1 Cuberoot-Delta-Exact compression DPCM
- Activision EXAKT SASSC DPCM
- Xilam DERF DPCM
- InterPlay ACM
- VisualArt's NWA
- Electronic Arts MicroTalk a.k.a. UTK or UMT
- CRI HCA
- Xiph Vorbis (Ogg, FSB5, Wwise, OGL, Silicon Knights)
- MPEG MP1/2/3 (standard, AHX, XVAG, FSB, AWC, P3D, etc)
- ITU-T G.722.1 (Polycom Siren 7)

View File

@ -160,6 +160,10 @@ void decode_asf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
/* xmd_decoder */
void decode_xmd(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
/* derf_decoder */
void decode_derf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* ea_mt_decoder*/
ea_mt_codec_data *init_ea_mt(int channel_count, int type);
void decode_ea_mt(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
@ -277,6 +281,7 @@ size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate,
#endif
/* coding_utils */
int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, size_t chunk_size, uint16_t codec);
int ffmpeg_make_riff_atrac3(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int joint_stereo, int encoder_delay);

43
src/coding/derf_decoder.c Normal file
View File

@ -0,0 +1,43 @@
#include "coding.h"
/* IMA table plus seven extra steps at the beginning */
static const int derf_steps[96] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 16,
17, 19, 21, 23, 25, 28, 31, 34,
37, 41, 45, 50, 55, 60, 66, 73,
80, 88, 97, 107, 118, 130, 143, 157,
173, 190, 209, 230, 253, 279, 307, 337,
371, 408, 449, 494, 544, 598, 658, 724,
796, 876, 963, 1060, 1166, 1282, 1411, 1552,
1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132,
7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289,
16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767,
};
/* 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;
}

View File

@ -566,7 +566,6 @@ static const coding_info coding_info_list[] = {
{coding_YAMAHA_NXAP, "Yamaha NXAP 4-bit ADPCM"},
{coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"},
{coding_L5_555, "Level-5 0x555 4-bit ADPCM"},
{coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"},
{coding_LSF, "lsf 4-bit ADPCM"},
{coding_MTAF, "Konami MTAF 4-bit ADPCM"},
{coding_MTA2, "Konami MTA2 4-bit ADPCM"},
@ -579,6 +578,8 @@ static const coding_info coding_info_list[] = {
{coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"},
{coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"},
{coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"},
{coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"},
{coding_DERF, "Xilam DERF 8-bit DPCM"},
{coding_ACM, "InterPlay ACM"},
{coding_NWA, "VisualArt's NWA DPCM"},
@ -1085,6 +1086,7 @@ static const meta_info meta_info_list[] = {
{meta_APC, "Cryo APC header"},
{meta_WV2, "Infogrames North America WAV2 header"},
{meta_XAU_KONAMI, "Konami XAU header"},
{meta_DERF, "Xilam DERF header"},
};

View File

@ -460,10 +460,14 @@
RelativePath=".\meta\dc_str.c"
>
</File>
<File
RelativePath=".\meta\dec.c"
>
</File>
<File
RelativePath=".\meta\dec.c"
>
</File>
<File
RelativePath=".\meta\derf.c"
>
</File>
<File
RelativePath=".\meta\dmsg_segh.c"
>
@ -1674,6 +1678,10 @@
RelativePath=".\coding\coding_utils.c"
>
</File>
<File
RelativePath=".\coding\derf_decoder.c"
>
</File>
<File
RelativePath=".\coding\ea_mt_decoder.c"
>

View File

@ -234,6 +234,7 @@
<ClCompile Include="meta\dc_kcey.c" />
<ClCompile Include="meta\dc_str.c" />
<ClCompile Include="meta\dec.c" />
<ClCompile Include="meta\derf.c" />
<ClCompile Include="meta\dmsg_segh.c" />
<ClCompile Include="meta\dsp_adx.c" />
<ClCompile Include="meta\dsp_bdsp.c" />
@ -479,6 +480,7 @@
<ClCompile Include="coding\adx_decoder.c" />
<ClCompile Include="coding\asf_decoder.c" />
<ClCompile Include="coding\yamaha_decoder.c" />
<ClCompile Include="coding\derf_decoder.c" />
<ClCompile Include="coding\ea_mt_decoder.c" />
<ClCompile Include="coding\ea_xa_decoder.c" />
<ClCompile Include="coding\ea_xas_decoder.c" />

View File

@ -292,6 +292,9 @@
<ClCompile Include="meta\dec.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\derf.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\dmsg_segh.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -1003,6 +1006,9 @@
<ClCompile Include="coding\yamaha_decoder.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
<ClCompile Include="coding\derf_decoder.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
<ClCompile Include="coding\ea_mt_decoder.c">
<Filter>coding\Source Files</Filter>
</ClCompile>

48
src/meta/derf.c Normal file
View File

@ -0,0 +1,48 @@
#include "meta.h"
#include "../coding/coding.h"
/* DERF - from Stupid Invaders (PC) */
VGMSTREAM * init_vgmstream_derf(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
/* checks */
if (!check_extensions(streamFile, "adp"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x44455246) /* "DERF" */
goto fail;
channel_count = read_32bitLE(0x04,streamFile);
if (channel_count > 2) goto fail;
/* movie DERF also exist with slightly different header */
start_offset = 0x0c;
data_size = read_32bitLE(0x08,streamFile);
if (data_size + start_offset != get_streamfile_size(streamFile))
goto fail;
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = 22050;
vgmstream->meta_type = meta_DERF;
vgmstream->coding_type = coding_DERF;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x01;
vgmstream->num_samples = data_size / channel_count; /* bytes-to-samples */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -761,19 +761,30 @@ VGMSTREAM * init_vgmstream_nus3bank(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_scd_sscf(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_a2m(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ahv(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_msv(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_sdf_ps2(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_sdf_3ds(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_svg(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_vis(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_sdf_3ds(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_vai(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_aif_asobo(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ao(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_apc(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_wv2(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_xau_konami(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_derf(STREAMFILE *streamFile);
#endif /*_META_H*/

View File

@ -437,6 +437,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_apc,
init_vgmstream_wv2,
init_vgmstream_xau_konami,
init_vgmstream_derf,
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
@ -1096,6 +1097,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_SDX2_int:
case coding_CBD2:
case coding_ACM:
case coding_DERF:
case coding_NWA:
case coding_SASSC:
return 1;
@ -1270,6 +1272,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_SDX2:
case coding_SDX2_int:
case coding_CBD2:
case coding_DERF:
case coding_NWA:
case coding_SASSC:
return 0x01;
@ -1709,6 +1712,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
vgmstream->channels,vgmstream->samples_into_block,samples_to_do);
}
break;
case coding_DERF:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_derf(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do);
}
break;
case coding_IMA:
case coding_IMA_int:
case coding_DVI_IMA:

View File

@ -133,7 +133,6 @@ typedef enum {
coding_REF_IMA, /* Reflections IMA ADPCM */
coding_AWC_IMA, /* Rockstar AWC IMA ADPCM */
coding_UBI_IMA, /* Ubisoft IMA ADPCM */
coding_H4M_IMA, /* H4M IMA ADPCM (stereo or mono, high nibble first) */
coding_MSADPCM, /* Microsoft ADPCM (stereo/mono) */
@ -145,7 +144,6 @@ typedef enum {
coding_YAMAHA_NXAP, /* Yamaha ADPCM (NXAP variation) */
coding_NDS_PROCYON, /* Procyon Studio ADPCM */
coding_L5_555, /* Level-5 0x555 ADPCM */
coding_SASSC, /* Activision EXAKT SASSC DPCM */
coding_LSF, /* lsf ADPCM (Fastlane Street Racing iPhone)*/
coding_MTAF, /* Konami MTAF ADPCM */
coding_MTA2, /* Konami MTA2 ADPCM */
@ -159,6 +157,8 @@ typedef enum {
coding_SDX2_int, /* SDX2 2:1 Squareroot-Delta-Exact compression with sample-level interleave */
coding_CBD2, /* CBD2 2:1 Cuberoot-Delta-Exact compression DPCM */
coding_CBD2_int, /* CBD2 2:1 Cuberoot-Delta-Exact compression, with sample-level interleave */
coding_SASSC, /* Activision EXAKT SASSC 8-bit DPCM */
coding_DERF, /* DERF 8-bit DPCM */
coding_ACM, /* InterPlay ACM */
coding_NWA, /* VisualArt's NWA */
@ -705,6 +705,7 @@ typedef enum {
meta_APC, /* MegaRace 3 (PC) */
meta_WV2, /* Slave Zero (PC) */
meta_XAU_KONAMI, /* Yu-Gi-Oh - The Dawn of Destiny (Xbox) */
meta_DERF, /* Stupid Invaders (PC) */
} meta_t;