NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / win / gem / load_img.c
blobdc5befb57234964181468e69cdcdd59cf19b2155
1 /*
2 * $ANH-Date: 1432512809 2015/05/25 00:13:29 $ $ANH-Branch: master $:$ANH-Revision: 1.5 $
3 */
4 #define __TCC_COMPAT__
5 #include <stdio.h>
6 #include <string.h>
7 #include <osbind.h>
8 #include <memory.h>
9 #include <aesbind.h>
10 #include <vdibind.h>
11 #include <gemfast.h>
12 #include <e_gem.h>
13 #include "load_img.h"
15 #ifndef FALSE
16 #define FALSE 0
17 #define TRUE !FALSE
18 #endif
20 /* VDI <-> Device palette order conversion matrixes: */
21 /* Four-plane vdi-device */
22 int vdi2dev4[] = { 0, 15, 1, 2, 4, 6, 3, 5, 7, 8, 9, 10, 12, 14, 11, 13 };
23 /* Two-plane vdi-device */
24 int vdi2dev2[] = { 0, 3, 1, 2 };
26 void
27 get_colors(int handle, short *palette, int col)
29 int i, idx;
31 /* get current color palette */
32 for (i = 0; i < col; i++) {
33 /* device->vdi->device palette order */
34 switch (planes) {
35 case 1:
36 idx = i;
37 break;
38 case 2:
39 idx = vdi2dev2[i];
40 break;
41 case 4:
42 idx = vdi2dev4[i];
43 break;
44 default:
45 if (i < 16)
46 idx = vdi2dev4[i];
47 else
48 idx = i == 255 ? 1 : i;
50 vq_color(handle, i, 0, (int *) palette + idx * 3);
54 void
55 img_set_colors(int handle, short *palette, int col)
57 int i, idx, end;
59 /* set color palette */
60 end = min(1 << col, 1 << planes);
61 for (i = 0; i < end; i++) {
62 switch (planes) { /* MAR -- war col 10.01.2001 */
63 case 1:
64 idx = i;
65 break;
66 case 2:
67 idx = vdi2dev2[i];
68 break;
69 case 4:
70 idx = vdi2dev4[i];
71 break;
72 default:
73 if (i < 16)
74 idx = vdi2dev4[i];
75 else
76 idx = i == 255 ? 1 : i;
78 vs_color(handle, i, (int *) palette + idx * 3);
82 int
83 convert(MFDB *image, long size)
85 int plane, mplanes;
86 char *line_addr, *buf_addr, *new_addr, *new1_addr, *image_addr,
87 *screen_addr;
88 MFDB dev_form, tmp;
89 long new_size;
91 /* convert size from words to bytes */
92 size <<= 1;
94 /* memory for the device raster */
95 new_size = size * (long) planes;
96 if ((new_addr = (char *) calloc(1, new_size)) == NULL)
97 return (FALSE);
99 /* initialize MFDBs */
100 tmp = *image;
101 tmp.fd_nplanes = planes;
102 tmp.fd_addr = new_addr;
103 tmp.fd_stand = 1; /* standard format */
104 dev_form = tmp;
105 screen_addr = new_addr;
106 dev_form.fd_stand = 0; /* device format */
107 image_addr = (char *) image->fd_addr;
109 /* initialize some variables and zero temp. line buffer */
110 mplanes = min(image->fd_nplanes, planes);
111 /* convert image */
112 line_addr = image_addr;
113 buf_addr = screen_addr;
114 if (mplanes > 1) {
115 /* cut/pad color planes into temp buf */
116 for (plane = 0; plane < mplanes; plane++) {
117 memcpy(buf_addr, line_addr, size);
118 line_addr += size;
119 buf_addr += size;
121 } else {
122 /* fill temp line bitplanes with a b&w line */
123 for (plane = 0; plane < planes; plane++) {
124 memcpy(buf_addr, line_addr, size);
125 buf_addr += size;
128 free(image->fd_addr);
129 /* convert image line in temp into current device raster format */
130 if ((new1_addr = (char *) calloc(1, new_size)) == NULL)
131 return (FALSE);
132 dev_form.fd_addr = new1_addr;
133 vr_trnfm(x_handle, &tmp, &dev_form);
134 free(new_addr);
136 /* change image description */
137 image->fd_stand = 0; /* device format */
138 image->fd_addr = new1_addr;
139 image->fd_nplanes = planes;
140 return (TRUE);
144 transform_img(MFDB *image)
145 { /* return FALSE if transform_img fails */
146 int success;
147 long size;
149 if (!image->fd_addr)
150 return (FALSE);
152 size = (long) ((long) image->fd_wdwidth * (long) image->fd_h);
153 success = convert(
154 image, size); /* Use vr_trfm(), which needs quite a lot memory. */
155 if (success)
156 return (TRUE);
157 /* else show_error(ERR_ALLOC); */
158 return (FALSE);
161 /* Loads & depacks IMG (0 if succeded, else error). */
162 /* Bitplanes are one after another in address IMG_HEADER.addr. */
164 depack_img(char *name, IMG_header *pic)
166 int b, line, plane, width, word_aligned, opcode, patt_len, pal_size,
167 byte_repeat, patt_repeat, scan_repeat, error = FALSE;
168 char *pattern, *to, *endline, *puffer, sol_pat;
169 long size;
170 FILE *fp;
172 if ((fp = fopen(name, "rb")) == NULL)
173 return (ERR_FILE);
175 setvbuf(fp, NULL, _IOLBF, BUFSIZ);
177 /* read header info (bw & ximg) into image structure */
178 fread((char *) &(pic->version), 2, 8 + 3, fp);
180 /* only 2-256 color imgs */
181 if (pic->planes < 1 || pic->planes > 8) {
182 error = ERR_COLOR;
183 goto end_depack;
186 /* if XIMG, read info */
187 if (pic->magic == XIMG && pic->paltype == 0) {
188 pal_size = (1 << pic->planes) * 3 * 2;
189 if ((pic->palette = (short *) calloc(1, pal_size))) {
190 fread((char *) pic->palette, 1, pal_size, fp);
192 } else {
193 pic->palette = NULL;
196 /* width in bytes word aliged */
197 word_aligned = (pic->img_w + 15) >> 4;
198 word_aligned <<= 1;
200 /* width byte aligned */
201 width = (pic->img_w + 7) >> 3;
203 /* allocate memory for the picture */
204 free(pic->addr);
205 size = (long) ((long) word_aligned * (long) pic->img_h
206 * (long) pic->planes); /*MAR*/
208 /* check for header validity & malloc long... */
209 if (pic->length > 7 && pic->planes < 33 && pic->img_w > 0
210 && pic->img_h > 0) {
211 if (!(pic->addr = (char *) calloc(1, size))) {
212 error = ERR_ALLOC;
213 goto end_depack;
215 } else {
216 error = ERR_HEADER;
217 goto end_depack;
220 patt_len = pic->pat_len;
222 /* jump over the header and possible (XIMG) info */
223 fseek(fp, (long) pic->length * 2L, SEEK_SET);
225 for (line = 0, to = pic->addr; line < pic->img_h;
226 line += scan_repeat) { /* depack whole img */
227 for (plane = 0, scan_repeat = 1; plane < pic->planes;
228 plane++) { /* depack one scan line */
229 puffer = to =
230 pic->addr
231 + (long) (line + plane * pic->img_h) * (long) word_aligned;
232 endline = puffer + width;
233 do { /* depack one line in one bitplane */
234 switch ((opcode = fgetc(fp))) {
235 case 0: /* pattern or scan repeat */
236 if ((patt_repeat = fgetc(fp))) { /* repeat a pattern */
237 fread(to, patt_len, 1, fp);
238 pattern = to;
239 to += patt_len;
240 while (--patt_repeat) { /* copy pattern */
241 memcpy(to, pattern, patt_len);
242 to += patt_len;
244 } else { /* repeat a line */
245 if (fgetc(fp) == 0xFF)
246 scan_repeat = fgetc(fp);
247 else {
248 error = ERR_DEPACK;
249 goto end_depack;
252 break;
253 case 0x80: /* Literal */
254 byte_repeat = fgetc(fp);
255 fread(to, byte_repeat, 1, fp);
256 to += byte_repeat;
257 break;
258 default: /* Solid run */
259 byte_repeat = opcode & 0x7F;
260 sol_pat = opcode & 0x80 ? 0xFF : 0x00;
261 while (byte_repeat--)
262 *to++ = sol_pat;
264 } while (to < endline);
266 if (to == endline) {
267 /* ensure that lines aren't repeated past the end of the img
269 if (line + scan_repeat > pic->img_h)
270 scan_repeat = pic->img_h - line;
271 /* copy line to image buffer */
272 if (scan_repeat > 1) {
273 /* calculate address of a current line in a current
274 * bitplane */
275 /* to=pic->addr+(long)(line+1+plane*pic->img_h)*(long)word_aligned;*/
276 for (b = scan_repeat - 1; b; --b) {
277 memcpy(to, puffer, width);
278 to += word_aligned;
281 } else {
282 error = ERR_DEPACK;
283 goto end_depack;
288 end_depack:
289 fclose(fp);
290 return (error);
294 half_img(MFDB *s, MFDB *d)
296 int pxy[8], i, j;
297 MFDB tmp;
299 mfdb(&tmp, NULL, s->fd_w / 2, s->fd_h, s->fd_stand, s->fd_nplanes);
300 tmp.fd_w = s->fd_w / 2;
301 tmp.fd_addr = calloc(1, mfdb_size(&tmp));
302 if (!tmp.fd_addr)
303 return (FALSE);
305 pxy[1] = pxy[5] = 0;
306 pxy[3] = pxy[7] = s->fd_h - 1;
307 for (i = 0; i < s->fd_w / 2; i++) {
308 pxy[0] = pxy[2] = 2 * i;
309 pxy[4] = pxy[6] = i;
310 vro_cpyfm(x_handle, S_ONLY, pxy, s, &tmp);
312 pxy[0] = pxy[4] = 0;
313 pxy[2] = pxy[6] = s->fd_w / 2 - 1;
314 for (j = 0; j < s->fd_h / 2; j++) {
315 pxy[1] = pxy[3] = 2 * j;
316 pxy[5] = pxy[7] = j;
317 vro_cpyfm(x_handle, S_ONLY, pxy, &tmp, d);
319 free(tmp.fd_addr);
320 return (TRUE);