Skip to content

Commit

Permalink
Merge pull request vgmstream#1495 from bnnm/mpc
Browse files Browse the repository at this point in the history
- Add EA SCHl .mpc videos [SSX Tricky (PS2)]
- Add HCA key
  • Loading branch information
bnnm authored Feb 25, 2024
2 parents aa61b40 + 489b3e8 commit aa22b1c
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 23 deletions.
6 changes: 6 additions & 0 deletions doc/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,12 @@ a companion file:
The key file can be `.(ext)key` (for the whole folder), or `(name).(ext)key"
(for a single file). The format is made up to suit vgmstream.

For example, if you have an encrypted HCA and its key string is *"123456789"*, make
a text file named `.hcakey` (notice it starts with a dot), open it with a text editor
and copy that key without quotes nor line endings: `123456789`. Save it, then play the
HCA normally. vgmstream will see this key and use it automatically.


### Artificial files
In some cases a file only has raw data, while important header info (codec type,
sample rate, channels, etc) is stored in the .exe or other hard to locate places.
Expand Down
35 changes: 20 additions & 15 deletions src/meta/ea_schl.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,26 +201,31 @@ VGMSTREAM* init_vgmstream_ea_schl_video(STREAMFILE* sf) {
int32_t(*read_32bit)(off_t, STREAMFILE*);


/* check extension */
/* checks */
/* .uv: early */
/* .dct: early-mid [ex. Need for Speed II SE (PC), FIFA 98 (PC)] */
/* .wve: early-mid [Madden NFL 99 (PC)] */
/* .mad: mid */
/* .vp6: late */
if (check_extensions(sf, "uv,dct")) {
/* starts with audio header block */
if (read_32bitBE(0x00, sf) != EA_BLOCKID_HEADER) /* "SCHl" */
goto fail;
} else if (check_extensions(sf, "mad,wve")) {
/* check initial movie block id */
if (read_32bitBE(0x00, sf) != 0x4D41446B) /* "MADk" */
goto fail;
} else if (check_extensions(sf, "vp6")) {
/* check initial movie block id */
if (read_32bitBE(0x00, sf) != 0x4D566864) /* "MVhd" */
goto fail;
} else {
goto fail;
/* .mpc: SSX Tricky (PS2) */
if (is_id32be(0x00, sf, "SCHl")) {
if (!check_extensions(sf, "uv,dct"))
return NULL;
}
else if (is_id32be(0x00, sf, "MADk")) {
if (!check_extensions(sf, "mad,wve"))
return NULL;
}
else if (is_id32be(0x00, sf, "MVhd")) {
if (!check_extensions(sf, "vp6"))
return NULL;
}
else if (is_id32be(0x00, sf, "MPCh")) {
if (!check_extensions(sf, "mpc,lmpc"))
return NULL;
}
else {
return NULL;
}

/* use block size to check endianness */
Expand Down
41 changes: 33 additions & 8 deletions src/meta/hca_bf.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "../coding/coding.h"

#ifdef HCA_BRUTEFORCE
#define HCA_BF_CHUNK 0x48000008 //~1GB (int), extra size for keys in between chunks

static void bruteforce_process_result(hca_keytest_t* hk, unsigned long long* p_keycode) {
*p_keycode = hk->best_key;
Expand Down Expand Up @@ -34,7 +35,8 @@ typedef enum {
static void bruteforce_hca_key_bin_type(STREAMFILE* sf, hca_codec_data* hca_data, unsigned long long* p_keycode, uint16_t subkey, HBF_type_t type) {
STREAMFILE* sf_keys = NULL;
uint8_t* buf = NULL;
uint32_t keys_size, bytes;
uint64_t keys_offset;
uint32_t keys_limit;
int pos, step;
uint64_t key = 0, old_key = 0;
hca_keytest_t hk = {0};
Expand All @@ -48,16 +50,12 @@ static void bruteforce_hca_key_bin_type(STREAMFILE* sf, hca_codec_data* hca_data

VGM_LOG("HCA BF: test keys.bin (type %i)\n", type);

keys_size = get_streamfile_size(sf_keys);

buf = malloc(keys_size);
buf = malloc(HCA_BF_CHUNK);
if (!buf) {
VGM_LOG("HCA BF: key file too big!\n");
goto done;
}

bytes = read_streamfile(buf, 0, keys_size, sf_keys);
if (bytes != keys_size) goto done;

VGM_LOG("HCA BF: start .bin\n");

Expand All @@ -73,9 +71,36 @@ static void bruteforce_hca_key_bin_type(STREAMFILE* sf, hca_codec_data* hca_data
default: goto done;
}

/* main read */
keys_offset = 0;
keys_limit = 0;
pos = 0;
while (pos < keys_size - 8) {
VGM_ASSERT(pos % 0x1000000 == 0, "HCA: pos %x...\n", pos);
while (true) {
/* read new chunk */
if (pos >= keys_limit) {
if (keys_offset + keys_limit == get_streamfile_size(sf_keys))
break;
if (keys_limit >= 8)
keys_offset += keys_limit - 8;

VGM_LOG("HCA: reading %llx + ...\n", (long long)keys_offset);
keys_limit = read_streamfile(buf, keys_offset, HCA_BF_CHUNK, sf_keys);
if (keys_limit == 0)
return;
pos = 0;
}

if (pos % 0x1000000 == 0) {
uint64_t pos_out = keys_offset + pos;
VGM_LOG("HCA: pos %llx...\n", (long long)pos_out);
}

#ifdef HCA_BF_IGNORE_BAD_KEYS
if (!is_good_key(buf + pos, int_size)) {
pos += step;
continue;
}
#endif

/* keys are usually u64le but other orders may exist */
switch(type) {
Expand Down
2 changes: 2 additions & 0 deletions src/meta/hca_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,8 @@ static const hcakey_info hcakey_list[] = {
// YuYuYui (Switch)
{3733383634313939}, // 000D437E1D5562D3

// Pachislot Valvrave (iOS)
{2753732797542815}, // 009C8816134319F
};

#endif/*_HCA_KEYS_H_*/

0 comments on commit aa22b1c

Please sign in to comment.