mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-29 19:37:30 +01:00
Add DERF DPCM decoder [Stupid Invaders (PC)]
This commit is contained in:
parent
00bec4bd70
commit
f519b1ad70
15
README.md
15
README.md
@ -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)
|
||||
|
@ -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
43
src/coding/derf_decoder.c
Normal 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;
|
||||
}
|
@ -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"},
|
||||
|
||||
};
|
||||
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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" />
|
||||
|
@ -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
48
src/meta/derf.c
Normal 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;
|
||||
}
|
@ -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*/
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user