in doom_py/src/vizdoom/src/wildmidi/wildmidi_lib.cpp [662:1192]
static int WM_LoadConfig(const char *config_file) {
unsigned long int config_size = 0;
char *config_buffer = NULL;
const char *dir_end = NULL;
char *config_dir = NULL;
unsigned long int config_ptr = 0;
unsigned long int line_start_ptr = 0;
unsigned short int patchid = 0;
struct _patch * tmp_patch;
char **line_tokens = NULL;
int token_count = 0;
config_buffer = (char *) _WM_BufferFile(config_file, &config_size, true);
if (!config_buffer) {
WM_FreePatches();
return -1;
}
// This part was rewritten because the original depended on a header that was GPL'd.
dir_end = strrchr(config_file, '/');
#ifdef _WIN32
const char *dir_end2 = strrchr(config_file, '\\');
if (dir_end2 > dir_end) dir_end = dir_end2;
#endif
if (dir_end) {
config_dir = (char*)malloc((dir_end - config_file + 2));
if (config_dir == NULL) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse config",
errno);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0);
WM_FreePatches();
free(config_buffer);
return -1;
}
strncpy(config_dir, config_file, (dir_end - config_file + 1));
config_dir[dir_end - config_file + 1] = '\0';
}
config_ptr = 0;
line_start_ptr = 0;
/* handle files without a newline at the end: this relies on
* _WM_BufferFile() allocating the buffer with one extra byte */
config_buffer[config_size] = '\n';
while (config_ptr <= config_size) {
if (config_buffer[config_ptr] == '\r' ||
config_buffer[config_ptr] == '\n')
{
config_buffer[config_ptr] = '\0';
if (config_ptr != line_start_ptr) {
line_tokens = WM_LC_Tokenize_Line(&config_buffer[line_start_ptr]);
if (line_tokens) {
if (stricmp(line_tokens[0], "dir") == 0) {
free(config_dir);
if (!line_tokens[1]) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(missing name in dir line)", 0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(line_tokens);
free(config_buffer);
return -1;
} else if (!(config_dir = wm_strdup(line_tokens[1]))) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM,
"to parse config", errno);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(line_tokens);
free(config_buffer);
return -1;
}
if (!IS_DIR_SEPARATOR(config_dir[strlen(config_dir) - 1])) {
config_dir[strlen(config_dir) + 1] = '\0';
config_dir[strlen(config_dir)] = '/';
}
} else if (stricmp(line_tokens[0], "source") == 0) {
char *new_config = NULL;
if (!line_tokens[1]) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(missing name in source line)", 0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(line_tokens);
free(config_buffer);
return -1;
} else if (!IS_ABSOLUTE_PATH(line_tokens[1]) && config_dir) {
new_config = (char*)malloc(
strlen(config_dir) + strlen(line_tokens[1])
+ 1);
if (new_config == NULL) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM,
"to parse config", errno);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
strcpy(new_config, config_dir);
strcpy(&new_config[strlen(config_dir)], line_tokens[1]);
} else {
if (!(new_config = wm_strdup(line_tokens[1]))) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM,
"to parse config", errno);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(line_tokens);
free(config_buffer);
return -1;
}
}
if (WM_LoadConfig(new_config) == -1) {
free(new_config);
free(line_tokens);
free(config_buffer);
free(config_dir);
return -1;
}
free(new_config);
} else if (stricmp(line_tokens[0], "bank") == 0) {
if (!line_tokens[1] || !wm_isdigit(line_tokens[1][0])) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(syntax error in bank line)", 0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
patchid = (atoi(line_tokens[1]) & 0xFF) << 8;
} else if (stricmp(line_tokens[0], "drumset") == 0) {
if (!line_tokens[1] || !wm_isdigit(line_tokens[1][0])) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(syntax error in drumset line)", 0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
patchid = ((atoi(line_tokens[1]) & 0xFF) << 8) | 0x80;
} else if (stricmp(line_tokens[0], "reverb_room_width") == 0) {
if (!line_tokens[1] || !wm_isdigit(line_tokens[1][0])) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(syntax error in reverb_room_width line)",
0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
reverb_room_width = (float) atof(line_tokens[1]);
if (reverb_room_width < 1.0f) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(reverb_room_width < 1 meter, setting to minimum of 1 meter)",
0);
reverb_room_width = 1.0f;
} else if (reverb_room_width > 100.0f) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(reverb_room_width > 100 meters, setting to maximum of 100 meters)",
0);
reverb_room_width = 100.0f;
}
} else if (stricmp(line_tokens[0], "reverb_room_length") == 0) {
if (!line_tokens[1] || !wm_isdigit(line_tokens[1][0])) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(syntax error in reverb_room_length line)",
0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
reverb_room_length = (float) atof(line_tokens[1]);
if (reverb_room_length < 1.0f) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(reverb_room_length < 1 meter, setting to minimum of 1 meter)",
0);
reverb_room_length = 1.0f;
} else if (reverb_room_length > 100.0f) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(reverb_room_length > 100 meters, setting to maximum of 100 meters)",
0);
reverb_room_length = 100.0f;
}
} else if (stricmp(line_tokens[0], "reverb_listener_posx") == 0) {
if (!line_tokens[1] || !wm_isdigit(line_tokens[1][0])) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(syntax error in reverb_listen_posx line)",
0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
reverb_listen_posx = (float) atof(line_tokens[1]);
if ((reverb_listen_posx > reverb_room_width)
|| (reverb_listen_posx < 0.0f)) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(reverb_listen_posx set outside of room)",
0);
reverb_listen_posx = reverb_room_width / 2.0f;
}
} else if (stricmp(line_tokens[0],
"reverb_listener_posy") == 0) {
if (!line_tokens[1] || !wm_isdigit(line_tokens[1][0])) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(syntax error in reverb_listen_posy line)",
0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
reverb_listen_posy = (float) atof(line_tokens[1]);
if ((reverb_listen_posy > reverb_room_width)
|| (reverb_listen_posy < 0.0f)) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(reverb_listen_posy set outside of room)",
0);
reverb_listen_posy = reverb_room_length * 0.75f;
}
} else if (stricmp(line_tokens[0],
"guspat_editor_author_cant_read_so_fix_release_time_for_me")
== 0) {
fix_release = 1;
} else if (stricmp(line_tokens[0], "auto_amp") == 0) {
auto_amp = 1;
} else if (stricmp(line_tokens[0], "auto_amp_with_amp")
== 0) {
auto_amp = 1;
auto_amp_with_amp = 1;
} else if (wm_isdigit(line_tokens[0][0])) {
patchid = (patchid & 0xFF80)
| (atoi(line_tokens[0]) & 0x7F);
if (patch[(patchid & 0x7F)] == NULL) {
patch[(patchid & 0x7F)] = (struct _patch*)malloc(
sizeof(struct _patch));
if (patch[(patchid & 0x7F)] == NULL) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM,
NULL, errno);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
tmp_patch = patch[(patchid & 0x7F)];
tmp_patch->patchid = patchid;
tmp_patch->filename = NULL;
tmp_patch->amp = 1024;
tmp_patch->note = 0;
tmp_patch->next = NULL;
tmp_patch->first_sample = NULL;
tmp_patch->loaded = 0;
tmp_patch->inuse_count = 0;
} else {
tmp_patch = patch[(patchid & 0x7F)];
if (tmp_patch->patchid == patchid) {
free(tmp_patch->filename);
tmp_patch->filename = NULL;
tmp_patch->amp = 1024;
tmp_patch->note = 0;
} else {
if (tmp_patch->next) {
while (tmp_patch->next) {
if (tmp_patch->next->patchid == patchid)
break;
tmp_patch = tmp_patch->next;
}
if (tmp_patch->next == NULL) {
if ((tmp_patch->next = (struct _patch*)malloc(
sizeof(struct _patch)))
== NULL) {
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_MEM, NULL, 0);
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_LOAD, config_file,
0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
tmp_patch = tmp_patch->next;
tmp_patch->patchid = patchid;
tmp_patch->filename = NULL;
tmp_patch->amp = 1024;
tmp_patch->note = 0;
tmp_patch->next = NULL;
tmp_patch->first_sample = NULL;
tmp_patch->loaded = 0;
tmp_patch->inuse_count = 0;
} else {
tmp_patch = tmp_patch->next;
free(tmp_patch->filename);
tmp_patch->filename = NULL;
tmp_patch->amp = 1024;
tmp_patch->note = 0;
}
} else {
tmp_patch->next = (struct _patch*)malloc(
sizeof(struct _patch));
if (tmp_patch->next == NULL) {
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_MEM, NULL, errno);
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_LOAD, config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
tmp_patch = tmp_patch->next;
tmp_patch->patchid = patchid;
tmp_patch->filename = NULL;
tmp_patch->amp = 1024;
tmp_patch->note = 0;
tmp_patch->next = NULL;
tmp_patch->first_sample = NULL;
tmp_patch->loaded = 0;
tmp_patch->inuse_count = 0;
}
}
}
if (!line_tokens[1]) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG,
"(missing name in patch line)", 0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
} else if (!IS_ABSOLUTE_PATH(line_tokens[1]) && config_dir) {
tmp_patch->filename = (char*)malloc(
strlen(config_dir) + strlen(line_tokens[1])
+ 5);
if (tmp_patch->filename == NULL) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM,
NULL, 0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
strcpy(tmp_patch->filename, config_dir);
strcat(tmp_patch->filename, line_tokens[1]);
} else {
if (!(tmp_patch->filename = wm_strdup(line_tokens[1]))) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM,
NULL, 0);
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD,
config_file, 0);
WM_FreePatches();
free(config_dir);
free(line_tokens);
free(config_buffer);
return -1;
}
}
if (strnicmp(
&tmp_patch->filename[strlen(tmp_patch->filename)
- 4], ".pat", 4) != 0) {
strcat(tmp_patch->filename, ".pat");
}
tmp_patch->env[0].set = 0x00;
tmp_patch->env[1].set = 0x00;
tmp_patch->env[2].set = 0x00;
tmp_patch->env[3].set = 0x00;
tmp_patch->env[4].set = 0x00;
tmp_patch->env[5].set = 0x00;
tmp_patch->keep = 0;
tmp_patch->remove = 0;
token_count = 0;
while (line_tokens[token_count]) {
if (strnicmp(line_tokens[token_count], "amp=", 4)
== 0) {
if (!wm_isdigit(line_tokens[token_count][4])) {
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_INVALID_ARG,
"(syntax error in patch line)", 0);
} else {
tmp_patch->amp = (atoi(
&line_tokens[token_count][4]) << 10)
/ 100;
}
} else if (strnicmp(line_tokens[token_count],
"note=", 5) == 0) {
if (!wm_isdigit(line_tokens[token_count][5])) {
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_INVALID_ARG,
"(syntax error in patch line)", 0);
} else {
tmp_patch->note = atoi(
&line_tokens[token_count][5]);
}
} else if (strnicmp(line_tokens[token_count],
"env_time", 8) == 0) {
if ((!wm_isdigit(line_tokens[token_count][8]))
|| (!wm_isdigit(
line_tokens[token_count][10]))
|| (line_tokens[token_count][9] != '=')) {
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_INVALID_ARG,
"(syntax error in patch line)", 0);
} else {
unsigned int env_no = atoi(
&line_tokens[token_count][8]);
if (env_no > 5) {
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_INVALID_ARG,
"(syntax error in patch line)",
0);
} else {
tmp_patch->env[env_no].time =
(float) atof(
&line_tokens[token_count][10]);
if ((tmp_patch->env[env_no].time
> 45000.0f)
|| (tmp_patch->env[env_no].time
< 1.47f)) {
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_INVALID_ARG,
"(range error in patch line)",
0);
tmp_patch->env[env_no].set &= 0xFE;
} else {
tmp_patch->env[env_no].set |= 0x01;
}
}
}
} else if (strnicmp(line_tokens[token_count],
"env_level", 9) == 0) {
if ((!wm_isdigit(line_tokens[token_count][9]))
|| (!wm_isdigit(
line_tokens[token_count][11]))
|| (line_tokens[token_count][10] != '=')) {
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_INVALID_ARG,
"(syntax error in patch line)", 0);
} else {
unsigned int env_no = atoi(
&line_tokens[token_count][9]);
if (env_no > 5) {
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_INVALID_ARG,
"(syntax error in patch line)",
0);
} else {
tmp_patch->env[env_no].level =
(float) atof(
&line_tokens[token_count][11]);
if ((tmp_patch->env[env_no].level > 1.0f)
|| (tmp_patch->env[env_no].level
< 0.0f)) {
_WM_ERROR(__FUNCTION__, __LINE__,
WM_ERR_INVALID_ARG,
"(range error in patch line)",
0);
tmp_patch->env[env_no].set &= 0xFD;
} else {
tmp_patch->env[env_no].set |= 0x02;
}
}
}
} else if (stricmp(line_tokens[token_count],
"keep=loop") == 0) {
tmp_patch->keep |= SAMPLE_LOOP;
} else if (stricmp(line_tokens[token_count],
"keep=env") == 0) {
tmp_patch->keep |= SAMPLE_ENVELOPE;
} else if (stricmp(line_tokens[token_count],
"remove=sustain") == 0) {
tmp_patch->remove |= SAMPLE_SUSTAIN;
} else if (stricmp(line_tokens[token_count],
"remove=clamped") == 0) {
tmp_patch->remove |= SAMPLE_CLAMPED;
}
token_count++;
}
}
}
/* free up tokens */
free(line_tokens);
}
line_start_ptr = config_ptr + 1;
}
config_ptr++;
}
free(config_buffer);
free(config_dir);
return 0;
}