summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Shaw <jshaw@netsurf-browser.org>2008-03-25 22:35:34 +0000
committerJames Shaw <jshaw@netsurf-browser.org>2008-03-25 22:35:34 +0000
commit83231da18da90d329f3a3b825119ba5e7d7670aa (patch)
tree5ad2fb393fc3ea13128ecf407f530e89f9cf876d
parent2b29c4dcde7e673d50cfbde6eb41810c3f9ec21b (diff)
downloadlibrosprite-83231da18da90d329f3a3b825119ba5e7d7670aa.tar.gz
librosprite-83231da18da90d329f3a3b825119ba5e7d7670aa.tar.bz2
Refactor file and memory reader functions, and sprite_read_word(), to
return error value. svn path=/import/jshaw/libsprite/; revision=10016
-rw-r--r--trunk/example.c48
-rw-r--r--trunk/librosprite.c77
-rw-r--r--trunk/librosprite.h7
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 <stdio.h>
#include <stdbool.h>
+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);