#include "beatmap.h" #include "beatmapreader.h" #include "util.h" #include #include #include #include SDL_EnumerationResult handleBeatmapKeyValue(char* section, char* key, char* value, void* userdata) { struct Osu_Beatmap* beatmap = userdata; if (strcmp(section, "Metadata") == 0) { if (strcmp(key, "Title") == 0) { SDL_asprintf(&beatmap->title, "%s", value); } else if (strcmp(key, "TitleUnicode") == 0) { SDL_asprintf(&beatmap->titleUnicode, "%s", value); } else if (strcmp(key, "Artist") == 0) { SDL_asprintf(&beatmap->artist, "%s", value); } else if (strcmp(key, "ArtistUnicode") == 0) { SDL_asprintf(&beatmap->artistUnicode, "%s", value); } else if (strcmp(key, "Creator") == 0) { SDL_asprintf(&beatmap->creator, "%s", value); } else if (strcmp(key, "Version") == 0) { SDL_asprintf(&beatmap->version, "%s", value); } else if (strcmp(key, "Source") == 0) { SDL_asprintf(&beatmap->source, "%s", value); } else if (strcmp(key, "Tags") == 0) { SDL_asprintf(&beatmap->tags, "%s", value); } else if (strcmp(key, "BeatmapID") == 0) { SDL_asprintf(&beatmap->beatmapID, "%s", value); } else if (strcmp(key, "BeatmapSetID") == 0) { SDL_asprintf(&beatmap->beatmapSetID, "%s", value); } } else if (strcmp(section, "General") == 0) { if (strcmp(key, "AudioFilename") == 0) { SDL_asprintf(&beatmap->audioFilename, "%s/%s", beatmap->dirname, value); } else if (strcmp(key, "AudioLeadIn") == 0) { beatmap->audioLeadIn = atoi(value); if (beatmap->audioLeadIn < 0) { beatmap->audioLeadIn = 0; } } else if (strcmp(key, "PreviewTime") == 0) { beatmap->previewTime = atoi(value); if (beatmap->previewTime < 0) { beatmap->previewTime = 0; } } } // TODO: End enumeration early if all data has been read. return SDL_ENUM_CONTINUE; } SDL_EnumerationResult handleBeatmapCSVRow(char* section, char** values, size_t valuesLen, void* userdata) { struct Osu_Beatmap* beatmap = userdata; SDL_assert(valuesLen > 0); if (SDL_strcmp(section, "Events") == 0) { SDL_assert(valuesLen > 2); if (SDL_strcmp(values[0], "0") == 0 && SDL_strcmp(values[1], "0") == 0 && !beatmap->backgroundPath) { const char* value = values[2]; OSU_LOG_TRACE(value); char* begin = strchr(value, '"'); char* end = strrchr(value, '"'); SDL_assert(begin); SDL_assert(end); SDL_assert(begin < end); begin++; size_t filenameLen = end - begin; OSU_LOG_TRACEF("%z", filenameLen); size_t totalLen = strlen(beatmap->dirname) + 1 + filenameLen + 1; // +1 for /, +1 for null terminator char* filepath = malloc(totalLen); strncpy(filepath, beatmap->dirname, strlen(beatmap->dirname)); filepath[strlen(beatmap->dirname)] = '/'; strncpy(filepath + strlen(beatmap->dirname) + 1, begin, filenameLen); filepath[totalLen - 1] = 0; beatmap->backgroundPath = filepath; } } return SDL_ENUM_CONTINUE; } struct Osu_Beatmap* Osu_LoadBeatmap(const char* filepath) { OSU_LOG_TRACEF("Loading beatmap file: %s", filepath); char* file = SDL_LoadFile(filepath, NULL); if (!file) { OSU_LOG_TRACEF("Unable to load file: %s", SDL_GetError()); return NULL; } struct Osu_Beatmap* beatmap = calloc(1, sizeof(struct Osu_Beatmap)); SDL_asprintf(&beatmap->filepath, "%s", filepath); SDL_asprintf(&beatmap->dirname, "%s", filepath); dirname(beatmap->dirname); beatmap->audioLeadIn = 0; beatmap->previewTime = 0; if (!Osu_EnumerateBeatmapData(file, &handleBeatmapKeyValue, &handleBeatmapCSVRow, beatmap)) { Osu_DestroyBeatmap(beatmap); SDL_free(file); return NULL; } SDL_free(file); return beatmap; } void Osu_DestroyBeatmap(struct Osu_Beatmap* beatmap) { if (!beatmap) { return; } free(beatmap->filepath); free(beatmap->dirname); free(beatmap->audioFilename); free(beatmap->title); free(beatmap->titleUnicode); free(beatmap->artist); free(beatmap->artistUnicode); free(beatmap->creator); free(beatmap->version); free(beatmap->source); free(beatmap->tags); free(beatmap->beatmapID); free(beatmap->beatmapSetID); free(beatmap->backgroundPath); free(beatmap); }