Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map parsing failure #36

Merged
merged 10 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 41 additions & 19 deletions src/beatmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static void hitpoint_to_action(char *keys, struct hitpoint *point,

/**
* Returns a randomly generated number in the range of [0, range], while
* attemting to constrain it outside of a bound(ary) given in percent (]0, 1[),
* attempting to constrain it outside of a bound(ary) given in percent (]0, 1[),
* in a given number of rounds.
*/
static int generate_number(int range, int rounds, double bound);
Expand Down Expand Up @@ -69,7 +69,7 @@ size_t find_beatmap(char *base, char *partial, char **map)
strcpy(*map, base);
// A.p. to the beatmap folder.
strcpy(*map + base_len, folder);
// Add a trailing seperator and terminating zero.
// Add a trailing separator and terminating zero.
strcpy(*map + base_len + folder_len, (char[2]){(char)SEPERATOR, '\0'});

free(folder);
Expand All @@ -95,7 +95,7 @@ size_t find_beatmap(char *base, char *partial, char **map)
// Verify that the file we found is a beatmap.
if (strcmp(*map + map_len - 4, ".osu") != 0) {
debug("%s is not a beatmap", *map);

free(*map);

return 0;
Expand All @@ -109,6 +109,8 @@ size_t find_beatmap(char *base, char *partial, char **map)
size_t parse_beatmap(char *file, struct hitpoint **points,
struct beatmap_meta **meta)
{
debug("parsing beatmap '%s'", file);

if (!points || !meta || !file) {
debug("received null pointer");
return 0;
Expand All @@ -121,12 +123,24 @@ size_t parse_beatmap(char *file, struct hitpoint **points,
return 0;
}

*points = NULL;
*meta = calloc(1, sizeof(struct beatmap_meta));

const size_t line_len = 256;
char *line = malloc(line_len);

// First line always contains version.
if (fgets(line, (int)line_len, stream)) {
short version = (short)strtol(line + 17, NULL, 10);

debug("beatmap version is %d", version);

if (version < MIN_VERSION || version > MAX_VERSION) {
printf("parsing an unsupported beatmap (%d)",
version);
}
}

*points = NULL;
*meta = calloc(1, sizeof(struct beatmap_meta));

struct hitpoint cur_point;
size_t hp_size = sizeof(struct hitpoint), num_parsed = 0;

Expand All @@ -150,7 +164,15 @@ size_t parse_beatmap(char *file, struct hitpoint **points,

if (line[0] == '[') {
strcpy(cur_section, line);
cur_section[strlen(cur_section) - 1] = '\0';

const int len = (int)strlen(line);
for (int i = 0; i < len; i++) {
if (line[i] == ']') {
cur_section[i + 1] = '\0';
}
}

debug("current section is now '%s'", cur_section);
}
}

Expand All @@ -164,7 +186,7 @@ size_t parse_beatmap(char *file, struct hitpoint **points,
static int parse_beatmap_line(char *line, struct beatmap_meta *meta)
{
int i = 0;
// strtok() modfies its arguments, work with a copy.
// strtok() modifies its arguments, work with a copy.
char *ln = strdup(line);
char *token = NULL, *key = NULL, *value = NULL;

Expand Down Expand Up @@ -200,33 +222,33 @@ static void parse_beatmap_token(char *key, char *value,
return;
}

// Always ignore last two characters since .osu files are CRLF by
// default.
if (!(strcmp(key, "Title"))) {
value[strlen(value) - 2] = '\0';
value[strlen(value)] = '\0';

strcpy(meta->title, value);
} else if (!(strcmp(key, "Artist"))) {
value[strlen(value) - 2] = '\0';
value[strlen(value)] = '\0';

strcpy(meta->artist, value);
} else if (!(strcmp(key, "Version"))) {
value[strlen(value) - 2] = '\0';
value[strlen(value)] = '\0';

strcpy(meta->version, value);
} else if (!(strcmp(key, "BeatmapID"))) {
meta->map_id = atoi(value);
} else if (!(strcmp(key, "BeatmapSetID"))) {
meta->set_id = atoi(value);
} else if (!(strcmp(key, "CircleSize"))) {
meta->columns = atoi(value);
// meta->columns = atoi(value);
// This worked with v12 and maybe also v13 but not with v14.
meta->columns = 4;
}
}

// TODO: This function is not thread safe.
static int parse_hitobject_line(char *line, int columns, struct hitpoint *point)
{
int secval = 0, end_time = 0, slider = 0, i = 0;
int secval = 0, end_time = 0, hold = 0, i = 0;
char *ln = strdup(line), *token = NULL;

// Line is expected to follow the following format:
Expand All @@ -240,16 +262,16 @@ static int parse_hitobject_line(char *line, int columns, struct hitpoint *point)
case 0: point->column = secval / (COLS_WIDTH / columns);
break;
// Start time
case 2: point->start_time = secval;
case 2: point->start_time = secval - 15;
break;
// Type
case 3: slider = secval & TYPE_SLIDER;
case 3: hold = secval & TYPE_HOLD;
break;
// Extra string, first element is either 0 or end time
case 5:
end_time = (int)strtol(strtok(token, ":"), NULL, 10);

point->end_time = slider ? end_time :
point->end_time = hold ? end_time :
point->start_time + TAPTIME_MS;

break;
Expand Down Expand Up @@ -358,7 +380,7 @@ void humanize_hitpoints(int total, struct hitpoint **points, int level)

// [0, level]
offset = generate_number(level, RNG_ROUNDS, RNG_BOUNDARY);

// [-(level / 2), (level / 2)]
offset -= (level / 2);

Expand Down
8 changes: 6 additions & 2 deletions src/beatmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
#define RNG_ROUNDS 50
#define RNG_BOUNDARY 0.5

#define TYPE_SLIDER 128
// 7th bit in type is hold
#define TYPE_HOLD 128

#define MIN_VERSION 12
#define MAX_VERSION 14

struct beatmap_meta {
int set_id;
Expand Down Expand Up @@ -45,7 +49,7 @@ struct action {
size_t find_beatmap(char *base, char *partial, char **map);

/**
* Parse a beatmap file (*.osu) into an array of hitpoint structs pointed to by
* Parse a beatmap file (*.osu) into an array of hitpoint structs pointed to by
* **points and a metadata struct.
* Returns the number of points parsed and stored.
*/
Expand Down
11 changes: 8 additions & 3 deletions src/game.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ hot inline void send_keypress(int key, int down)
in.ki.dwExtraInfo = 0;
in.ki.dwFlags = down ? 0 : KEYEVENTF_KEYUP;
in.ki.wVk = VkKeyScanEx(key, GetKeyboardLayout(0)) & 0xFF;

# ifdef DEBUG
if (!SendInput(1, &in, sizeof(INPUT))) {
debug("failed sending input: %lu", GetLastError());
}
# else
SendInput(1, &in, sizeof(INPUT));
# endif /* DEBUG */
#endif /* ON_WINDOWS */
}

Expand Down Expand Up @@ -73,7 +78,7 @@ void do_setup()

return;
}

debug("opened X display (%#x)", (unsigned)(intptr_t)display);
#endif /* ON_LINUX */

Expand All @@ -82,7 +87,7 @@ void do_setup()
printf("failed to get handle to game process\n");
return;
}

debug("got handle to game process with ID %d",
(int)game_proc_id);
#endif /* ON_WINDOWS */
Expand Down
24 changes: 20 additions & 4 deletions src/maniac.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,18 +187,26 @@ static int play(char *map)
{
struct hitpoint *points = NULL;
struct beatmap_meta *meta = NULL;
int num_points = parse_beatmap(map, &points, &meta);
int num_points = (int)parse_beatmap(map, &points, &meta);
if (!num_points || !points || !meta) {
debug("num_points = %i, points = %p, meta = %p", num_points,
points, meta);

(void *)points, (void *)meta);
printf("failed to parse beatmap (%s)\n", map);

return PLAY_ERROR;
}

printf("parsed %d hitpoints of map '%s' ('%s', %d)\n", num_points,
meta->title, meta->version, meta->map_id);

#ifdef DEBUG
for (int i = 0; i < num_points; i++) {
struct hitpoint *point = &points[i];
debug("point %d: (col: %d, start: %d, end: %d)", i, point->column,
point->start_time, point->end_time);
}
#endif /* DEBUG */

humanize_hitpoints(num_points, &points, delay);

debug("humanized %d hitpoints with delay of %d", num_points, delay);
Expand All @@ -213,6 +221,14 @@ static int play(char *map)

debug("parsed %d actions", num_actions);

#ifdef DEBUG
for (int i = 0; i < num_actions; i++) {
struct action *action = &actions[i];
debug("action %d: (t: %d, k: %c/%d, d: %d)", i, action->time,
action->key, action->key, action->down);
}
#endif /* DEBUG */

free(points);

if (sort_actions(num_actions, &actions) != 0) {
Expand Down Expand Up @@ -261,7 +277,7 @@ static void play_loop(struct action *actions, int num_actions)
}

time = get_maptime();
debug("time %i", time);
// debug("time %i", time);

while (cur_i < num_actions &&
(cur_a = actions + cur_i)->time < time)
Expand Down