z_mirror/sdl-osu

git clone https://git.raiguard.me/z_mirror/sdl-osu

Caleb HeuerSwitch to four-space indents and inline braces836a89c

trunk
4.6 KiB134 linesraw
1#include "beatmap.h"
2#include "beatmapreader.h"
3#include "util.h"
4#include <libgen.h>
5#include <SDL3/SDL.h>
6#include <stdio.h>
7#include <stdlib.h>
8
9SDL_EnumerationResult handleBeatmapKeyValue(char* section, char* key, char* value, void* userdata) {
10    struct Osu_Beatmap* beatmap = userdata;
11
12    if (strcmp(section, "Metadata") == 0) {
13        if (strcmp(key, "Title") == 0) {
14            SDL_asprintf(&beatmap->title, "%s", value);
15        } else if (strcmp(key, "TitleUnicode") == 0) {
16            SDL_asprintf(&beatmap->titleUnicode, "%s", value);
17        } else if (strcmp(key, "Artist") == 0) {
18            SDL_asprintf(&beatmap->artist, "%s", value);
19        } else if (strcmp(key, "ArtistUnicode") == 0) {
20            SDL_asprintf(&beatmap->artistUnicode, "%s", value);
21        } else if (strcmp(key, "Creator") == 0) {
22            SDL_asprintf(&beatmap->creator, "%s", value);
23        } else if (strcmp(key, "Version") == 0) {
24            SDL_asprintf(&beatmap->version, "%s", value);
25        } else if (strcmp(key, "Source") == 0) {
26            SDL_asprintf(&beatmap->source, "%s", value);
27        } else if (strcmp(key, "Tags") == 0) {
28            SDL_asprintf(&beatmap->tags, "%s", value);
29        } else if (strcmp(key, "BeatmapID") == 0) {
30            SDL_asprintf(&beatmap->beatmapID, "%s", value);
31        } else if (strcmp(key, "BeatmapSetID") == 0) {
32            SDL_asprintf(&beatmap->beatmapSetID, "%s", value);
33        }
34    } else if (strcmp(section, "General") == 0) {
35        if (strcmp(key, "AudioFilename") == 0) {
36            SDL_asprintf(&beatmap->audioFilename, "%s/%s", beatmap->dirname, value);
37        } else if (strcmp(key, "AudioLeadIn") == 0) {
38            beatmap->audioLeadIn = atoi(value);
39            if (beatmap->audioLeadIn < 0) {
40                beatmap->audioLeadIn = 0;
41            }
42        } else if (strcmp(key, "PreviewTime") == 0) {
43            beatmap->previewTime = atoi(value);
44            if (beatmap->previewTime < 0) {
45                beatmap->previewTime = 0;
46            }
47        }
48    }
49
50    // TODO: End enumeration early if all data has been read.
51
52    return SDL_ENUM_CONTINUE;
53}
54
55SDL_EnumerationResult handleBeatmapCSVRow(char* section, char** values, size_t valuesLen, void* userdata) {
56    struct Osu_Beatmap* beatmap = userdata;
57
58    SDL_assert(valuesLen > 0);
59    if (SDL_strcmp(section, "Events") == 0) {
60        SDL_assert(valuesLen > 2);
61        if (SDL_strcmp(values[0], "0") == 0 && SDL_strcmp(values[1], "0") == 0 && !beatmap->backgroundPath) {
62            const char* value = values[2];
63            OSU_LOG_TRACE(value);
64            char* begin = strchr(value, '"');
65            char* end = strrchr(value, '"');
66            SDL_assert(begin);
67            SDL_assert(end);
68            SDL_assert(begin < end);
69            begin++;
70            size_t filenameLen = end - begin;
71            OSU_LOG_TRACEF("%z", filenameLen);
72            size_t totalLen = strlen(beatmap->dirname) + 1 + filenameLen + 1; // +1 for /, +1 for null terminator
73            char* filepath = malloc(totalLen);
74            strncpy(filepath, beatmap->dirname, strlen(beatmap->dirname));
75            filepath[strlen(beatmap->dirname)] = '/';
76            strncpy(filepath + strlen(beatmap->dirname) + 1, begin, filenameLen);
77            filepath[totalLen - 1] = 0;
78            beatmap->backgroundPath = filepath;
79        }
80    }
81    return SDL_ENUM_CONTINUE;
82}
83
84struct Osu_Beatmap* Osu_LoadBeatmap(const char* filepath) {
85    OSU_LOG_TRACEF("Loading beatmap file: %s", filepath);
86    char* file = SDL_LoadFile(filepath, NULL);
87    if (!file) {
88        OSU_LOG_TRACEF("Unable to load file: %s", SDL_GetError());
89        return NULL;
90    }
91
92    struct Osu_Beatmap* beatmap = calloc(1, sizeof(struct Osu_Beatmap));
93    SDL_asprintf(&beatmap->filepath, "%s", filepath);
94    SDL_asprintf(&beatmap->dirname, "%s", filepath);
95    dirname(beatmap->dirname);
96
97    beatmap->audioLeadIn = 0;
98    beatmap->previewTime = 0;
99
100    if (!Osu_EnumerateBeatmapData(file, &handleBeatmapKeyValue, &handleBeatmapCSVRow, beatmap)) {
101        Osu_DestroyBeatmap(beatmap);
102        SDL_free(file);
103        return NULL;
104    }
105
106    SDL_free(file);
107    return beatmap;
108}
109
110void Osu_DestroyBeatmap(struct Osu_Beatmap* beatmap) {
111    if (!beatmap) {
112        return;
113    }
114
115    free(beatmap->filepath);
116    free(beatmap->dirname);
117
118    free(beatmap->audioFilename);
119
120    free(beatmap->title);
121    free(beatmap->titleUnicode);
122    free(beatmap->artist);
123    free(beatmap->artistUnicode);
124    free(beatmap->creator);
125    free(beatmap->version);
126    free(beatmap->source);
127    free(beatmap->tags);
128    free(beatmap->beatmapID);
129    free(beatmap->beatmapSetID);
130
131    free(beatmap->backgroundPath);
132
133    free(beatmap);
134}