Various bugfixes and features for the upcoming iidx multidisk release #236

Merged
icex2 merged 38 commits from timebase-tool into master 2023-04-06 16:39:53 +03:00
Showing only changes of commit d8d5a512b4 - Show all commits
+236 -65
View File
@@ -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;