Mercurial > hg > dmlib
comparison lib64gfx.c @ 407:59244a7ae37f
Move c64 utilities to the engine lib, as we benefit from a common framework.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 03 Nov 2012 02:19:51 +0200 |
parents | |
children | e4b2f689aff6 |
comparison
equal
deleted
inserted
replaced
406:a0160ffdf7e5 | 407:59244a7ae37f |
---|---|
1 /* | |
2 * Functions for reading and converting various restricted | |
3 * C64/etc and/or indexed/paletted graphics formats. | |
4 * Programmed and designed by Matti 'ccr' Hamalainen | |
5 * (C) Copyright 2012 Tecnic Software productions (TNSP) | |
6 * | |
7 * Please read file 'COPYING' for information on license and distribution. | |
8 */ | |
9 #include "lib64gfx.h" | |
10 #include <errno.h> | |
11 | |
12 const char *dmC64ImageTypeNames[DM_C64IFMT_LAST_TYPE] = | |
13 { | |
14 "hires", | |
15 "multicolor", | |
16 "hires interlace", | |
17 "mc interlace", | |
18 "hires fli", | |
19 "mc fli", | |
20 }; | |
21 | |
22 | |
23 // Based on Pepto's palette, stolen from VICE | |
24 DMColor dmC64Palette[C64_NCOLORS] = | |
25 { | |
26 { 0x00, 0x00, 0x00, 0 }, | |
27 { 0xFF, 0xFF, 0xFF, 0 }, | |
28 { 0x68, 0x37, 0x2B, 0 }, | |
29 { 0x70, 0xA4, 0xB2, 0 }, | |
30 { 0x6F, 0x3D, 0x86, 0 }, | |
31 { 0x58, 0x8D, 0x43, 0 }, | |
32 { 0x35, 0x28, 0x79, 0 }, | |
33 { 0xB8, 0xC7, 0x6F, 0 }, | |
34 { 0x6F, 0x4F, 0x25, 0 }, | |
35 { 0x43, 0x39, 0x00, 0 }, | |
36 { 0x9A, 0x67, 0x59, 0 }, | |
37 { 0x44, 0x44, 0x44, 0 }, | |
38 { 0x6C, 0x6C, 0x6C, 0 }, | |
39 { 0x9A, 0xD2, 0x84, 0 }, | |
40 { 0x6C, 0x5E, 0xB5, 0 }, | |
41 { 0x95, 0x95, 0x95, 0 }, | |
42 }; | |
43 | |
44 | |
45 const size_t dmC64DefaultSizes[DT_LAST] = | |
46 { | |
47 C64_SCR_COLOR_SIZE, | |
48 C64_SCR_BITMAP_SIZE, | |
49 C64_SCR_SCREEN_SIZE, | |
50 1, | |
51 C64_SCR_EXTRADATA, | |
52 }; | |
53 | |
54 | |
55 | |
56 DMImage * dmImageAlloc(int width, int height) | |
57 { | |
58 DMImage *img = dmCalloc(1, sizeof(DMImage)); | |
59 if (img == NULL) | |
60 return NULL; | |
61 | |
62 img->width = img->pitch = width; | |
63 img->height = height; | |
64 img->data = dmMalloc(width * height * sizeof(uint8_t)); | |
65 if (img->data == NULL) | |
66 { | |
67 dmFree(img); | |
68 return NULL; | |
69 } | |
70 | |
71 return img; | |
72 } | |
73 | |
74 | |
75 void dmImageFree(DMImage *img) | |
76 { | |
77 if (img != NULL) | |
78 { | |
79 if (!img->constpal) | |
80 { | |
81 dmFree(img->pal); | |
82 } | |
83 dmFree(img->data); | |
84 dmFree(img); | |
85 } | |
86 } | |
87 | |
88 | |
89 int dmImageGetBytesPerPixel(int format) | |
90 { | |
91 switch (format) | |
92 { | |
93 case DM_IFMT_PALETTE : return 1; | |
94 case DM_IFMT_RGB : return 3; | |
95 case DM_IFMT_RGBA : return 4; | |
96 case DM_IFMT_RGB_PLANE : return 3; | |
97 default: return 0; | |
98 } | |
99 } | |
100 | |
101 | |
102 int dmC64ConvertCSData(DMImage *img, | |
103 int xoffs, int yoffs, const uint8_t *buf, | |
104 int width, int height, BOOL multicolor, int *colors) | |
105 { | |
106 int yc, widthpx = width * 8; | |
107 uint8_t *dp; | |
108 | |
109 if (img == NULL) | |
110 return -1; | |
111 if (xoffs < 0 || yoffs < 0) | |
112 return -2; | |
113 if (xoffs > img->width - widthpx || | |
114 yoffs > img->height - height) | |
115 return -3; | |
116 | |
117 dp = img->data + (yoffs * img->pitch) + xoffs; | |
118 | |
119 if (multicolor) | |
120 { | |
121 for (yc = 0; yc < height; yc++) | |
122 { | |
123 const int offs = yc * width; | |
124 int xc; | |
125 uint8_t *d = dp; | |
126 | |
127 for (xc = 0; xc < widthpx / 2; xc++) | |
128 { | |
129 const int b = buf[offs + (xc / 4)]; | |
130 const int v = 6 - ((xc * 2) & 6); | |
131 const uint8_t c = colors[(b >> v) & 3]; | |
132 | |
133 *d++ = c; | |
134 *d++ = c; | |
135 } | |
136 | |
137 dp += img->pitch; | |
138 } | |
139 } | |
140 else | |
141 { | |
142 for (yc = 0; yc < height; yc++) | |
143 { | |
144 const int offs = yc * width; | |
145 int xc; | |
146 uint8_t *d = dp; | |
147 | |
148 for (xc = 0; xc < widthpx; xc++) | |
149 { | |
150 const int b = buf[offs + (xc / 8)]; | |
151 const int v = 7 - (xc & 7); | |
152 const uint8_t c = colors[(b >> v) & 1]; | |
153 | |
154 *d++ = c; | |
155 } | |
156 | |
157 dp += img->pitch; | |
158 } | |
159 } | |
160 | |
161 return 0; | |
162 } | |
163 | |
164 | |
165 static int fmtProbeDrazPaint(const uint8_t *buf, const size_t len) | |
166 { | |
167 if (len == 10051 && buf[0] == 0x00 && buf[1] == 0x58) | |
168 return DM_PROBE_SCORE_GOOD; | |
169 | |
170 return DM_PROBE_SCORE_FALSE; | |
171 } | |
172 | |
173 | |
174 static int fmtProbeDrazPaint20Packed(const uint8_t *buf, const size_t len) | |
175 { | |
176 const char *ident = (const char *) buf + 2; | |
177 if (len > 22 && buf[0] == 0x00 && buf[1] == 0x58 && | |
178 strncmp(ident, "DRAZPAINT ", 10) == 0 && | |
179 ident[11] == '.' && ( | |
180 (ident[10] == '1' && ident[12] == '4') || | |
181 (ident[10] == '2' && ident[12] == '0') | |
182 )) | |
183 return DM_PROBE_SCORE_MAX; | |
184 | |
185 return DM_PROBE_SCORE_FALSE; | |
186 } | |
187 | |
188 | |
189 static int fmtDecodeDrazPaintPacked(DMC64Image *img, const uint8_t *buf, const size_t len, const DMC64ImageFormat *fmt) | |
190 { | |
191 int res; | |
192 uint8_t rleMarker; | |
193 uint8_t *mem, *dst, *dstEnd; | |
194 const uint8_t *src, *srcEnd; | |
195 | |
196 if ((mem = dmMalloc(C64_RAM_SIZE)) == NULL) | |
197 return -1; | |
198 | |
199 rleMarker = *(buf + 0x0d); | |
200 src = buf + 0x0e; | |
201 srcEnd = buf + len; | |
202 dst = mem; | |
203 dstEnd = mem + C64_RAM_SIZE; | |
204 | |
205 while (src <= srcEnd && dst <= dstEnd) | |
206 { | |
207 int c = *src++; | |
208 if (c == rleMarker && src + 2 <= srcEnd) | |
209 { | |
210 int cnt = *src++; | |
211 c = *src++; | |
212 while (cnt-- && dst <= dstEnd) | |
213 *dst++ = c; | |
214 } | |
215 else | |
216 *dst++ = c; | |
217 } | |
218 | |
219 res = dmC64DecodeGenericBMP(img, mem, dst - mem + 1, fmt); | |
220 | |
221 dmFree(mem); | |
222 | |
223 return res; | |
224 } | |
225 | |
226 | |
227 static int fmtProbeDrazLace10(const uint8_t *buf, const size_t len) | |
228 { | |
229 if (len == 18242 && buf[0] == 0x00 && buf[1] == 0x58) | |
230 return DM_PROBE_SCORE_GOOD; | |
231 return DM_PROBE_SCORE_FALSE; | |
232 } | |
233 | |
234 | |
235 static int fmtProbeDrazLace10Packed(const uint8_t *buf, const size_t len) | |
236 { | |
237 const char *ident = (const char *) buf + 2; | |
238 if (len > 22 && buf[0] == 0x00 && buf[1] == 0x58 && | |
239 strncmp(ident, "DRAZLACE! 1.0", 13) == 0) | |
240 return DM_PROBE_SCORE_MAX; | |
241 | |
242 return DM_PROBE_SCORE_FALSE; | |
243 } | |
244 | |
245 | |
246 static BOOL fmtDrazLaceSetLaceType(DMC64Image *img, const struct _DMDecodeOp *op, const uint8_t *buf, const size_t len) | |
247 { | |
248 img->laceType = buf[op->offs] ? DM_C64ILACE_RES : DM_C64ILACE_COLOR; | |
249 img->laceBank2 = 0; | |
250 return TRUE; | |
251 } | |
252 | |
253 | |
254 #define AMICA_DM_PROBE_SIZE 1024 | |
255 static int fmtProbeAmicaPaintPacked(const uint8_t *buf, const size_t len) | |
256 { | |
257 int i, n; | |
258 if (len < AMICA_DM_PROBE_SIZE || buf[0] != 0x00 || buf[1] != 0x40) | |
259 return DM_PROBE_SCORE_FALSE; | |
260 | |
261 for (n = 0, i = 2; i < AMICA_DM_PROBE_SIZE; i++) | |
262 if (buf[i] == 0xC2) n++; | |
263 | |
264 if (n > 5) | |
265 return DM_PROBE_SCORE_GOOD; | |
266 if (n > 3) | |
267 return DM_PROBE_SCORE_AVG; | |
268 | |
269 return DM_PROBE_SCORE_MAYBE; | |
270 } | |
271 | |
272 | |
273 static int fmtDecodeAmicaPaintPacked(DMC64Image *img, const uint8_t *buf, const size_t len, const DMC64ImageFormat *fmt) | |
274 { | |
275 int res; | |
276 uint8_t *mem, *dst, *dstEnd; | |
277 const uint8_t *src, *srcEnd; | |
278 | |
279 if ((mem = dmMalloc(C64_RAM_SIZE)) == NULL) | |
280 return -1; | |
281 | |
282 src = buf; | |
283 srcEnd = buf + len; | |
284 dst = mem; | |
285 dstEnd = mem + C64_RAM_SIZE; | |
286 | |
287 while (src <= srcEnd && dst <= dstEnd) | |
288 { | |
289 int c = *src++; | |
290 if (c == 0xC2 && src + 2 <= srcEnd) | |
291 { | |
292 int cnt = *src++; | |
293 c = *src++; | |
294 while (cnt-- && dst <= dstEnd) | |
295 *dst++ = c; | |
296 } | |
297 else | |
298 *dst++ = c; | |
299 } | |
300 | |
301 res = dmC64DecodeGenericBMP(img, mem, dst - mem + 1, fmt); | |
302 | |
303 dmFree(mem); | |
304 | |
305 return res; | |
306 } | |
307 | |
308 | |
309 static int fmtProbeKoalaPaint(const uint8_t *buf, const size_t len) | |
310 { | |
311 if (len == 10003 && buf[0] == 0x00 && buf[1] == 0x60) | |
312 return DM_PROBE_SCORE_AVG; | |
313 return DM_PROBE_SCORE_FALSE; | |
314 } | |
315 | |
316 | |
317 static int fmtProbeTruePaint(const uint8_t *buf, const size_t len) | |
318 { | |
319 if (len == 19434 && buf[0] == 0x00 && buf[1] == 0x9c) | |
320 return DM_PROBE_SCORE_GOOD; | |
321 return DM_PROBE_SCORE_FALSE; | |
322 } | |
323 | |
324 | |
325 static BOOL fmtTruePaintSetLaceType(DMC64Image *img, const struct _DMDecodeOp *op, const uint8_t *buf, const size_t len) | |
326 { | |
327 img->laceType = DM_C64ILACE_RES; | |
328 img->laceBank2 = 1; | |
329 return TRUE; | |
330 } | |
331 | |
332 | |
333 DMC64ImageFormat dmC64ImageFormats[] = | |
334 { | |
335 { | |
336 DM_C64IFMT_MC, ".drp", "DrazPaint 2.0 (packed)", | |
337 fmtProbeDrazPaint20Packed, fmtDecodeDrazPaintPacked, NULL, | |
338 4, | |
339 { | |
340 { DT_COLOR_RAM, 0x0000, 0, 0, NULL }, | |
341 { DT_BITMAP, 0x0800, 0, 0, NULL }, | |
342 { DT_SCREEN_RAM, 0x0400, 0, 0, NULL }, | |
343 { DT_BGCOLOR, 0x2740, 0, 0, NULL }, | |
344 } | |
345 }, | |
346 | |
347 { | |
348 DM_C64IFMT_MC_ILACE, ".dlp", "DrazLace 1.0 (packed)", | |
349 fmtProbeDrazLace10Packed, fmtDecodeDrazPaintPacked, NULL, | |
350 6, | |
351 { | |
352 { DT_COLOR_RAM, 0x0000, 0, 0, NULL }, | |
353 { DT_BITMAP, 0x0800, 0, 0, NULL }, | |
354 { DT_SCREEN_RAM, 0x0400, 0, 0, NULL }, | |
355 { DT_BGCOLOR, 0x2740, 0, 0, NULL }, | |
356 { DT_BITMAP, 0x2800, 1, 0, NULL }, | |
357 { DT_FUNCTION, 0x2742, 0, 1, fmtDrazLaceSetLaceType }, | |
358 } | |
359 }, | |
360 | |
361 { | |
362 DM_C64IFMT_MC, ".drp", "DrazPaint (unpacked)", | |
363 fmtProbeDrazPaint, NULL, NULL, | |
364 4, | |
365 { | |
366 { DT_COLOR_RAM, 0x0000, 0, 0, NULL }, | |
367 { DT_BITMAP, 0x0800, 0, 0, NULL }, | |
368 { DT_SCREEN_RAM, 0x0400, 0, 0, NULL }, | |
369 { DT_BGCOLOR, 0x2740, 0, 0, NULL }, | |
370 } | |
371 }, | |
372 | |
373 { | |
374 DM_C64IFMT_MC_ILACE, ".drl", "DrazLace 1.0 (unpacked)", | |
375 fmtProbeDrazLace10, NULL, NULL, | |
376 6, | |
377 { | |
378 { DT_COLOR_RAM, 0x0000, 0, 0, NULL }, | |
379 { DT_BITMAP, 0x0800, 0, 0, NULL }, | |
380 { DT_SCREEN_RAM, 0x0400, 0, 0, NULL }, | |
381 { DT_BGCOLOR, 0x2740, 0, 0, NULL }, | |
382 { DT_BITMAP, 0x2800, 1, 0, NULL }, | |
383 { DT_FUNCTION, 0x2742, 0, 1, fmtDrazLaceSetLaceType }, | |
384 } | |
385 }, | |
386 | |
387 { | |
388 DM_C64IFMT_MC_ILACE, ".mci", "Truepaint (unpacked)", | |
389 fmtProbeTruePaint, NULL, NULL, | |
390 6, | |
391 { | |
392 { DT_SCREEN_RAM, 0x0000, 0, 0, NULL }, | |
393 { DT_BGCOLOR, 0x03e8, 0, 0, NULL }, | |
394 { DT_BITMAP, 0x0400, 0, 0, NULL }, | |
395 { DT_BITMAP, 0x2400, 1, 0, NULL }, | |
396 { DT_SCREEN_RAM, 0x4400, 1, 0, NULL }, | |
397 { DT_COLOR_RAM, 0x4800, 0, 0, NULL }, | |
398 { DT_FUNCTION, 0x0000, 0, 0, fmtTruePaintSetLaceType }, | |
399 } | |
400 }, | |
401 | |
402 { | |
403 DM_C64IFMT_MC, ".kla", "Koala Paint (unpacked)", | |
404 fmtProbeKoalaPaint, NULL, NULL, | |
405 4, | |
406 { | |
407 { DT_COLOR_RAM, 0x2328, 0, 0, NULL }, | |
408 { DT_BITMAP, 0x0000, 0, 0, NULL }, | |
409 { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL }, | |
410 { DT_BGCOLOR, 0x2710, 0, 0, NULL }, | |
411 } | |
412 }, | |
413 | |
414 { | |
415 DM_C64IFMT_MC, ".ami", "Amica Paint (packed)", | |
416 fmtProbeAmicaPaintPacked, fmtDecodeAmicaPaintPacked, NULL, | |
417 4, | |
418 { | |
419 { DT_COLOR_RAM, 0x2328, 0, 0, NULL }, | |
420 { DT_BITMAP, 0x0000, 0, 0, NULL }, | |
421 { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL }, | |
422 { DT_BGCOLOR, 0x2710, 0, 0, NULL }, | |
423 } | |
424 }, | |
425 | |
426 }; | |
427 | |
428 const int ndmC64ImageFormats = sizeof(dmC64ImageFormats) / sizeof(dmC64ImageFormats[0]); | |
429 | |
430 | |
431 int dmC64ProbeGeneric(const uint8_t *buf, const size_t len, | |
432 DMC64ImageFormat **pfmt) | |
433 { | |
434 int i, scoreMax = 0, scoreIndex = -1; | |
435 | |
436 for (i = 0; i < ndmC64ImageFormats; i++) | |
437 { | |
438 DMC64ImageFormat *fmt = &dmC64ImageFormats[i]; | |
439 int score = fmt->probe(buf, len); | |
440 if (score > scoreMax) | |
441 { | |
442 scoreMax = score; | |
443 scoreIndex = i; | |
444 } | |
445 } | |
446 | |
447 if (scoreIndex >= 0) | |
448 { | |
449 *pfmt = &dmC64ImageFormats[scoreIndex]; | |
450 return scoreMax; | |
451 } | |
452 else | |
453 return 0; | |
454 } | |
455 | |
456 | |
457 int dmC64DecodeGenericBMP(DMC64Image *img, const uint8_t *buf, | |
458 const size_t len, const DMC64ImageFormat *fmt) | |
459 { | |
460 int i; | |
461 | |
462 memset(img, 0, sizeof(*img)); | |
463 img->type = fmt->type; | |
464 | |
465 for (i = 0; i < fmt->ndecodeOps; i++) | |
466 { | |
467 const DMDecodeOp *op = &fmt->decodeOps[i]; | |
468 const uint8_t *src; | |
469 size_t size; | |
470 | |
471 if (op->bank < 0 || op->bank >= C64_SCR_MAX_BANK) | |
472 { | |
473 dmError("Invalid bank %d definition in generic decode operator %d @ #%d.\n", | |
474 op->bank, op->type, i); | |
475 return -1; | |
476 } | |
477 | |
478 if (op->type < 0 || op->type >= DT_LAST) | |
479 { | |
480 dmError("Invalid decode operator type %d @ #%d.\n", | |
481 op->type, i); | |
482 return -1; | |
483 } | |
484 | |
485 size = (op->size == 0) ? dmC64DefaultSizes[op->type] : op->size; | |
486 | |
487 if (op->offs + size > len) | |
488 { | |
489 dmError("Decode out of bounds, op #%d type=%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x\n", | |
490 i, op->type, op->offs, op->offs, op->bank, size, size, len, len); | |
491 return -2; | |
492 } | |
493 | |
494 src = buf + op->offs; | |
495 | |
496 switch (op->type) | |
497 { | |
498 case DT_COLOR_RAM: memcpy(img->color[op->bank], src, size); break; | |
499 case DT_BITMAP: memcpy(img->bitmap[op->bank], src, size); break; | |
500 case DT_SCREEN_RAM: memcpy(img->screen[op->bank], src, size); break; | |
501 case DT_BGCOLOR: img->bgcolor = *src; break; | |
502 case DT_EXTRADATA: memcpy(img->extradata, src, size); break; | |
503 case DT_FUNCTION: | |
504 if (op->function == NULL) | |
505 { | |
506 dmError("Decode op is a function, but function ptr is NULL: op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x\n", | |
507 i, op->offs, op->offs, op->bank, size, size, len, len); | |
508 return -6; | |
509 } | |
510 if (!op->function(img, op, buf, len)) | |
511 { | |
512 dmError("Decode op custom function failed: op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x\n", | |
513 i, op->offs, op->offs, op->bank, size, size, len, len); | |
514 return -5; | |
515 } | |
516 break; | |
517 } | |
518 } | |
519 | |
520 return 0; | |
521 } | |
522 | |
523 | |
524 static int dmC64ConvertHiResBMP(DMImage *screen, const DMC64Image *img) | |
525 { | |
526 int yc; | |
527 uint8_t *dp = screen->data; | |
528 | |
529 for (yc = 0; yc < C64_SCR_HEIGHT; yc++) | |
530 { | |
531 uint8_t *d = dp; | |
532 const int y = yc / 8, yb = yc & 7; | |
533 const int scroffsy = y * C64_SCR_CH_WIDTH; | |
534 const int bmoffsy = y * C64_SCR_WIDTH; | |
535 int xc; | |
536 | |
537 for (xc = 0; xc < C64_SCR_WIDTH; xc++) | |
538 { | |
539 const int x = xc / 8; | |
540 const int scroffs = scroffsy + x; | |
541 const int b = img->bitmap[0][bmoffsy + (x * 8) + yb]; | |
542 const int v = 7 - (xc & 7); | |
543 uint8_t c; | |
544 | |
545 if ((b >> v) & 1) | |
546 c = img->screen[0][scroffs] & 15; | |
547 else | |
548 c = img->screen[0][scroffs] >> 4; | |
549 | |
550 *d++ = c; | |
551 } | |
552 | |
553 dp += screen->pitch; | |
554 } | |
555 | |
556 return 0; | |
557 } | |
558 | |
559 | |
560 static int dmC64ConvertMultiColorBMP(DMImage *screen, const DMC64Image *img) | |
561 { | |
562 int yc; | |
563 uint8_t *dp = screen->data; | |
564 | |
565 for (yc = 0; yc < C64_SCR_HEIGHT; yc++) | |
566 { | |
567 uint8_t *d = dp; | |
568 const int y = yc / 8, yb = yc & 7; | |
569 const int scroffsy = y * C64_SCR_CH_WIDTH; | |
570 const int bmoffsy = y * C64_SCR_WIDTH; | |
571 int xc; | |
572 | |
573 for (xc = 0; xc < C64_SCR_WIDTH / 2; xc++) | |
574 { | |
575 const int x = xc / 4; | |
576 const int scroffs = scroffsy + x; | |
577 const int b = img->bitmap[0][bmoffsy + (x * 8) + yb]; | |
578 const int v = 6 - ((xc * 2) & 6); | |
579 uint8_t c; | |
580 | |
581 switch ((b >> v) & 3) | |
582 { | |
583 case 0: c = img->bgcolor; break; | |
584 case 1: c = img->screen[0][scroffs] >> 4; break; | |
585 case 2: c = img->screen[0][scroffs] & 15; break; | |
586 case 3: c = img->color[0][scroffs] & 15; break; | |
587 } | |
588 | |
589 *d++ = c; | |
590 *d++ = c; | |
591 } | |
592 | |
593 dp += screen->pitch; | |
594 } | |
595 | |
596 return 0; | |
597 } | |
598 | |
599 | |
600 static int dmC64ConvertLaceMultiColorBMP(DMImage *screen, const DMC64Image *img) | |
601 { | |
602 int yc; | |
603 uint8_t *dp = screen->data; | |
604 | |
605 for (yc = 0; yc < C64_SCR_HEIGHT; yc++) | |
606 { | |
607 uint8_t *d = dp; | |
608 const int y = yc / 8, yb = yc & 7; | |
609 const int scroffsy = y * C64_SCR_CH_WIDTH; | |
610 const int bmoffsy = y * C64_SCR_WIDTH; | |
611 int xc; | |
612 | |
613 for (xc = 0; xc < C64_SCR_WIDTH / 2; xc++) | |
614 { | |
615 const int x = xc / 4; | |
616 const int scroffs = scroffsy + x; | |
617 const int bmoffs = bmoffsy + (x * 8) + yb; | |
618 const int v = 6 - ((xc * 2) & 6); | |
619 const int b1 = (img->bitmap[0][bmoffs] >> v) & 3; | |
620 const int b2 = (img->bitmap[1][bmoffs] >> v) & 3; | |
621 uint8_t c1, c2; | |
622 | |
623 switch (b1) | |
624 { | |
625 case 0: c1 = img->bgcolor; break; | |
626 case 1: c1 = img->screen[0][scroffs] >> 4; break; | |
627 case 2: c1 = img->screen[0][scroffs] & 15; break; | |
628 case 3: c1 = img->color[0][scroffs] & 15; break; | |
629 } | |
630 | |
631 switch (b2) | |
632 { | |
633 case 0: c2 = img->bgcolor; break; | |
634 case 1: c2 = img->screen[img->laceBank2][scroffs] >> 4; break; | |
635 case 2: c2 = img->screen[img->laceBank2][scroffs] & 15; break; | |
636 case 3: c2 = img->color[img->laceBank2][scroffs] & 15; break; | |
637 } | |
638 | |
639 *d++ = c1; | |
640 *d++ = c2; | |
641 } | |
642 | |
643 dp += screen->pitch; | |
644 } | |
645 | |
646 return 0; | |
647 } | |
648 | |
649 | |
650 int dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src) | |
651 { | |
652 switch (src->type) | |
653 { | |
654 case DM_C64IFMT_HIRES: | |
655 return dmC64ConvertHiResBMP(dst, src); | |
656 | |
657 case DM_C64IFMT_MC: | |
658 return dmC64ConvertMultiColorBMP(dst, src); | |
659 | |
660 case DM_C64IFMT_MC_ILACE: | |
661 return dmC64ConvertLaceMultiColorBMP(dst, src); | |
662 | |
663 default: | |
664 return -1; | |
665 } | |
666 } | |
667 | |
668 | |
669 #define BUF_SIZE_INITIAL (16*1024) | |
670 #define BUF_SIZE_GROW (2*1024) | |
671 | |
672 int dmReadDataFile(const char *filename, uint8_t **pbuf, size_t *pbufSize) | |
673 { | |
674 FILE *f; | |
675 uint8_t *dataBuf = NULL, *dataPtr; | |
676 size_t bufSize, readSize, dataSize; | |
677 | |
678 if (filename == NULL) | |
679 f = stdin; | |
680 else | |
681 if ((f = fopen(filename, "rb")) == NULL) | |
682 { | |
683 int err = errno; | |
684 dmError("Could not open input file '%s': %d, %s\n", | |
685 filename, err, strerror(err)); | |
686 return -1; | |
687 } | |
688 | |
689 readSize = bufSize = BUF_SIZE_INITIAL; | |
690 if ((dataBuf = dmMalloc(bufSize)) == NULL) | |
691 { | |
692 fclose(f); | |
693 dmError("Error allocating memory for data, %d bytes.\n", bufSize); | |
694 return -4; | |
695 } | |
696 | |
697 dataPtr = dataBuf; | |
698 dataSize = 0; | |
699 | |
700 while (!feof(f) && !ferror(f)) | |
701 { | |
702 size_t read = fread(dataPtr, 1, readSize, f); | |
703 | |
704 dataSize += read; | |
705 dataPtr += read; | |
706 | |
707 if (read == readSize && !feof(f)) | |
708 { | |
709 readSize = BUF_SIZE_GROW; | |
710 bufSize += BUF_SIZE_GROW; | |
711 if ((dataBuf = dmRealloc(dataBuf, bufSize)) == NULL) | |
712 { | |
713 dmError("Error reallocating memory for data, %d bytes.\n", bufSize); | |
714 return -4; | |
715 } | |
716 } | |
717 else | |
718 break; | |
719 } | |
720 | |
721 fclose(f); | |
722 | |
723 *pbuf = dataBuf; | |
724 *pbufSize = dataSize; | |
725 | |
726 return 0; | |
727 } |