diff --git a/.gitignore b/.gitignore index 1efab61..7093131 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ *.tsv *.pdf *bin/Lephisto +*bin/mksprite *bin/data *pack *core diff --git a/bin/Makefile b/bin/Makefile index 89f047e..4d68275 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -35,7 +35,7 @@ DATAFILES = $(shell find ../scripts/ ../gfx/ ../dat/ -name '*.lua' -o -name '*.p @gcc -c $(CFLAGS) -o $@ $< @echo -e "\tCC $@" -all: data lua $(OBJS) +all: utils data lua $(OBJS) @gcc $(LDFLAGS) -o $(APPNAME) $(OBJS) ../lib/lua/liblua.a @echo "\tLD $(APPNAME)" @@ -45,12 +45,17 @@ lua: pack: ../src/pack.c ../utils/pack/main.c @(cd ../utils/pack; $(MAKE)) +mksprite: ../utils/mkspr/main.c + @(cd ../utils/mkspr; $(MAKE)) + data: pack $(DATAFILES) ../src/pack.c ../utils/pack/main.c @echo -e "\tCreating data..\n" @./pack $(DATA) $(DATAFILES) - + +utils: mksprite + clean: @echo -e "\tRemoving data.." - rm -rf $(OBJS) $(APPNAME) $(DATA) pack core + rm -rf $(OBJS) $(APPNAME) $(DATA) pack core mksprite #rm -rf ../lib/lua/*.o ../lib/lua/*.a diff --git a/utils/mkspr/Makefile b/utils/mkspr/Makefile new file mode 100644 index 0000000..0dcac02 --- /dev/null +++ b/utils/mkspr/Makefile @@ -0,0 +1,18 @@ +ROOTDIR = ../../bin/ +LOCALDIR = utils/mksprite/ + +COBJ = + +CFLAGS = `sdl-config --cflags` -O2 -Wall +LFLAGS = `sdl-config --libs` -lSDL_image + +APPNAME = mksprite + +%.o: $(SRCDIR)%.c + @$(CC) -c $(CFLAGS) -o $@ $< + @echo -e "\tCC $(LOCALDIR)$@" + +all: + @$(CC) $(LFLAGS) $(CFLAGS) -o $(ROOTDIR)$(APPNAME) main.c $(COBJS) + @echo -e "\tLD $(APPNAME)" + diff --git a/utils/mkspr/main.c b/utils/mkspr/main.c new file mode 100644 index 0000000..a7180e9 --- /dev/null +++ b/utils/mkspr/main.c @@ -0,0 +1,227 @@ +#include +#include +#include + +#include "SDL.h" +#include "SDL_image.h" + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +# define RMASK 0xff000000 +# define BMASK 0x00ff0000 +# define GMASK 0x0000ff00 +# define AMASK 0x000000ff +#else +# define RMASK 0x000000ff +# define BMASK 0x0000ff00 +# define GMASK 0x00ff0000 +# define AMASK 0xff0000 +#endif +#define RGBAMASK RMASK, GMASK, BMASK, AMASK + +// Logging macros. +#define LOG(str, args...)(fprintf(stdout, str"\n", ## args)) +#define WARN(str, args...)(fprintf(stderr, "Warning: "str"\n", ## args)) +#define ERR(str, args...) { fprintf(stderr, "ERROR %s:%d: "str"\n", \ + __FILE__, __LINE__, ## args); return EXIT_FAILURE; } + +#define WS 6 +#define HS 6 + +static int save_png(SDL_Surface* surface, const char* file); +static int write_png(const char* file_name, png_bytep* rows, int w, int h, int colortype, int bitdepth); + +int main(int argc, char* argv[]) { + int i, ws, hs; + unsigned int sflags, salpha; + char file[8]; + SDL_Surface* final, *tmp, **load; + SDL_Rect r; + + // Init variables. + r.w = r.h = 0; + + if(argc == 2) { + ws = hs = atoi(argv[1]); + } + else if(argc == 3) { + ws = atoi(argv[1]); + hs = atoi(argv[2]); + } else { + ws = WS; + hs = HS; + } + + load = NULL; + tmp = NULL; + final = NULL; + + // Init SDL. + if(SDL_Init(SDL_INIT_VIDEO)) ERR("Initializing SDL: %s", SDL_GetError()); + // Create the window. + tmp = SDL_SetVideoMode(320, 240, 0, SDL_NOFRAME); + if(tmp == NULL) ERR("Initializing video surface: %s", SDL_GetError()); + + // Open RAM for the images. + load = malloc(sizeof(SDL_Surface*)*(ws*hs)); + if(load == NULL) ERR("Out of RAM"); + + // Load all the images to RAM. + for(i = 0; i < (ws*hs); i++) { + // Filenames will be in the sequence of: 000.png, 001.png, ..., 045.png, etc. + sprintf(file, "%d%d%d.png", i/100, (i%100)/10, i%10); + + // Load the image properly. + tmp = IMG_Load(file); + if(tmp == NULL) ERR("Problem loading file '%s': %s", file, IMG_GetError()); + sflags = tmp->flags & (SDL_SRCALPHA | SDL_SRCCOLORKEY); + salpha = tmp->format->alpha; + if(sflags & SDL_SRCALPHA) + SDL_SetAlpha(tmp, 0, SDL_ALPHA_OPAQUE); + if(sflags & SDL_SRCCOLORKEY) + SDL_SetColorKey(tmp, 0, tmp->format->colorkey); + + load[i] = tmp; + + // Check if size has changed. + if(r.w == 0 && r.h == 0) { + r.w = load[i]->w; + r.h = load[i]->h; + } + else if((r.w != load[i]->w) || (r.h != load[i]->h)) + ERR("File '%s' is not of the same dimensions as the files before!", file); + + // Create the suface if it hasn't been created already. + if(!final) { + final = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, ws*r.w, hs*r.h, + load[i]->format->BitsPerPixel, RGBAMASK); + if(!final) ERR("Problem creating RGB Surface: %s", SDL_GetError()); + tmp = final; + } + // New position. + r.y = r.h * (i/ws); + r.x = r.w * (i%ws); + if(SDL_BlitSurface(load[i], NULL, final, &r)) + ERR("Problem blitting surface '%s' to final surface: %s", file, SDL_GetError()); + SDL_FreeSurface(load[i]); + } + // Draw the result and cleanup. + save_png(final, "sprite.png"); + SDL_FreeSurface(final); + free(load); + + SDL_Quit(); + + return EXIT_SUCCESS; +} + +static int save_png(SDL_Surface* surface, const char* file) { + static unsigned char** ss_rows; + static int ss_size; + static int ss_w, ss_h; + SDL_Surface* ss_surface; + SDL_Rect ss_rect; + int r, i; + int alpha = 0; + int pixel_bits = 32; + + unsigned surf_flags; + unsigned surf_alpha; + + ss_rows = 0; + ss_size = 0; + ss_surface = 0; + + ss_w = surface->w; + ss_h = surface->h; + + if(surface->format->Amask) { + alpha = 1; + pixel_bits = 32; + } else { + pixel_bits = 24; + } + + ss_surface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, ss_w, ss_h, pixel_bits, RGBAMASK); + + if(ss_surface == 0) { + return -1; + } + + surf_flags = surface->flags & (SDL_SRCALPHA | SDL_SRCCOLORKEY); + surf_alpha = surface->format->alpha; + if(surf_flags & SDL_SRCALPHA) + SDL_SetAlpha(surface, 0, SDL_ALPHA_OPAQUE); + if(surf_flags & SDL_SRCCOLORKEY) + SDL_SetColorKey(surface, 0, surface->format->colorkey); + + ss_rect.x = 0; + ss_rect.y = 0; + ss_rect.w = ss_w; + ss_rect.h = ss_h; + SDL_BlitSurface(surface, &ss_rect, ss_surface, 0); + + if(ss_size == 0) { + ss_size = ss_h; + ss_rows = (unsigned char**)malloc(sizeof(unsigned char*) * ss_size); + if(ss_rows == 0) { + return -1; + } + } + if(surf_flags & SDL_SRCALPHA) + SDL_SetAlpha(surface, SDL_SRCALPHA, (Uint8)surf_alpha); + if(surf_flags & SDL_SRCCOLORKEY) + SDL_SetColorKey(surface, SDL_SRCCOLORKEY, surface->format->colorkey); + + for(i = 0; i < ss_h; i++) { + ss_rows[i] = ((unsigned char*)ss_surface->pixels) + i * ss_surface->pitch; + } + + if(alpha) { + r = write_png(file, ss_rows, surface->w, surface->h, PNG_COLOR_TYPE_RGB_ALPHA, 8); + } else { + r = write_png(file, ss_rows, surface->w, surface->h, PNG_COLOR_TYPE_RGB, 8); + } + + free(ss_rows); + SDL_FreeSurface(ss_surface); + ss_surface = NULL; + + return r; +} + +static int write_png(const char* file_name, png_bytep* rows, int w, int h, int colortype, int bitdepth) { + png_structp png_ptr; + png_infop info_ptr; + FILE* fp = NULL; + char* doing = "Open for writing"; + + if(!(fp = fopen(file_name, "wb"))) goto fail; + + doing = "Create png info struct"; + if(!(info_ptr = png_create_info_struct(png_ptr))) goto fail; + if(setjmp(png_jmpbuf(png_ptr))) goto fail; + + doing = "Init IO"; + png_init_io(png_ptr, fp); + png_set_IHDR(png_ptr, info_ptr, w, h, bitdepth, colortype, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + doing = "Write info"; + png_write_end(png_ptr, info_ptr); + + doing = "Write image"; + png_write_image(png_ptr, rows); + + doing = "Write end"; + png_write_end(png_ptr, NULL); + + doing = "Closing file"; + if(0 != fclose(fp)) goto fail; + + return 0; + +fail: + WARN("write_png: Could not %s", doing); + return -1; +} +