#include "layout.h" #include "../vgmstream.h" /* weird mix of Ubi ADPCM format with Ubi IMA, found in Splinter Cell Essentials (PSP) */ void block_update_ubi_sce(off_t block_offset, VGMSTREAM* vgmstream) { STREAMFILE* sf = vgmstream->ch[0].streamfile; int i, channels; size_t header_size, frame_size, subframe_size, padding_size; /* format mimics Ubi ADPCM's: * - 0x34/38 header with frame size (ex. 0x600), pre-read in meta * xN frames: * - 0x34 channel header per channel, with ADPCM config * - subframe (ex. 0x300) + padding byte * - subframe (ex. 0x300) + padding byte * * to skip the padding byte we'll detect subframes using codec_config as a counter * (higher bit has a special meaning) */ vgmstream->codec_config |= 0x80; /* flag for decoder, ugly I know */ if ((vgmstream->codec_config & 1) == 0) { header_size = 0x34; /* read header in first subframe */ } else { header_size = 0x00; } vgmstream->codec_config ^= 1; /* swap counter bit */ channels = vgmstream->channels; frame_size = vgmstream->full_block_size; subframe_size = frame_size / 2; padding_size = 0x01; vgmstream->current_block_offset = block_offset; vgmstream->current_block_size = subframe_size; vgmstream->next_block_offset = block_offset + header_size * vgmstream->channels + subframe_size + padding_size; for (i = 0; i < vgmstream->channels; i++) { vgmstream->ch[i].offset = block_offset + header_size * channels; if (header_size > 0) { vgmstream->ch[i].adpcm_step_index = read_32bitLE(block_offset + header_size * i + 0x04, sf); vgmstream->ch[i].adpcm_history1_32 = read_32bitLE(block_offset + header_size * i + 0x08, sf); /* TODO figure out * First step seems to always be a special value for the decoder, unsure of meaning. * 0 = too quiet and max = 88 = waveform starts a bit off and clicky. First hist is usually +-1, * other frames look, fine not sure what are they aiming for. */ if (vgmstream->ch[i].adpcm_step_index == 0x500) { vgmstream->ch[i].adpcm_step_index = 88; } } } }