From c978f746058497ddd9ddc9cf3e156c4453e487f1 Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Fri, 15 Feb 2013 15:28:42 -0500 Subject: Add resource manager and move src/image.*. --- diff --git a/Makefile b/Makefile index 3efdec5..2648c43 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,9 @@ CC = gcc CFLAGS = -Wall -Wextra -Werror -g -SRCS = src/main.c src/init.c src/logging.c src/image.c \ - src/base64.c src/compression.c src/tmx.c +SRCS = src/main.c src/init.c src/logging.c \ + src/base64.c src/compression.c \ + src/tmx.c src/resources/resource.c src/resources/image.c OBJS = $(SRCS:.c=.o) LIBS = sdl SDL_image zlib expat diff --git a/src/image.c b/src/image.c deleted file mode 100644 index 557e1de..0000000 --- a/src/image.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include "logging.h" -#include "image.h" - -SDL_Surface * -load_png(const char *path) -{ - SDL_RWops *rwops; - SDL_Surface *img; - - debug("Loading PNG image \"%s\"...", path); - - rwops = SDL_RWFromFile(path, "rb"); - img = IMG_LoadPNG_RW(rwops); - if (!img) { - err(1, "Failed to load image \"%s\" (%s)", - path, IMG_GetError()); - } - - return img; -} diff --git a/src/image.h b/src/image.h deleted file mode 100644 index 0de4083..0000000 --- a/src/image.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef IMAGE_H -#define IMAGE_H - -SDL_Surface *load_png(const char *path); - -#endif diff --git a/src/layer.h b/src/layer.h index 126c3d9..85558a6 100644 --- a/src/layer.h +++ b/src/layer.h @@ -3,6 +3,7 @@ #include +#if 0 const int LAYER_GROUND = 0; const int LAYER_OBJ_LOW = 1; const int LAYER_CHAR_BOT = 2; @@ -10,6 +11,7 @@ const int LAYER_OBJ_MID = 3; const int LAYER_CHAR_TOP = 4; const int LAYER_OBJ_HIGH = 5; const int LAYER_WEATHER = 6; +#endif struct layer { char *name; diff --git a/src/main.c b/src/main.c index b30d0b2..24e9e1e 100644 --- a/src/main.c +++ b/src/main.c @@ -1,20 +1,29 @@ #include #include "init.h" #include "logging.h" -#include "image.h" +#include "resources/image.h" #include "tmx.h" int main(void) { - SDL_Surface *img; + struct image *img; SDL_Rect imgrect, surfacerect; init(); tmx_load("data/forest1.tmx"); - img = load_png("../forest-6-layer-test_ground.png"); + img = img_png_get("../forest-6-layer-test_ground.png"); + img_png_free(img); + img = img_png_get("../forest-6-layer-test_ground.png"); + img = img_png_get("../forest-6-layer-test_ground.png"); + img = img_png_get("../forest-6-layer-test_ground.png"); + img = img_png_get("../forest-6-layer-test_ground.png"); + img_png_free(img); + img_png_free(img); + img_png_free(img); + img = img_png_get("../forest-6-layer-test_ground.png"); imgrect.w = 240; imgrect.h = 160; surfacerect.x = 0; @@ -24,37 +33,37 @@ main(void) imgrect.x = 208; imgrect.y = 480; - SDL_BlitSurface(img, &imgrect, screen, &surfacerect); + SDL_BlitSurface(img->image, &imgrect, screen, &surfacerect); SDL_Flip(screen); SDL_Delay(500); imgrect.x = 208; imgrect.y = 464; - SDL_BlitSurface(img, &imgrect, screen, &surfacerect); + SDL_BlitSurface(img->image, &imgrect, screen, &surfacerect); SDL_Flip(screen); SDL_Delay(500); imgrect.x = 224; imgrect.y = 464; - SDL_BlitSurface(img, &imgrect, screen, &surfacerect); + SDL_BlitSurface(img->image, &imgrect, screen, &surfacerect); SDL_Flip(screen); SDL_Delay(500); imgrect.x = 240; imgrect.y = 464; - SDL_BlitSurface(img, &imgrect, screen, &surfacerect); + SDL_BlitSurface(img->image, &imgrect, screen, &surfacerect); SDL_Flip(screen); SDL_Delay(500); imgrect.x = 256; imgrect.y = 464; - SDL_BlitSurface(img, &imgrect, screen, &surfacerect); + SDL_BlitSurface(img->image, &imgrect, screen, &surfacerect); SDL_Flip(screen); SDL_Delay(500); imgrect.x = 256; imgrect.y = 448; - SDL_BlitSurface(img, &imgrect, screen, &surfacerect); + SDL_BlitSurface(img->image, &imgrect, screen, &surfacerect); SDL_Flip(screen); SDL_Delay(500); diff --git a/src/map.h b/src/map.h index 554b428..925bdd2 100644 --- a/src/map.h +++ b/src/map.h @@ -1,6 +1,7 @@ #ifndef MAP_H #define MAP_H +#include #include "tileset.h" #include "layer.h" @@ -11,6 +12,7 @@ struct map { int tileheight; struct tileset *tilesets; struct layer *layers; + Uint8 *collision; }; #endif diff --git a/src/resources/image.c b/src/resources/image.c new file mode 100644 index 0000000..cd2c317 --- /dev/null +++ b/src/resources/image.c @@ -0,0 +1,48 @@ +#include +#include +#include "../logging.h" +#include "image.h" +#include "resource.h" + +struct resource_table img_res; + +struct image * +img_png_get(const char *path) +{ + SDL_RWops *rwops; + struct image *img; + + img = (struct image *) resource_get(&img_res, path); + if (img != NULL) { + resource_use((struct resource *) img); + return img; + } + + img = resource_alloc(path, sizeof(*img)); + rwops = SDL_RWFromFile(path, "rb"); + img->image = IMG_LoadPNG_RW(rwops); + if (!img->image) { + err(1, "Failed to load image \"%s\" (%s)", + path, IMG_GetError()); + } + + resource_use((struct resource *) img); + resource_add(&img_res, path, (struct resource *) img); + + return img; +} + +void +img_png_free(struct image *image) +{ + SDL_Surface *data; + + if (image == NULL) { + return; + } + + data = image->image; + if (resource_free(&img_res, (struct resource *) image)) { + SDL_FreeSurface(data); + } +} diff --git a/src/resources/image.h b/src/resources/image.h new file mode 100644 index 0000000..92ef040 --- /dev/null +++ b/src/resources/image.h @@ -0,0 +1,14 @@ +#ifndef IMAGE_H +#define IMAGE_H + +#include "resource.h" + +struct image { + struct resource res; + SDL_Surface *image; +}; + +struct image *img_png_get(const char *path); +void img_png_free(struct image *image); + +#endif diff --git a/src/resources/resource.c b/src/resources/resource.c new file mode 100644 index 0000000..ebfcf27 --- /dev/null +++ b/src/resources/resource.c @@ -0,0 +1,87 @@ +#include +#include +#include "resource.h" + +#include "../logging.h" + +inline void * +resource_alloc(const char *path, size_t size) +{ + void *new_res; + + debug("Allocating resource \"%s\"...", path); + new_res = malloc(size); + if (new_res == NULL) { + err(1, "Failed to allocate resource \"%s\"", path); + return NULL; + } + memset(new_res, 0, size); + + return new_res; +} + +struct resource * +resource_get(struct resource_table *resources, const char *path) +{ + struct resource *res; + + for (res = resources->head; res != NULL; res = res->next) { + if (strcmp(res->path, path) == 0) { + debug("Found resource \"%s\"", path); + return res; + } + } + + return NULL; +} + +void +resource_add(struct resource_table *resources, const char *path, + struct resource *new_res) +{ + new_res->path = strdup(path); + new_res->prev = resources->tail; + new_res->next = NULL; + + if (resources->head == NULL) { + resources->head = new_res; + } else { + resources->tail->next = new_res; + } + resources->tail = new_res; +} + +/* XXX: Not thread-safe. */ +void +resource_use(struct resource *resource) +{ + ++resource->refs; +} + +int +resource_free(struct resource_table *resources, struct resource *resource) +{ + if (resource == NULL) { + return -1; + } + + debug("Releasing resource with path \"%s\" and %d refs...", + resource->path, resource->refs); + + if (--resource->refs == 0) { + debug("Freeing resource with path \"%s\"...", resource->path); + if (resource->prev == NULL) { + resources->head = resource->next; + } else { + resource->prev->next = resource->next; + } + if (resource->next == NULL) { + resources->tail = resource->prev; + } else { + resource->next->prev = resource->prev; + } + free(resource); + return 1; + } + return 0; +} diff --git a/src/resources/resource.h b/src/resources/resource.h new file mode 100644 index 0000000..ada91fd --- /dev/null +++ b/src/resources/resource.h @@ -0,0 +1,23 @@ +#ifndef RESOURCE_H +#define RESOURCE_H + +struct resource_table { + struct resource *head; + struct resource *tail; +}; +struct resource { + char *path; + int refs; + struct resource *prev; + struct resource *next; +}; + +extern inline void *resource_alloc(const char *path, size_t size); +struct resource *resource_get(struct resource_table *resources, + const char *path); +void resource_add(struct resource_table *resources, const char *path, + struct resource *new_res); +void resource_use(struct resource *resource); +int resource_free(struct resource_table *resources, struct resource *resource); + +#endif diff --git a/src/tileset.h b/src/tileset.h index 2fd384a..26aec80 100644 --- a/src/tileset.h +++ b/src/tileset.h @@ -5,7 +5,7 @@ struct tileset { int firstgid; int tilewidth; int tileheight; - SDL_Surface *image; + struct image *image; struct tileset *next; }; diff --git a/src/tmx.c b/src/tmx.c index 0e401b3..731f76c 100644 --- a/src/tmx.c +++ b/src/tmx.c @@ -7,7 +7,7 @@ #include "base64.h" #include "compression.h" #include "map.h" -#include "image.h" +#include "resources/image.h" struct tmx { char *dirname; @@ -129,7 +129,7 @@ tmx_start_image(struct tmx *cur_tmx, const char **attr) err(1, "Failed to allocate resource path string"); } sprintf(path, "%s/%s", cur_tmx->dirname, source); - cur_tmx->cur_tileset->image = load_png(path); + cur_tmx->cur_tileset->image = img_png_get(path); free(path); debug(" Found tileset with firstgid %d and source \"%s\"", -- cgit v0.9.1