uint8_t *load(void **context, size_t *file_size, FILE *file, size_t max_size) { size_t pos; size_t size = 0; struct chunk *chunk; struct chunk head = { 0, &head, &head }; size_t chunk_size = load_size(file); int error = 0; #ifdef WITH_LIBARCHIVE struct archive *archive = *context; struct archive_entry *archive_entry; if (archive != NULL) goto init_ok; archive = archive_read_new(); *context = archive; if (archive == NULL) { error = ENOMEM; goto error; } archive_read_support_compression_all(archive); archive_read_support_format_all(archive); archive_read_support_format_raw(archive); if (archive_read_open_FILE(archive, file) != ARCHIVE_OK) { error = EIO; goto error; } init_ok: switch (archive_read_next_header(archive, &archive_entry)) { case ARCHIVE_OK: break; case ARCHIVE_EOF: error = 0; goto error; default: error = EIO; goto error; } #else *context = (void *)0xffff; #endif if (chunk_size == 0) chunk_size = CHUNK_SIZE; else if ((max_size != 0) && (chunk_size > max_size)) chunk_size = max_size; while (1) { pos = 0; chunk = malloc(sizeof(*chunk) + chunk_size); if (chunk == NULL) { error = errno; goto error; } chunk->size = chunk_size; chunk->next = &head; chunk->prev = head.prev; chunk->prev->next = chunk; head.prev = chunk; do { size_t i; #ifdef WITH_LIBARCHIVE ssize_t j; j = archive_read_data(archive, &chunk->data[pos], (chunk->size - pos)); /* Don't bother with ARCHIVE_WARN and ARCHIVE_RETRY, consider any negative value an error. */ if (j < 0) { error = EIO; goto error; } i = (size_t)j; #else i = fread(&chunk->data[pos], 1, (chunk->size - pos), file); #endif if (i == 0) { chunk->size = pos; #ifndef WITH_LIBARCHIVE if (ferror(file)) { error = EIO; goto error; } assert(feof(file)); #endif goto process; } pos += i; size += i; if ((max_size != 0) && (size > max_size)) { error = EFBIG; goto error; } } while (pos != chunk->size); chunk_size = CHUNK_SIZE; } process: chunk = realloc(head.next, (sizeof(*chunk) + size)); if (chunk == NULL) { error = errno; goto error; } chunk->next->prev = chunk; head.next = chunk; pos = chunk->size; chunk->size = size; chunk = chunk->next; while (chunk != &head) { struct chunk *next = chunk->next; memcpy(&head.next->data[pos], chunk->data, chunk->size); pos += chunk->size; chunk->next->prev = chunk->prev; chunk->prev->next = chunk->next; free(chunk); chunk = next; } chunk = head.next; chunk->prev = chunk; chunk->next = chunk; if (file_size != NULL) *file_size = chunk->size; return chunk->data; error: #ifdef WITH_LIBARCHIVE load_finish(context); #endif chunk = head.next; while (chunk != &head) { struct chunk *next = chunk->next; free(chunk); chunk = next; } errno = error; return NULL; }
static SDL_bool load_config(session *s, game_state *gs, json_t *game, char const *root) { json_t *entities, *fnt, *level; char const *file, *path; /* load config */ fnt = json_object_get(game, "font"); path = set_path("%s/%s/%s", root, ASSET_DIR, json_string_value(json_object_get(fnt, "resource"))); int fnt_siz = json_integer_value(json_object_get(fnt, "size")); TTF_Font *font = TTF_OpenFont(path, fnt_siz); if (!font) { fprintf(stderr, "error: could not load font %s: %s\n", path, TTF_GetError()); return SDL_FALSE; } if (!gs->debug.font) { gs->debug.font = TTF_OpenFont("debug_font.ttf", 14); } SDL_bool ok; ok = load_finish(s, game, font, fnt_siz); if (!ok) { return SDL_FALSE; } ok = load_messages(s, game, font, fnt_siz, root); if (!ok) { return SDL_FALSE; } TTF_CloseFont(font); level = json_object_get(game, "level"); if (!ok) { return SDL_FALSE; } path = set_path("%s/%s/%s", root, CONF_DIR, json_string_value(level)); json_error_t e; level = json_load_file(path, 0, &e); if (*e.text != 0) { fprintf(stderr, "Error at %s:%d: %s\n", path, e.line, e.text); return SDL_FALSE; } s->level.background = load_asset_tex(level, root, s->r, "resource"); if (!s->level.background) { return SDL_FALSE; } load_collisions(&s->level, level); json_decref(level); entity_rule *e_rules; SDL_Texture **e_texs; entities = json_object_get(game, "entities"); if (!entities) { fprintf(stderr, "Error: No entities defined, need player\n"); return SDL_FALSE; } file = json_string_value(json_object_get(entities, "resource")); path = set_path("%s/%s/%s", root, CONF_DIR, file); entities = load_entities(root, path, s->r, &e_texs, &e_rules); if (!entities) { fprintf(stderr, "Error: Could not load entities\n"); return SDL_FALSE; } init_group(&gs->entities[GROUP_PLAYER ], game, entities, "players", e_texs, e_rules, ST_IDLE); init_group(&gs->entities[GROUP_OBJECTS], game, entities, "objects", e_texs, e_rules, ST_IDLE); init_group(&gs->entities[GROUP_ENEMIES], game, entities, "enemies", e_texs, e_rules, ST_WALK); load_intro(&gs->logo, s, entities, "logo", e_rules, e_texs); load_intro(&gs->intro, s, entities, "intro", e_rules, e_texs); /* all texture pointers are copied by value, no need to hold onto the * e_texs buffer */ free(e_texs); json_decref(entities); json_decref(game); return SDL_TRUE; }