NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / win / share / tileset.c
blobe2fda2d330b3893de56cd77b9b82e58687d9bd88
1 /* aNetHack 0.0.1 tileset.c $ANH-Date: 1457207053 2016/03/05 19:44:13 $ $ANH-Branch: chasonr $:$ANH-Revision: 1.0 $ */
2 /* Copyright (c) Ray Chason, 2016. */
3 /* aNetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
6 #include "tileset.h"
8 static void FDECL(get_tile_map, (const char *));
9 static void FDECL(split_tiles, (const struct TileSetImage *));
10 static void FDECL(free_image, (struct TileSetImage *));
12 static struct TileImage *tiles;
13 static unsigned num_tiles;
14 static struct TileImage blank_tile; /* for graceful undefined tile handling */
16 static boolean have_palette;
17 static struct Pixel palette[256];
19 boolean
20 read_tiles(filename, true_color)
21 const char *filename;
22 boolean true_color;
24 static const unsigned char png_sig[] = {
25 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A
27 struct TileSetImage image;
28 FILE *fp = NULL; /* custodial */
29 char header[16];
30 boolean ok;
32 /* Fill the image structure with known values */
33 image.width = 0;
34 image.height = 0;
35 image.pixels = NULL; /* custodial */
36 image.indexes = NULL; /* custodial */
37 image.image_desc = NULL; /* custodial */
38 image.tile_width = 0;
39 image.tile_height = 0;
41 /* Identify the image type */
42 fp = fopen(filename, "rb");
43 if (fp == NULL) goto error;
44 memset(header, 0, sizeof(header));
45 fread(header, 1, sizeof(header), fp);
46 fclose(fp);
48 /* Call the loader appropriate for the image */
49 if (memcmp(header, "BM", 2) == 0) {
50 ok = read_bmp_tiles(filename, &image);
51 } else if (memcmp(header, "GIF87a", 6) == 0
52 || memcmp(header, "GIF89a", 6) == 0) {
53 ok = read_gif_tiles(filename, &image);
54 } else if (memcmp(header, png_sig, sizeof(png_sig)) == 0) {
55 ok = read_png_tiles(filename, &image);
56 } else {
57 ok = FALSE;
59 if (!ok) goto error;
61 /* Reject if the interface cannot handle direct color and the image does
62 not use a palette */
63 if (!true_color && image.indexes == NULL) goto error;
65 /* Save the palette if present */
66 have_palette = image.indexes != NULL;
67 memcpy(palette, image.palette, sizeof(palette));
69 /* Set defaults for tile metadata */
70 if (image.tile_width == 0) {
71 image.tile_width = image.width / 40;
73 if (image.tile_height == 0) {
74 image.tile_height = image.tile_width;
76 /* Set the tile dimensions if the user has not done so */
77 if (iflags.wc_tile_width == 0) {
78 iflags.wc_tile_width = image.tile_width;
80 if (iflags.wc_tile_height == 0) {
81 iflags.wc_tile_height = image.tile_height;
84 /* Parse the tile map */
85 get_tile_map(image.image_desc);
87 /* Split the image into tiles */
88 split_tiles(&image);
90 fclose(fp);
91 free_image(&image);
92 return TRUE;
94 error:
95 if (fp) fclose(fp);
96 free_image(&image);
97 return FALSE;
100 const struct Pixel *
101 get_palette()
103 return have_palette ? palette : NULL;
106 /* TODO: derive tile_map from image_desc */
107 static void
108 get_tile_map(image_desc)
109 const char *image_desc;
113 void
114 free_tiles()
116 unsigned i;
118 if (tiles != NULL) {
119 for (i = 0; i < num_tiles; ++i) {
120 free(tiles[i].pixels);
121 free(tiles[i].indexes);
124 free(tiles);
125 tiles = NULL;
126 num_tiles = 0;
128 free(blank_tile.pixels);
129 blank_tile.pixels = NULL;
130 free(blank_tile.indexes);
131 blank_tile.indexes = NULL;
134 static void
135 free_image(image)
136 struct TileSetImage *image;
138 free(image->pixels);
139 image->pixels = NULL;
140 free(image->indexes);
141 image->indexes = NULL;
142 free(image->image_desc);
143 image->image_desc = NULL;
146 const struct TileImage *
147 get_tile(tile_index)
148 unsigned tile_index;
150 if (tile_index >= num_tiles) {
151 return &blank_tile;
152 } else {
153 return &tiles[tile_index];
157 static void
158 split_tiles(image)
159 const struct TileSetImage *image;
161 unsigned tile_rows, tile_cols;
162 size_t tile_size, i, j;
163 unsigned x1, y1, x2, y2;
165 /* Get the number of tiles */
166 tile_rows = image->height / iflags.wc_tile_height;
167 tile_cols = image->width / iflags.wc_tile_width;
168 num_tiles = tile_rows * tile_cols;
169 tile_size = (size_t) iflags.wc_tile_height * (size_t) iflags.wc_tile_width;
171 /* Allocate the tile array */
172 tiles = (struct TileImage *) alloc(num_tiles * sizeof(tiles[0]));
173 memset(tiles, 0, num_tiles * sizeof(tiles[0]));
175 /* Copy the pixels into the tile structures */
176 for (y1 = 0; y1 < tile_rows; ++y1) {
177 for (x1 = 0; x1 < tile_cols; ++x1) {
178 struct TileImage *tile = &tiles[y1 * tile_cols + x1];
179 tile->width = iflags.wc_tile_width;
180 tile->height = iflags.wc_tile_height;
181 tile->pixels = (struct Pixel *)
182 alloc(tile_size * sizeof(struct Pixel));
183 if (image->indexes != NULL) {
184 tile->indexes = (unsigned char *) alloc(tile_size);
186 for (y2 = 0; y2 < iflags.wc_tile_height; ++y2) {
187 for (x2 = 0; x2 < iflags.wc_tile_width; ++x2) {
188 unsigned x = x1 * iflags.wc_tile_width + x2;
189 unsigned y = y1 * iflags.wc_tile_height + y2;
190 i = y * image->width + x;
191 j = y2 * tile->width + x2;
192 tile->pixels[j] = image->pixels[i];
193 if (image->indexes != NULL) {
194 tile->indexes[j] = image->indexes[i];
201 /* Create a blank tile for use when the tile index is invalid */
202 blank_tile.width = iflags.wc_tile_width;
203 blank_tile.height = iflags.wc_tile_height;
204 blank_tile.pixels = (struct Pixel *)
205 alloc(tile_size * sizeof(struct Pixel));
206 for (i = 0; i < tile_size; ++i) {
207 blank_tile.pixels[i].r = 0;
208 blank_tile.pixels[i].g = 0;
209 blank_tile.pixels[i].b = 0;
210 blank_tile.pixels[i].a = 255;
212 if (image->indexes) {
213 blank_tile.indexes = (unsigned char *) alloc(tile_size);
214 memset(blank_tile.indexes, 0, tile_size);
218 boolean
219 read_png_tiles(filename, image)
220 const char *filename;
221 struct TileSetImage *image;
223 /* stub */
224 return FALSE;