mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2025-02-17 19:19:16 +01:00
feat(iidx18/19): Improve chart-patch to correctly support iidx 18 and 19
The paths changed for 18 and again for 19. Refactor and improve the detection logic to consider this. This also should make the code more maintainable.
This commit is contained in:
parent
32c786de27
commit
a1a849aef3
@ -50,6 +50,19 @@ struct ospreybin {
|
||||
uint32_t checksum_type;
|
||||
};
|
||||
|
||||
enum song_data_path_format {
|
||||
SONG_DATA_PATH_INVALID = 0,
|
||||
SONG_DATA_PATH_09_TO_17 = 1,
|
||||
SONG_DATA_PATH_18 = 2,
|
||||
SONG_DATA_PATH_19 = 3,
|
||||
};
|
||||
|
||||
enum song_data_file_type {
|
||||
SONG_DATA_FILE_TYPE_UNKNKOWN = 0,
|
||||
SONG_DATA_FILE_TYPE_DOT_1 = 1,
|
||||
SONG_DATA_FILE_TYPE_CHECKSUM = 2,
|
||||
};
|
||||
|
||||
static bool chart_patch_initted;
|
||||
|
||||
static double chart_patch_hz;
|
||||
@ -163,7 +176,7 @@ static bool chart_patch_file_load(
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool chart_patch_is_chart_id(const wchar_t *str)
|
||||
static bool chart_patch_is_valid_song_id(const wchar_t *str)
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!(str[i] >= L'0' && str[i] <= L'9')) {
|
||||
@ -249,14 +262,185 @@ static void chart_patch_execute_patch_checksum()
|
||||
log_warning("Could not find checksum row for %s", chart_patch_file_1_name);
|
||||
}
|
||||
|
||||
static enum song_data_path_format chart_patch_is_song_data_path(const wchar_t *path, wchar_t *song_id)
|
||||
{
|
||||
log_assert(path);
|
||||
log_assert(song_id);
|
||||
|
||||
// Song data path for 09 to 17
|
||||
// data folder next to revision folder and working dir set to revision folder
|
||||
if (swscanf(
|
||||
path,
|
||||
// Ensure to match %lc and not %c to extract wide string chars
|
||||
L"..\\data\\sd_data%*[\\/]%lc%lc%lc%lc%*[\\/]",
|
||||
&song_id[0],
|
||||
&song_id[1],
|
||||
&song_id[2],
|
||||
&song_id[3]) == 4) {
|
||||
song_id[4] = '\0';
|
||||
|
||||
if (!chart_patch_is_valid_song_id(song_id)) {
|
||||
return SONG_DATA_PATH_INVALID;
|
||||
}
|
||||
|
||||
return SONG_DATA_PATH_09_TO_17;
|
||||
}
|
||||
|
||||
// Song data path for 18
|
||||
// data dir next to modules folder but working dir set to root folder
|
||||
if (swscanf(
|
||||
path,
|
||||
// Ensure to match %lc and not %c to extract wide string chars
|
||||
L".\\data\\sd_data%*[\\/]%lc%lc%lc%lc%*[\\/]",
|
||||
&song_id[0],
|
||||
&song_id[1],
|
||||
&song_id[2],
|
||||
&song_id[3]) == 4) {
|
||||
song_id[4] = '\0';
|
||||
|
||||
if (!chart_patch_is_valid_song_id(song_id)) {
|
||||
return SONG_DATA_PATH_INVALID;
|
||||
}
|
||||
|
||||
return SONG_DATA_PATH_18;
|
||||
}
|
||||
|
||||
// Song data path for 19
|
||||
// data dir next to modules folder but working dir set to root folder
|
||||
// ...and they had to rename sd_data to sound *tableflip*
|
||||
if (swscanf(
|
||||
path,
|
||||
// Ensure to match %lc and not %c to extract wide string chars
|
||||
L".\\data\\sound%*[\\/]%lc%lc%lc%lc%*[\\/]",
|
||||
&song_id[0],
|
||||
&song_id[1],
|
||||
&song_id[2],
|
||||
&song_id[3]) == 4) {
|
||||
song_id[4] = '\0';
|
||||
|
||||
if (!chart_patch_is_valid_song_id(song_id)) {
|
||||
return SONG_DATA_PATH_INVALID;
|
||||
}
|
||||
|
||||
return SONG_DATA_PATH_19;
|
||||
}
|
||||
|
||||
return SONG_DATA_PATH_INVALID;
|
||||
}
|
||||
|
||||
static void chart_patch_get_song_chart_file_name(const wchar_t *song_id, wchar_t *chart_file_name)
|
||||
{
|
||||
log_assert(song_id);
|
||||
log_assert(chart_file_name);
|
||||
log_assert(wcslen(song_id) == 4);
|
||||
|
||||
memcpy(chart_file_name, song_id, sizeof(wchar_t) * 4);
|
||||
chart_file_name[4] = L'.';
|
||||
chart_file_name[5] = L'1';
|
||||
chart_file_name[6] = L'\0';
|
||||
}
|
||||
|
||||
static enum song_data_file_type chart_patch_get_song_data_file_type(const wchar_t *path, const wchar_t *song_id)
|
||||
{
|
||||
wchar_t chart_file[7];
|
||||
|
||||
log_assert(path);
|
||||
log_assert(song_id);
|
||||
|
||||
chart_patch_get_song_chart_file_name(song_id, chart_file);
|
||||
|
||||
if (wstr_ends_with(path, chart_file)) {
|
||||
return SONG_DATA_FILE_TYPE_DOT_1;
|
||||
}
|
||||
|
||||
if (wstr_ends_with(path, L"osprey.bin")) {
|
||||
return SONG_DATA_FILE_TYPE_CHECKSUM;
|
||||
}
|
||||
|
||||
return SONG_DATA_FILE_TYPE_UNKNKOWN;
|
||||
}
|
||||
|
||||
static void chart_patch_get_path_dot_1_file(const wchar_t *song_id, enum song_data_path_format path_format, wchar_t *path)
|
||||
{
|
||||
switch (path_format) {
|
||||
case SONG_DATA_PATH_09_TO_17:
|
||||
// Note: These use %s also for wide strings!
|
||||
wsprintfW(
|
||||
path,
|
||||
L"..\\data\\sd_data\\%s\\%s.1",
|
||||
song_id,
|
||||
song_id);
|
||||
break;
|
||||
|
||||
case SONG_DATA_PATH_18:
|
||||
// Note: These use %s also for wide strings!
|
||||
wsprintfW(
|
||||
path,
|
||||
L".\\data\\sd_data\\%s\\%s.1",
|
||||
song_id,
|
||||
song_id);
|
||||
break;
|
||||
|
||||
case SONG_DATA_PATH_19:
|
||||
// Note: These use %s also for wide strings!
|
||||
wsprintfW(
|
||||
path,
|
||||
L".\\data\\sound\\%s\\%s.1",
|
||||
song_id,
|
||||
song_id);
|
||||
break;
|
||||
|
||||
case SONG_DATA_FILE_TYPE_UNKNKOWN:
|
||||
default:
|
||||
log_fatal("Illegal state");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void chart_patch_get_path_checksum_file(const wchar_t *song_id, enum song_data_path_format path_format, wchar_t *path)
|
||||
{
|
||||
switch (path_format) {
|
||||
case SONG_DATA_PATH_09_TO_17:
|
||||
// Note: These use %s also for wide strings!
|
||||
wsprintfW(
|
||||
path,
|
||||
L"..\\data\\sd_data\\%s\\osprey.bin",
|
||||
song_id);
|
||||
break;
|
||||
|
||||
case SONG_DATA_PATH_18:
|
||||
// Note: These use %s also for wide strings!
|
||||
wsprintfW(
|
||||
path,
|
||||
L".\\data\\sd_data\\%s\\osprey.bin",
|
||||
song_id);
|
||||
break;
|
||||
|
||||
case SONG_DATA_PATH_19:
|
||||
// Note: These use %s also for wide strings!
|
||||
wsprintfW(
|
||||
path,
|
||||
L".\\data\\sound\\%s\\osprey.bin",
|
||||
song_id);
|
||||
break;
|
||||
|
||||
case SONG_DATA_FILE_TYPE_UNKNKOWN:
|
||||
default:
|
||||
log_fatal("Illegal state");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool chart_patch_file_trap(struct irp *irp)
|
||||
{
|
||||
wchar_t buffer_1_path[1024];
|
||||
wchar_t buffer_checksum_path[1024];
|
||||
wchar_t chart_id[5];
|
||||
wchar_t chart_file[7];
|
||||
bool is_1_file;
|
||||
bool is_checksum_file;
|
||||
enum song_data_path_format path_format;
|
||||
enum song_data_file_type file_type;
|
||||
|
||||
wchar_t buffer_1_path[MAX_PATH];
|
||||
wchar_t buffer_checksum_path[MAX_PATH];
|
||||
wchar_t song_id[5];
|
||||
wchar_t chart_file_name[7];
|
||||
|
||||
char *tmp;
|
||||
|
||||
/* This has to trap three different scenarios:
|
||||
@ -266,44 +450,36 @@ static bool chart_patch_file_trap(struct irp *irp)
|
||||
In the end, we have to serve either just the .1 file or both the .1
|
||||
and checksum file from memory until the application closes one or both
|
||||
files */
|
||||
if (swscanf(
|
||||
irp->open_filename,
|
||||
L"..\\data\\sd_data%*[\\/]%c%c%c%c%*[\\/]",
|
||||
&chart_id[0],
|
||||
&chart_id[1],
|
||||
&chart_id[2],
|
||||
&chart_id[3]) == 4 &&
|
||||
chart_patch_is_chart_id(chart_id)) {
|
||||
|
||||
path_format = chart_patch_is_song_data_path(irp->open_filename, song_id);
|
||||
|
||||
if (path_format != SONG_DATA_PATH_INVALID) {
|
||||
EnterCriticalSection(&chart_patch_lock);
|
||||
|
||||
chart_id[4] = '\0';
|
||||
file_type = chart_patch_get_song_data_file_type(irp->open_filename, song_id);
|
||||
|
||||
wstr_narrow(irp->open_filename, &tmp);
|
||||
log_misc("Trapping %s...", tmp);
|
||||
free(tmp);
|
||||
|
||||
memcpy(chart_file, chart_id, sizeof(chart_id));
|
||||
chart_file[4] = L'.';
|
||||
chart_file[5] = L'1';
|
||||
chart_file[6] = L'\0';
|
||||
|
||||
is_1_file = wstr_ends_with(irp->open_filename, chart_file);
|
||||
is_checksum_file = wstr_ends_with(irp->open_filename, L"osprey.bin");
|
||||
// %S for printing wide strings
|
||||
log_misc("Trapping song ID %S, path format %d, file type %d, path %S", song_id, path_format, file_type, irp->open_filename);
|
||||
|
||||
/* Block a second open call to either .1 or checksum file if detouring
|
||||
is already active */
|
||||
if (chart_patch_file_detour) {
|
||||
if (is_1_file) {
|
||||
irp->fd = chart_patch_file_1.fd;
|
||||
chart_patch_file_1.active = true;
|
||||
} else if (is_checksum_file) {
|
||||
irp->fd = chart_patch_file_checksum.fd;
|
||||
chart_patch_file_checksum.active = true;
|
||||
} else {
|
||||
LeaveCriticalSection(&chart_patch_lock);
|
||||
/* other file, like *.2dx */
|
||||
return false;
|
||||
switch (file_type) {
|
||||
case SONG_DATA_FILE_TYPE_DOT_1:
|
||||
irp->fd = chart_patch_file_1.fd;
|
||||
chart_patch_file_1.active = true;
|
||||
break;
|
||||
|
||||
case SONG_DATA_FILE_TYPE_CHECKSUM:
|
||||
irp->fd = chart_patch_file_checksum.fd;
|
||||
chart_patch_file_checksum.active = true;
|
||||
break;
|
||||
|
||||
case SONG_DATA_FILE_TYPE_UNKNKOWN:
|
||||
default:
|
||||
LeaveCriticalSection(&chart_patch_lock);
|
||||
/* other file, like *.2dx */
|
||||
return false;
|
||||
}
|
||||
|
||||
log_misc("Data already prepared");
|
||||
@ -313,31 +489,21 @@ static bool chart_patch_file_trap(struct irp *irp)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_1_file || is_checksum_file) {
|
||||
wstr_narrow(chart_id, &tmp);
|
||||
log_misc("Preparing in-memory chart %s...", tmp);
|
||||
free(tmp);
|
||||
if (file_type == SONG_DATA_FILE_TYPE_DOT_1 || file_type == SONG_DATA_FILE_TYPE_CHECKSUM) {
|
||||
log_misc("Preparing in-memory chart data for song ID %S...", song_id);
|
||||
|
||||
wsprintfW(
|
||||
buffer_1_path,
|
||||
L"..\\data\\sd_data\\\\%s\\%s.1",
|
||||
chart_id,
|
||||
chart_id);
|
||||
wsprintfW(
|
||||
buffer_checksum_path,
|
||||
L"..\\data\\sd_data\\%s\\osprey.bin",
|
||||
chart_id);
|
||||
chart_patch_get_song_chart_file_name(song_id, chart_file_name);
|
||||
chart_patch_get_path_dot_1_file(song_id, path_format, buffer_1_path);
|
||||
chart_patch_get_path_checksum_file(song_id, path_format, buffer_checksum_path);
|
||||
|
||||
if (!chart_patch_file_load(
|
||||
irp, &chart_patch_file_1, buffer_1_path)) {
|
||||
wstr_narrow(buffer_1_path, &tmp);
|
||||
log_fatal("Cannot load .1 file %s", tmp);
|
||||
free(tmp);
|
||||
log_fatal("Cannot load .1 file %S", buffer_1_path);
|
||||
}
|
||||
|
||||
chart_patch_execute_patch_1();
|
||||
|
||||
wstr_narrow(chart_file, &tmp);
|
||||
wstr_narrow(chart_file_name, &tmp);
|
||||
memcpy(
|
||||
chart_patch_file_1_name, tmp, sizeof(chart_patch_file_1_name));
|
||||
free(tmp);
|
||||
@ -349,19 +515,24 @@ static bool chart_patch_file_trap(struct irp *irp)
|
||||
}
|
||||
|
||||
/* Return dummy handle */
|
||||
if (is_1_file) {
|
||||
irp->fd = chart_patch_file_1.fd;
|
||||
chart_patch_file_1.active = true;
|
||||
} else if (is_checksum_file) {
|
||||
irp->fd = chart_patch_file_checksum.fd;
|
||||
chart_patch_file_checksum.active = true;
|
||||
} else {
|
||||
log_fatal("Illegal state 2");
|
||||
switch (file_type) {
|
||||
case SONG_DATA_FILE_TYPE_DOT_1:
|
||||
irp->fd = chart_patch_file_1.fd;
|
||||
chart_patch_file_1.active = true;
|
||||
break;
|
||||
|
||||
case SONG_DATA_FILE_TYPE_CHECKSUM:
|
||||
irp->fd = chart_patch_file_checksum.fd;
|
||||
chart_patch_file_checksum.active = true;
|
||||
break;
|
||||
|
||||
case SONG_DATA_FILE_TYPE_UNKNKOWN:
|
||||
default:
|
||||
log_fatal("Illegal state 2");
|
||||
break;
|
||||
}
|
||||
|
||||
wstr_narrow(chart_id, &tmp);
|
||||
log_misc("Patch for %s prepared in memory", tmp);
|
||||
free(tmp);
|
||||
log_misc("Chart patch for song ID %S prepared in memory", song_id);
|
||||
|
||||
chart_patch_file_detour = true;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user