Fix some .lse [Operation Abyss (PC), Operation Babel (PC)]

This commit is contained in:
bnnm 2018-10-04 20:43:23 +02:00
parent a7e29c8be1
commit f59faa0c07
3 changed files with 68 additions and 74 deletions

View File

@ -1031,16 +1031,12 @@ static const meta_info meta_info_list[] = {
{meta_OGG_SLI, "Ogg Vorbis with .sli (start,length) for looping"},
{meta_OGG_SLI2, "Ogg Vorbis with .sli (from,to) for looping"},
{meta_OGG_SFL, "Ogg Vorbis with SFPL for looping"},
{meta_OGG_UM3, "Ogg Vorbis (Ultramarine3)"},
{meta_OGG_KOVS, "Ogg Vorbis (KOVS header)"},
{meta_OGG_PSYCHIC, "Ogg Vorbis (Psychic Software)"},
{meta_OGG_SNGW, "Ogg Vorbis (Capcom)"},
{meta_OGG_ISD, "Ogg Vorbis (ISD)"},
{meta_OGG_encrypted, "Ogg Vorbis (encrypted)"},
{meta_KMA9, "Koei Tecmo KMA9 header"},
{meta_XWC, "Starbreeze XWC header"},
{meta_SQEX_SAB, "Square-Enix SAB header"},
{meta_SQEX_MAB, "Square-Enix MAB header"},
{meta_OGG_L2SD, "Ogg Vorbis (L2SD)"},
{meta_WAF, "KID WAF header"},
{meta_WAVE, "EngineBlack .WAVE header"},
{meta_WAVE_segmented, "EngineBlack .WAVE header (segmented)"},
@ -1054,20 +1050,15 @@ static const meta_info meta_info_list[] = {
{meta_DSP_MCADPCM, "Bethesda .mcadpcm header"},
{meta_UBI_LYN, "Ubisoft LyN RIFF header"},
{meta_MSB_MSH, "Sony MultiStream MSH+MSB header"},
{meta_OGG_RPGMV, "Ogg Vorbis (RPGMV header)"},
{meta_OGG_ENO, "Ogg Vorbis (ENO header)"},
{meta_TXTP, "TXTP generic header"},
{meta_SMC_SMH, "Genki SMC+SMH header"},
{meta_OGG_YS8, "Ogg Vorbis (Ys VIII header)"},
{meta_PPST, "Parappa PPST header"},
{meta_OPUS_PPP, "AT9 OPUS header"},
{meta_UBI_BAO, "Ubisoft BAO header"},
{meta_DSP_SWITCH_AUDIO, "UE4 Switch Audio header"},
{meta_TA_AAC_VITA, "tri-Ace AAC (Vita) header"},
{meta_OGG_GWM, "Ogg Vorbis (GWM header)"},
{meta_DSP_SADF, "Procyon Studio SADF header"},
{meta_H4M, "Hudson HVQM4 header"},
{meta_OGG_MUS, "Ogg Vorbis (MUS header)"},
{meta_ASF, "Argonaut ASF header"},
{meta_XMD, "Konami XMD header"},
{meta_CKS, "Cricket Audio CKS header"},
@ -1097,7 +1088,6 @@ static const meta_info meta_info_list[] = {
{meta_NXA, "Entergram NXA header"},
{meta_ADPCM_CAPCOM, "Capcom .ADPCM header"},
{meta_UE4OPUS, "Epic Games UE4OPUS header"},
{meta_OGG_LSE, "Ogg Vorbis (LSE header)"},
};

View File

@ -78,7 +78,7 @@ static void um3_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
/* first 0x800 bytes are xor'd with 0xff */
/* first 0x800 bytes are xor'd */
if (ov_streamfile->offset < 0x800) {
int num_crypt = 0x800 - ov_streamfile->offset;
if (num_crypt > bytes_read)
@ -94,7 +94,7 @@ static void kovs_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, v
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
/* first 0x100 bytes are xor'd with offset */
/* first 0x100 bytes are xor'd */
if (ov_streamfile->offset < 0x100) {
int max_offset = ov_streamfile->offset + bytes_read;
if (max_offset > 0x100)
@ -110,9 +110,9 @@ static void psychic_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb
size_t bytes_read = size*nmemb;
int i;
/* add 0x23 ('#') */
/* bytes add 0x23 ('#') */
for (i = 0; i < bytes_read; i++) {
((uint8_t*)ptr)[i] += 0x23;
((uint8_t*)ptr)[i] += 0x23;
}
}
@ -125,7 +125,7 @@ static void sngw_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, v
put_32bitBE(key, ov_streamfile->xor_value);
/* bytes are xor'd with key and nibble-swapped, first "OggS" is changed */
/* first "OggS" is changed and bytes are xor'd and nibble-swapped */
for (i = 0; i < bytes_read; i++) {
if (ov_streamfile->offset+i < 0x04) {
((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4];
@ -145,7 +145,7 @@ static void isd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
/* bytes are xor'd with key */
/* bytes are xor'd */
for (i = 0; i < bytes_read; i++) {
((uint8_t*)ptr)[i] ^= key[(ov_streamfile->offset + i) % 16];
}
@ -160,7 +160,6 @@ static void l2sd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, v
/* first "OggS" is changed */
for (i = 0; i < bytes_read; i++) {
if (ov_streamfile->offset+i < 0x04) {
/* replace key in the first 4 bytes with "OggS" */
((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4];
}
else {
@ -177,7 +176,7 @@ static void rpgmvo_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb,
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
/* first 0x10 are xor'd with a key, but the header can be easily reconstructed
/* first 0x10 are xor'd, but header can be easily reconstructed
* (key is also in (game)/www/data/System.json "encryptionKey") */
for (i = 0; i < bytes_read; i++) {
if (ov_streamfile->offset+i < 0x10) {
@ -197,7 +196,7 @@ static void eno_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
/* bytes are xor'd with key */
/* bytes are xor'd */
for (i = 0; i < bytes_read; i++) {
((uint8_t*)ptr)[i] ^= (uint8_t)ov_streamfile->xor_value;
}
@ -208,7 +207,7 @@ static void ys8_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
/* bytes are xor'd with key and nibble-swapped */
/* bytes are xor'd and nibble-swapped */
for (i = 0; i < bytes_read; i++) {
uint8_t val = ((uint8_t*)ptr)[i] ^ ov_streamfile->xor_value;
((uint8_t*)ptr)[i] = ((val << 4) & 0xf0) | ((val >> 4) & 0x0f);
@ -220,7 +219,7 @@ static void gwm_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
/* bytes are xor'd with key */
/* bytes are xor'd */
for (i = 0; i < bytes_read; i++) {
((uint8_t*)ptr)[i] ^= (uint8_t)ov_streamfile->xor_value;
}
@ -236,7 +235,7 @@ static void mus_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo
int i;
char *header_id = "OggS";
/* bytes are xor'd with key, first "OggS" is changed */
/* first "OggS" is changed and bytes are xor'd */
for (i = 0; i < bytes_read; i++) {
if (ov_streamfile->offset+i < 0x04) { /* if decrypted gives "Mus " */
((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4];
@ -247,18 +246,35 @@ static void mus_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo
}
}
static void lse_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) {
static void lse_add_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) {
size_t bytes_read = size*nmemb;
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
/* bytes are xor'd with variable key */
/* bytes are xor'd */
for (i = 0; i < bytes_read; i++) {
int key = 0xC2 + (ov_streamfile->offset + i) % 256;
int key = (uint8_t)ov_streamfile->xor_value + ((ov_streamfile->offset + i) % 256);
((uint8_t*)ptr)[i] ^= key;
}
}
static void lse_ff_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) {
size_t bytes_read = size*nmemb;
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
char *header_id = "OggS";
/* first "OggS" is changed and bytes are xor'd */
for (i = 0; i < bytes_read; i++) {
if (ov_streamfile->offset+i < 0x04) {
((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4];
}
else {
((uint8_t*)ptr)[i] ^= 0xFF;
}
}
}
/* Ogg Vorbis, by way of libvorbisfile; may contain loop comments */
VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
@ -307,22 +323,21 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
goto fail;
}
/* check standard Ogg Vorbis and variations */
if (is_ogg) {
if (read_32bitBE(0x00,streamFile) == 0x2c444430) { /* Psychic Software [Darkwind: War on Wheels (PC)] */
ovmi.decryption_callback = psychic_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_PSYCHIC;
ovmi.meta_type = meta_OGG_encrypted;
}
else if (read_32bitBE(0x00,streamFile) == 0x4C325344) { /* "L2SD" [Lineage II Chronicle 4 (PC)] */
ovmi.decryption_callback = l2sd_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_L2SD;
ovmi.meta_type = meta_OGG_encrypted;
}
else if (read_32bitBE(0x00,streamFile) == 0x048686C5) { /* XOR'ed + bitswapped "OggS" [Ys VIII (PC)] */
else if (read_32bitBE(0x00,streamFile) == 0x048686C5) { /* "OggS" XOR'ed + bitswapped [Ys VIII (PC)] */
ovmi.xor_value = 0xF0;
ovmi.decryption_callback = ys8_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_YS8;
ovmi.meta_type = meta_OGG_encrypted;
}
else if (read_32bitBE(0x00,streamFile) == 0x4f676753) { /* "OggS" */
else if (read_32bitBE(0x00,streamFile) == 0x4f676753) { /* "OggS" (standard) */
ovmi.meta_type = meta_OGG_VORBIS;
}
else {
@ -330,16 +345,14 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
}
}
/* check "Ultramarine3" (???), may be encrypted */
if (is_um3) {
if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
if (is_um3) { /* ["Ultramarine3" (???)] */
if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" (optionally encrypted) */
ovmi.decryption_callback = um3_ogg_decryption_callback;
}
ovmi.meta_type = meta_OGG_UM3;
ovmi.meta_type = meta_OGG_encrypted;
}
/* check KOVS (Koei Tecmo games), header + encrypted */
if (is_kovs) {
if (is_kovs) { /* Koei Tecmo PC games] */
if (read_32bitBE(0x00,streamFile) != 0x4b4f5653) { /* "KOVS" */
goto fail;
}
@ -351,19 +364,17 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
start_offset = 0x20;
}
/* check SNGW (Capcom's MT Framework PC games), may be encrypted */
if (is_sngw) {
if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
if (is_sngw) { /* [Capcom's MT Framework PC games] */
if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" (optionally encrypted) */
ovmi.xor_value = read_32bitBE(0x00,streamFile);
ovmi.decryption_callback = sngw_ogg_decryption_callback;
}
ovmi.meta_type = meta_OGG_SNGW;
ovmi.meta_type = meta_OGG_encrypted;
}
/* check ISD [Gunvolt (PC)], encrypted */
if (is_isd) {
if (is_isd) { /* [Gunvolt (PC)] */
ovmi.decryption_callback = isd_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_ISD;
ovmi.meta_type = meta_OGG_encrypted;
//todo looping unknown, not in Ogg comments
// game has sound/GV_steam.* files with info about sound/stream/*.isd
@ -374,45 +385,48 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
// 0x0c(2): PCM block size, 0x0e(2): PCM bps, 0x10: null, 0x18: samples (in PCM bytes)
}
/* check RPGMKVO [RPG Maker MV (PC)], header + partially encrypted */
if (is_rpgmvo) {
if (is_rpgmvo) { /* [RPG Maker MV (PC)] */
if (read_32bitBE(0x00,streamFile) != 0x5250474D && /* "RPGM" */
read_32bitBE(0x00,streamFile) != 0x56000000) { /* "V\0\0\0" */
goto fail;
}
ovmi.decryption_callback = rpgmvo_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_RPGMV;
ovmi.meta_type = meta_OGG_encrypted;
start_offset = 0x10;
}
/* check ENO [Metronomicon (PC)], key + encrypted */
if (is_eno) {
if (is_eno) { /* [Metronomicon (PC)] */
/* first byte probably derives into xor key, but this works too */
ovmi.xor_value = read_8bit(0x05,streamFile); /* always zero = easy key */
ovmi.decryption_callback = eno_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_ENO;
ovmi.meta_type = meta_OGG_encrypted;
start_offset = 0x01;
}
/* check GWM [Adagio: Cloudburst (PC)], encrypted */
if (is_gwm) {
if (is_gwm) { /* [Adagio: Cloudburst (PC)] */
ovmi.xor_value = 0x5D;
ovmi.decryption_callback = gwm_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_GWM;
ovmi.meta_type = meta_OGG_encrypted;
}
/* check .mus [Redux - Dark Matters (PC)], encrypted */
if (is_mus) {
if (is_mus) { /* [Redux - Dark Matters (PC)] */
ovmi.decryption_callback = mus_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_MUS;
ovmi.meta_type = meta_OGG_encrypted;
}
/* check .lse [Labyrinth of Refrain: Coven of Dusk (PC)], encrypted */
if (is_lse) {
ovmi.decryption_callback = lse_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_LSE;
if (is_lse) { /* [Nippon Ichi PC games] */
if (read_32bitBE(0x00,streamFile) == 0xFFFFFFFF) { /* [Operation Abyss: New Tokyo Legacy (PC)] */
ovmi.decryption_callback = lse_ff_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_encrypted;
}
else { /* [Operation Babel: New Tokyo Legacy (PC), Labyrinth of Refrain: Coven of Dusk (PC)] */
ovmi.decryption_callback = lse_add_ogg_decryption_callback;
ovmi.xor_value = (uint8_t)read_8bit(0x04,streamFile) - 0x04;
ovmi.meta_type = meta_OGG_encrypted;
/* key is found at file_size-1 but this works too (same key for most files but can vary) */
}
}
@ -587,7 +601,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callb
}
}
//;VGM_LOG("OGG: user_comment=%s\n", user_comment);
;VGM_LOG("OGG: user_comment=%s\n", user_comment);
}
}

View File

@ -642,16 +642,12 @@ typedef enum {
meta_OGG_SLI, /* Ogg Vorbis file w/ companion .sli for looping */
meta_OGG_SLI2, /* Ogg Vorbis file w/ different styled .sli for looping */
meta_OGG_SFL, /* Ogg Vorbis file w/ .sfl (RIFF SFPL) for looping */
meta_OGG_UM3, /* Ogg Vorbis with optional encryption */
meta_OGG_KOVS, /* Ogg Vorbis with encryption (Koei Tecmo Games) */
meta_OGG_PSYCHIC, /* Ogg Vorbis with encryption */
meta_OGG_SNGW, /* Ogg Vorbis with optional encryption (Capcom PC games) */
meta_OGG_ISD, /* Ogg Vorbis with encryption (Azure Striker Gunvolt PC) */
meta_OGG_KOVS, /* Ogg Vorbis with header and encryption (Koei Tecmo Games) */
meta_OGG_encrypted, /* Ogg Vorbis with encryption */
meta_KMA9, /* Koei Tecmo [Nobunaga no Yabou - Souzou (Vita)] */
meta_XWC, /* Starbreeze games */
meta_SQEX_SAB, /* Square-Enix newest middleware (sound) */
meta_SQEX_MAB, /* Square-Enix newest middleware (music) */
meta_OGG_L2SD, /* Ogg Vorbis with obfuscation [Lineage II Chronicle 4 (PC)] */
meta_WAF, /* KID WAF [Ever 17 (PC)] */
meta_WAVE, /* EngineBlack games [Mighty Switch Force! (3DS)] */
meta_WAVE_segmented, /* EngineBlack games, segmented [Shantae and the Pirate's Curse (PC)] */
@ -665,19 +661,14 @@ typedef enum {
meta_DSP_MCADPCM, /* Skyrim (Switch) */
meta_UBI_LYN, /* Ubisoft LyN engine [The Adventures of Tintin (multi)] */
meta_MSB_MSH, /* sfx companion of MIH+MIB */
meta_OGG_RPGMV, /* Ogg Vorbis with encryption [RPG Maker MV games (PC)] */
meta_OGG_ENO, /* Ogg Vorbis with encryption [Metronomicon (PC)] */
meta_TXTP, /* generic text playlist */
meta_SMC_SMH, /* Wangan Midnight (System 246) */
meta_OGG_YS8, /* Ogg Vorbis with encryption (Ys VIII PC) */
meta_PPST, /* PPST [Parappa the Rapper (PSP)] */
meta_OPUS_PPP, /* .at9 Opus [Penny-Punching Princess (Switch)] */
meta_UBI_BAO, /* Ubisoft BAO */
meta_DSP_SWITCH_AUDIO, /* Gal Gun 2 (Switch) */
meta_TA_AAC_VITA, /* tri-Ace AAC (Judas Code) */
meta_OGG_GWM, /* Ogg Vorbis with encryption [Metronomicon (PC)] */
meta_H4M, /* Hudson HVQM4 video [Resident Evil 0 (GC), Tales of Symphonia (GC)] */
meta_OGG_MUS, /* Ogg Vorbis with encryption [Redux - Dark Matters (PC)] */
meta_ASF, /* Argonaut ASF [Croc 2 (PC)] */
meta_XMD, /* Konami XMD [Silent Hill 4 (Xbox), Castlevania: Curse of Darkness (Xbox)] */
meta_CKS, /* Cricket Audio stream [Part Time UFO (Android), Mega Man 1-6 (Android)] */
@ -707,7 +698,6 @@ typedef enum {
meta_NXA,
meta_ADPCM_CAPCOM,
meta_UE4OPUS,
meta_OGG_LSE,
} meta_t;