From 83231da18da90d329f3a3b825119ba5e7d7670aa Mon Sep 17 00:00:00 2001 From: James Shaw Date: Tue, 25 Mar 2008 22:35:34 +0000 Subject: Refactor file and memory reader functions, and sprite_read_word(), to return error value. svn path=/import/jshaw/libsprite/; revision=10016 --- trunk/example.c | 48 ++++++++++++++++++++++++--------- trunk/librosprite.c | 77 ++++++++++++++++++++++++++++++++++------------------- trunk/librosprite.h | 7 +++-- 3 files changed, 89 insertions(+), 43 deletions(-) diff --git a/trunk/example.c b/trunk/example.c index c42756d..6db17fe 100644 --- a/trunk/example.c +++ b/trunk/example.c @@ -55,6 +55,38 @@ int load_file_to_memory(const char *filename, uint8_t **result) return size; } +int create_file_context(char* filename, void** result) +{ + FILE *f = fopen(filename, "rb"); + if (!f) { + *result = NULL; + return -1; + } + + struct rosprite_file_context* ctx; + if (rosprite_create_file_context(f, &ctx) != ROSPRITE_OK) { + return -1; + } + *result = ctx; + + return 0; +} + +int create_mem_context(char* filename, void** result) +{ + uint8_t* content; + + int size = load_file_to_memory(filename, &content); + if (size < 0) return -1; + struct rosprite_mem_context* ctx; + if (rosprite_create_mem_context(content, size, &ctx) != ROSPRITE_OK) { + return -1; + } + *result = ctx; + + return 0; +} + int main(int argc, char *argv[]) { if (argc < 2) { @@ -69,21 +101,11 @@ int main(int argc, char *argv[]) atexit(SDL_Quit); char* filename = argv[1]; - uint8_t* content; - - int size = load_file_to_memory(filename, &content); - if (size < 0) { - printf("Can't load spritefile %s\n", filename); - exit(EXIT_FAILURE); - } else { - printf("Loaded file of size %d into memory", size); - } - - struct rosprite_mem_context* ctx = rosprite_create_mem_context(content, size); - + void* ctx; + create_file_context(filename, &ctx); printf("Loading %s\n", filename); - struct rosprite_area* sprite_area = rosprite_load(rosprite_mem_reader, ctx); + struct rosprite_area* sprite_area = rosprite_load(rosprite_file_reader, ctx); printf("sprite_count %u\n", sprite_area->sprite_count); printf("extension_size %u\n", sprite_area->extension_size); diff --git a/trunk/librosprite.c b/trunk/librosprite.c index 50dacc8..4c9c338 100644 --- a/trunk/librosprite.c +++ b/trunk/librosprite.c @@ -194,11 +194,14 @@ static const uint32_t sprite_8bpp_palette[] = { 0xccccccff, 0xddddddff, 0xeeeeeeff, 0xffffffff }; -struct rosprite_file_context* rosprite_create_file_context(FILE* f) +rosprite_error rosprite_create_file_context(FILE* f, struct rosprite_file_context** result) { struct rosprite_file_context* ctx = malloc(sizeof(struct rosprite_file_context)); + if (!ctx) return ROSPRITE_NOMEM; ctx->f = f; - return ctx; + *result = ctx; + + return ROSPRITE_OK; } void rosprite_destroy_file_context(struct rosprite_file_context* ctx) @@ -211,14 +214,17 @@ int rosprite_file_reader(uint8_t* buf, size_t count, void* ctx) return fread(buf, 1 /*size*/, count, ((struct rosprite_file_context*) ctx)->f); } -struct rosprite_mem_context* rosprite_create_mem_context(uint8_t* p, unsigned long total_size) +rosprite_error rosprite_create_mem_context(uint8_t* p, unsigned long total_size, struct rosprite_mem_context** result) { struct rosprite_mem_context* ctx = malloc(sizeof(struct rosprite_mem_context)); + if (!ctx) return ROSPRITE_NOMEM; + ctx->base = p; ctx->offset = 0; - ctx->known_size = true; ctx->size = total_size; - return ctx; + *result = ctx; + + return ROSPRITE_OK; } void rosprite_destroy_mem_context(struct rosprite_mem_context* ctx) @@ -229,22 +235,30 @@ void rosprite_destroy_mem_context(struct rosprite_mem_context* ctx) int rosprite_mem_reader(uint8_t* buf, size_t count, void* ctx) { struct rosprite_mem_context* memctx = (struct rosprite_mem_context*) ctx; - buf = memctx->base + memctx->offset; + if (memctx->offset + count > memctx->size) { + return -1; // TODO: use enum + } + + // if we're asked for more memory than the block contains, only copy as much as we can + size_t copy_size; + if ((memctx->offset + count) > memctx->size) { + copy_size = memctx->size - memctx->offset; + } else { + copy_size = count; + } + memcpy(buf, memctx->base + memctx->offset, count); memctx->offset += count; - return count; // TODO: assert size bounds, return real count + return copy_size; // TODO: assert size bounds, return real count } -/* TODO: get rid of this method */ -uint32_t sprite_read_word(reader reader, void* ctx) +rosprite_error sprite_read_word(reader reader, void* ctx, uint32_t* result) { unsigned char b[4]; - if (reader(b, 4, ctx) < 4) { - printf("Unexpected EOF\n"); /* TODO, have better error handling, don't exit here */ - exit(EXIT_FAILURE); + return ROSPRITE_EOF; } - - return BTUINT(b); + *result = BTUINT(b); + return ROSPRITE_OK; } static struct rosprite_mode sprite_get_mode(uint32_t spriteMode) @@ -560,7 +574,8 @@ static void sprite_load_low_color(uint8_t* image_in, uint8_t* mask, struct rospr struct rosprite* sprite_load_sprite(reader reader, void* ctx) { - uint32_t nextSpriteOffset = sprite_read_word(reader, ctx); + uint32_t nextSpriteOffset; + sprite_read_word(reader, ctx, &nextSpriteOffset); struct rosprite* sprite = malloc(sizeof(struct rosprite)); struct rosprite_header* header = malloc(sizeof(struct rosprite_header)); @@ -568,16 +583,20 @@ struct rosprite* sprite_load_sprite(reader reader, void* ctx) reader(sprite->name, 12, ctx); sprite->name[12] = '\0'; - header->width_words = sprite_read_word(reader, ctx) + 1; /* file has width - 1 and height - 1 */ - sprite->height = sprite_read_word(reader, ctx) + 1; - header->first_used_bit = sprite_read_word(reader, ctx); /* old format only (spriteType = 0) */ - header->last_used_bit = sprite_read_word(reader, ctx); + sprite_read_word(reader, ctx, &header->width_words); /* file has width - 1 and height - 1 */ + header->width_words += 1; + sprite_read_word(reader, ctx, &(sprite->height)); + sprite->height += 1; + sprite_read_word(reader, ctx, &(header->first_used_bit)); /* old format only (spriteType = 0) */ + sprite_read_word(reader, ctx, &(header->last_used_bit)); - uint32_t imageOffset = sprite_read_word(reader, ctx); + uint32_t imageOffset; + sprite_read_word(reader, ctx, &imageOffset); assert(imageOffset >= 44); /* should never be smaller than the size of the header) */ - uint32_t maskOffset = sprite_read_word(reader, ctx); - uint32_t spriteModeWord = sprite_read_word(reader, ctx); + uint32_t maskOffset, spriteModeWord; + sprite_read_word(reader, ctx, &maskOffset); + sprite_read_word(reader, ctx, &spriteModeWord); sprite->mode = sprite_get_mode(spriteModeWord); @@ -613,9 +632,10 @@ struct rosprite* sprite_load_sprite(reader reader, void* ctx) * PRM1-730 */ for (uint32_t j = 0; j < paletteEntries; j++) { - uint32_t word1 = sprite_read_word(reader, ctx); - uint32_t word2 = sprite_read_word(reader, ctx); - assert(word1 == word2); /* TODO: if they aren't, START FLASHING */ + uint32_t word1, word2; + sprite_read_word(reader, ctx, &word1); + sprite_read_word(reader, ctx, &word2); + assert(word1 == word2); /* if they aren't equal, flashing colours are desired, which we don't support */ /* swap rr and bb parts -- PRM1-731 */ uint32_t entry = ((word1 & 0xff000000) >> 16) | (word1 & 0x00ff0000) | ((word1 & 0x0000ff00) << 16) | 0xff; @@ -652,10 +672,11 @@ struct rosprite_area* rosprite_load(reader reader, void* ctx) { struct rosprite_area* sprite_area = malloc(sizeof(struct rosprite_area)); - sprite_area->sprite_count = sprite_read_word(reader, ctx); + sprite_read_word(reader, ctx, &(sprite_area->sprite_count)); - uint32_t firstSpriteOffset = sprite_read_word(reader, ctx); - /*uint32_t firstFreeWordOffset = */sprite_read_word(reader, ctx); /* TODO: use this for some sanity checking? */ + uint32_t firstSpriteOffset, firstFreeWordOffset; + sprite_read_word(reader, ctx, &firstSpriteOffset); + sprite_read_word(reader, ctx, &firstFreeWordOffset); /* TODO: use this for some sanity checking? */ sprite_area->extension_size = 16 - firstSpriteOffset; sprite_area->extension_words = NULL; diff --git a/trunk/librosprite.h b/trunk/librosprite.h index 61e5e22..97eea48 100644 --- a/trunk/librosprite.h +++ b/trunk/librosprite.h @@ -5,6 +5,8 @@ #include #include +typedef enum { ROSPRITE_OK, ROSPRITE_NOMEM, ROSPRITE_EOF } rosprite_error; + typedef enum { rosprite_rgb, rosprite_cmyk } rosprite_color_model; typedef int (*reader)(uint8_t* buf, size_t count, void* ctx); @@ -50,11 +52,12 @@ struct rosprite { uint32_t* image; /* image data in 0xRRGGBBAA words */ }; -struct rosprite_file_context* rosprite_create_file_context(FILE* f); +rosprite_error rosprite_create_file_context(FILE* f, struct rosprite_file_context** ctx); void rosprite_destroy_file_context(struct rosprite_file_context* ctx); int rosprite_file_reader(uint8_t* buf, size_t count, void* ctx); -struct rosprite_mem_context* rosprite_create_mem_context(uint8_t* p, unsigned long total_size); +struct rosprite_mem_context; +rosprite_error rosprite_create_mem_context(uint8_t* p, unsigned long total_size, struct rosprite_mem_context** result); void rosprite_destroy_mem_context(struct rosprite_mem_context* ctx); int rosprite_mem_reader(uint8_t* buf, size_t count, void* ctx); -- cgit v1.2.3