summaryrefslogtreecommitdiff
path: root/apps/plugins/xworld/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/xworld/video.c')
-rw-r--r--apps/plugins/xworld/video.c1141
1 files changed, 1141 insertions, 0 deletions
diff --git a/apps/plugins/xworld/video.c b/apps/plugins/xworld/video.c
new file mode 100644
index 0000000000..b4182df7a7
--- /dev/null
+++ b/apps/plugins/xworld/video.c
@@ -0,0 +1,1141 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 Franklin Wei, Benjamin Brown
11 * Copyright (C) 2004 Gregory Montoir
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "video.h"
24#include "video_data.h"
25#include "resource.h"
26#include "serializer.h"
27#include "sys.h"
28#include "file.h"
29
30void polygon_readVertices(struct Polygon* g, const uint8_t *p, uint16_t zoom) {
31 g->bbw = (*p++) * zoom / 64;
32 g->bbh = (*p++) * zoom / 64;
33 g->numPoints = *p++;
34 assert((g->numPoints & 1) == 0 && g->numPoints < MAX_POINTS);
35
36 //Read all points, directly from bytecode segment
37 for (int i = 0; i < g->numPoints; ++i) {
38 struct Point *pt = &g->points[i];
39 pt->x = (*p++) * zoom / 64;
40 pt->y = (*p++) * zoom / 64;
41 }
42}
43
44void video_create(struct Video* v, struct Resource* res, struct System* sys)
45{
46 v->res = res;
47 v->sys = sys;
48}
49
50void video_init(struct Video* v) {
51 v->paletteIdRequested = NO_PALETTE_CHANGE_REQUESTED;
52 v->page_data = v->res->_memPtrStart + MEM_BLOCK_SIZE;
53
54 rb->memset(v->page_data, 0, 4 * VID_PAGE_SIZE);
55
56 for (int i = 0; i < 4; ++i) {
57 v->_pagePtrs[i] = v->page_data + i * VID_PAGE_SIZE;
58 }
59
60 v->_curPagePtr3 = video_getPagePtr(v, 1);
61 v->_curPagePtr2 = video_getPagePtr(v, 2);
62
63 video_changePagePtr1(v, 0xFE);
64
65 v->_interpTable[0] = 0x4000;
66
67 for (int i = 1; i < 0x400; ++i) {
68 v->_interpTable[i] = 0x4000 / i;
69 }
70}
71
72void video_setDataBuffer(struct Video* v, uint8_t *dataBuf, uint16_t offset) {
73
74 v->_dataBuf = dataBuf;
75 v->_pData.pc = dataBuf + offset;
76}
77
78
79/* A shape can be given in two different ways:
80
81 - A list of screenspace vertices.
82 - A list of objectspace vertices, based on a delta from the first vertex.
83
84 This is a recursive function. */
85void video_readAndDrawPolygon(struct Video* v, uint8_t color, uint16_t zoom, const struct Point *pt) {
86
87 uint8_t i = scriptPtr_fetchByte(&v->_pData);
88
89 //This is
90 if (i >= 0xC0) { // 0xc0 = 192
91
92 // WTF ?
93 if (color & 0x80) { //0x80 = 128 (1000 0000)
94 color = i & 0x3F; //0x3F = 63 (0011 1111)
95 }
96
97 // pc is misleading here since we are not reading bytecode but only
98 // vertices informations.
99 polygon_readVertices(&v->polygon, v->_pData.pc, zoom);
100
101 video_fillPolygon(v, color, zoom, pt);
102
103
104
105 } else {
106 i &= 0x3F; //0x3F = 63
107 if (i == 1) {
108 warning("video_readAndDrawPolygon() ec=0x%X (i != 2)", 0xF80);
109 } else if (i == 2) {
110 video_readAndDrawPolygonHierarchy(v, zoom, pt);
111
112 } else {
113 warning("video_readAndDrawPolygon() ec=0x%X (i != 2)", 0xFBB);
114 }
115 }
116
117
118
119}
120
121void video_fillPolygon(struct Video* v, uint16_t color, uint16_t zoom, const struct Point *pt) {
122
123 (void) zoom;
124
125 if (v->polygon.bbw == 0 && v->polygon.bbh == 1 && v->polygon.numPoints == 4) {
126 video_drawPoint(v, color, pt->x, pt->y);
127
128 return;
129 }
130
131 int16_t x1 = pt->x - v->polygon.bbw / 2;
132 int16_t x2 = pt->x + v->polygon.bbw / 2;
133 int16_t y1 = pt->y - v->polygon.bbh / 2;
134 int16_t y2 = pt->y + v->polygon.bbh / 2;
135
136 if (x1 > 319 || x2 < 0 || y1 > 199 || y2 < 0)
137 return;
138
139 v->_hliney = y1;
140
141 uint16_t i, j;
142 i = 0;
143 j = v->polygon.numPoints - 1;
144
145 x2 = v->polygon.points[i].x + x1;
146 x1 = v->polygon.points[j].x + x1;
147
148 ++i;
149 --j;
150
151 drawLine drawFct;
152 if (color < 0x10) {
153 drawFct = &video_drawLineN;
154 } else if (color > 0x10) {
155 drawFct = &video_drawLineP;
156 } else {
157 drawFct = &video_drawLineBlend;
158 }
159
160 uint32_t cpt1 = x1 << 16;
161 uint32_t cpt2 = x2 << 16;
162
163 while (1) {
164 v->polygon.numPoints -= 2;
165 if (v->polygon.numPoints == 0) {
166#if TRACE_FRAMEBUFFER
167 video_dumpFrameBuffers(v, "fillPolygonEnd");
168#endif
169#if TRACE_BG_BUFFER
170 video_dumpBackGroundBuffer(v);
171#endif
172 break;
173 }
174 uint16_t h;
175 int32_t step1 = video_calcStep(v, &v->polygon.points[j + 1], &v->polygon.points[j], &h);
176 int32_t step2 = video_calcStep(v, &v->polygon.points[i - 1], &v->polygon.points[i], &h);
177
178 ++i;
179 --j;
180
181 cpt1 = (cpt1 & 0xFFFF0000) | 0x7FFF;
182 cpt2 = (cpt2 & 0xFFFF0000) | 0x8000;
183
184 if (h == 0) {
185 cpt1 += step1;
186 cpt2 += step2;
187 } else {
188 for (; h != 0; --h) {
189 if (v->_hliney >= 0) {
190 x1 = cpt1 >> 16;
191 x2 = cpt2 >> 16;
192 if (x1 <= 319 && x2 >= 0) {
193 if (x1 < 0) x1 = 0;
194 if (x2 > 319) x2 = 319;
195 (*drawFct)(v, x1, x2, color);
196 }
197 }
198 cpt1 += step1;
199 cpt2 += step2;
200 ++v->_hliney;
201 if (v->_hliney > 199) return;
202 }
203 }
204
205#if TRACE_FRAMEBUFFER
206 video_dumpFrameBuffers(v, "fillPolygonChild");
207#endif
208#if TRACE_BG_BUFFER
209
210 video_dumpBackGroundBuffer(v);
211#endif
212 }
213}
214
215/*
216 What is read from the bytecode is not a pure screnspace polygon but a polygonspace polygon.
217
218*/
219void video_readAndDrawPolygonHierarchy(struct Video* v, uint16_t zoom, const struct Point *pgc) {
220
221 struct Point pt = *pgc;
222 pt.x -= scriptPtr_fetchByte(&v->_pData) * zoom / 64;
223 pt.y -= scriptPtr_fetchByte(&v->_pData) * zoom / 64;
224
225 int16_t childs = scriptPtr_fetchByte(&v->_pData);
226 debug(DBG_VIDEO, "video_readAndDrawPolygonHierarchy childs=%d", childs);
227
228 for ( ; childs >= 0; --childs) {
229
230 uint16_t off = scriptPtr_fetchWord(&v->_pData);
231
232 struct Point po;
233 po = pt;
234 po.x += scriptPtr_fetchByte(&v->_pData) * zoom / 64;
235 po.y += scriptPtr_fetchByte(&v->_pData) * zoom / 64;
236
237 uint16_t color = 0xFF;
238 uint16_t _bp = off;
239 off &= 0x7FFF;
240
241 if (_bp & 0x8000) {
242 color = *v->_pData.pc & 0x7F;
243 v->_pData.pc += 2;
244 }
245
246 uint8_t *bak = v->_pData.pc;
247 v->_pData.pc = v->_dataBuf + off * 2;
248
249
250 video_readAndDrawPolygon(v, color, zoom, &po);
251
252
253 v->_pData.pc = bak;
254 }
255
256
257}
258
259int32_t video_calcStep(struct Video* v, const struct Point *p1, const struct Point *p2, uint16_t *dy) {
260 (void) v;
261 *dy = p2->y - p1->y;
262 return (p2->x - p1->x) * v->_interpTable[*dy] * 4;
263}
264
265void video_drawString(struct Video* v, uint8_t color, uint16_t x, uint16_t y, uint16_t stringId) {
266
267 const struct StrEntry *se = video_stringsTableEng;
268
269 //Search for the location where the string is located.
270 while (se->id != END_OF_STRING_DICTIONARY && se->id != stringId)
271 ++se;
272
273 debug(DBG_VIDEO, "video_drawString(%d, %d, %d, '%s')", color, x, y, se->str);
274
275 //Not found
276 if (se->id == END_OF_STRING_DICTIONARY)
277 return;
278
279
280 //Used if the string contains a return carriage.
281 uint16_t xOrigin = x;
282 int len = rb->strlen(se->str);
283 for (int i = 0; i < len; ++i) {
284
285 if (se->str[i] == '\n') {
286 y += 8;
287 x = xOrigin;
288 continue;
289 }
290
291 video_drawChar(v, se->str[i], x, y, color, v->_curPagePtr1);
292 x++;
293
294 }
295}
296
297void video_drawChar(struct Video* v, uint8_t character, uint16_t x, uint16_t y, uint8_t color, uint8_t *buf) {
298 (void) v;
299 if (x <= 39 && y <= 192) {
300
301 /* each character is 8x8 */
302 const uint8_t *ft = video_font + (character - ' ') * 8;
303
304 /* x is multiplied by 4 and not 8 because there are two pixels per byte */
305 uint8_t *p = buf + x * 4 + y * 160;
306
307 for (int j = 0; j < 8; ++j) {
308 uint8_t ch = *(ft + j);
309 for (int i = 0; i < 4; ++i) {
310 uint8_t b = *(p + i);
311 uint8_t cmask = 0xFF;
312 uint8_t colb = 0;
313 if (ch & 0x80) {
314 colb |= color << 4;
315 cmask &= 0x0F;
316 }
317 ch <<= 1;
318 if (ch & 0x80) {
319 colb |= color;
320 cmask &= 0xF0;
321 }
322 ch <<= 1;
323 *(p + i) = (b & cmask) | colb;
324 }
325 /* skip to the next line (320 pixels = 160 bytes) */
326 p += 160;
327 }
328 }
329}
330
331void video_drawPoint(struct Video* v, uint8_t color, int16_t x, int16_t y) {
332 debug(DBG_VIDEO, "drawPoint(%d, %d, %d)", color, x, y);
333 if (x >= 0 && x <= 319 && y >= 0 && y <= 199) {
334 uint16_t off = y * 160 + x / 2;
335
336 uint8_t cmasko, cmaskn;
337 if (x & 1) {
338 cmaskn = 0x0F;
339 cmasko = 0xF0;
340 } else {
341 cmaskn = 0xF0;
342 cmasko = 0x0F;
343 }
344
345 uint8_t colb = (color << 4) | color;
346 if (color == 0x10) {
347 cmaskn &= 0x88;
348 cmasko = ~cmaskn;
349 colb = 0x88;
350 } else if (color == 0x11) {
351 colb = *(v->_pagePtrs[0] + off);
352 }
353 uint8_t b = *(v->_curPagePtr1 + off);
354 *(v->_curPagePtr1 + off) = (b & cmasko) | (colb & cmaskn);
355 }
356}
357
358/* Blend a line in the current framebuffer (v->_curPagePtr1)
359 */
360void video_drawLineBlend(struct Video* v, int16_t x1, int16_t x2, uint8_t color) {
361 /* silence warnings without XWORLD_DEBUG */
362 (void) color;
363 debug(DBG_VIDEO, "drawLineBlend(%d, %d, %d)", x1, x2, color);
364 int16_t xmax = MAX(x1, x2);
365 int16_t xmin = MIN(x1, x2);
366 uint8_t *p = v->_curPagePtr1 + v->_hliney * 160 + xmin / 2;
367
368 uint16_t w = xmax / 2 - xmin / 2 + 1;
369 uint8_t cmaske = 0;
370 uint8_t cmasks = 0;
371 if (xmin & 1) {
372 --w;
373 cmasks = 0xF7;
374 }
375 if (!(xmax & 1)) {
376 --w;
377 cmaske = 0x7F;
378 }
379
380 if (cmasks != 0) {
381 *p = (*p & cmasks) | 0x08;
382 ++p;
383 }
384 while (w--) {
385 *p = (*p & 0x77) | 0x88;
386 ++p;
387 }
388 if (cmaske != 0) {
389 *p = (*p & cmaske) | 0x80;
390 ++p;
391 }
392
393
394}
395
396void video_drawLineN(struct Video* v, int16_t x1, int16_t x2, uint8_t color) {
397 debug(DBG_VIDEO, "drawLineN(%d, %d, %d)", x1, x2, color);
398 int16_t xmax = MAX(x1, x2);
399 int16_t xmin = MIN(x1, x2);
400 uint8_t *p = v->_curPagePtr1 + v->_hliney * 160 + xmin / 2;
401
402 uint16_t w = xmax / 2 - xmin / 2 + 1;
403 uint8_t cmaske = 0;
404 uint8_t cmasks = 0;
405 if (xmin & 1) {
406 --w;
407 cmasks = 0xF0;
408 }
409 if (!(xmax & 1)) {
410 --w;
411 cmaske = 0x0F;
412 }
413
414 uint8_t colb = ((color & 0xF) << 4) | (color & 0xF);
415 if (cmasks != 0) {
416 *p = (*p & cmasks) | (colb & 0x0F);
417 ++p;
418 }
419 while (w--) {
420 *p++ = colb;
421 }
422 if (cmaske != 0) {
423 *p = (*p & cmaske) | (colb & 0xF0);
424 ++p;
425 }
426
427
428}
429
430void video_drawLineP(struct Video* v, int16_t x1, int16_t x2, uint8_t color) {
431 /* silence warnings without XWORLD_DEBUG */
432 (void) color;
433 debug(DBG_VIDEO, "drawLineP(%d, %d, %d)", x1, x2, color);
434 int16_t xmax = MAX(x1, x2);
435 int16_t xmin = MIN(x1, x2);
436 uint16_t off = v->_hliney * 160 + xmin / 2;
437 uint8_t *p = v->_curPagePtr1 + off;
438 uint8_t *q = v->_pagePtrs[0] + off;
439
440 uint8_t w = xmax / 2 - xmin / 2 + 1;
441 uint8_t cmaske = 0;
442 uint8_t cmasks = 0;
443 if (xmin & 1) {
444 --w;
445 cmasks = 0xF0;
446 }
447 if (!(xmax & 1)) {
448 --w;
449 cmaske = 0x0F;
450 }
451
452 if (cmasks != 0) {
453 *p = (*p & cmasks) | (*q & 0x0F);
454 ++p;
455 ++q;
456 }
457 while (w--) {
458 *p++ = *q++;
459 }
460 if (cmaske != 0) {
461 *p = (*p & cmaske) | (*q & 0xF0);
462 ++p;
463 ++q;
464 }
465
466}
467
468uint8_t *video_getPagePtr(struct Video* v, uint8_t page) {
469 uint8_t *p;
470 if (page <= 3) {
471 p = v->_pagePtrs[page];
472 } else {
473 switch (page) {
474 case 0xFF:
475 p = v->_curPagePtr3;
476 break;
477 case 0xFE:
478 p = v->_curPagePtr2;
479 break;
480 default:
481 p = v->_pagePtrs[0]; // XXX check
482 warning("video_getPagePtr() p != [0,1,2,3,0xFF,0xFE] == 0x%X", page);
483 break;
484 }
485 }
486 return p;
487}
488
489
490
491void video_changePagePtr1(struct Video* v, uint8_t page) {
492 debug(DBG_VIDEO, "video_changePagePtr1(%d)", page);
493 v->_curPagePtr1 = video_getPagePtr(v, page);
494}
495
496
497
498void video_fillPage(struct Video* v, uint8_t pageId, uint8_t color) {
499 debug(DBG_VIDEO, "video_fillPage(%d, %d)", pageId, color);
500 uint8_t *p = video_getPagePtr(v, pageId);
501
502 // Since a palette indice is coded on 4 bits, we need to duplicate the
503 // clearing color to the upper part of the byte.
504 uint8_t c = (color << 4) | color;
505
506 rb->memset(p, c, VID_PAGE_SIZE);
507
508#if TRACE_FRAMEBUFFER
509 video_dumpFrameBuffers(v, "-fillPage");
510#endif
511#if TRACE_BG_BUFFER
512
513 video_dumpBackGroundBuffer(v);
514#endif
515}
516
517
518
519
520
521#if TRACE_FRAMEBUFFER
522#define SCREENSHOT_BPP 3
523int traceFrameBufferCounter = 0;
524uint8_t allFrameBuffers[640 * 400 * SCREENSHOT_BPP];
525
526#endif
527
528
529
530
531
532
533/* This opcode is used once the background of a scene has been drawn in one of the framebuffer:
534 it is copied in the current framebuffer at the start of a new frame in order to improve performances. */
535void video_copyPage(struct Video* v, uint8_t srcPageId, uint8_t dstPageId, int16_t vscroll) {
536
537 debug(DBG_VIDEO, "video_copyPage(%d, %d)", srcPageId, dstPageId);
538
539 if (srcPageId == dstPageId)
540 return;
541
542 uint8_t *p;
543 uint8_t *q;
544
545 if (srcPageId >= 0xFE || !((srcPageId &= 0xBF) & 0x80)) {
546 p = video_getPagePtr(v, srcPageId);
547 q = video_getPagePtr(v, dstPageId);
548 memcpy(q, p, VID_PAGE_SIZE);
549
550 } else {
551 p = video_getPagePtr(v, srcPageId & 3);
552 q = video_getPagePtr(v, dstPageId);
553 if (vscroll >= -199 && vscroll <= 199) {
554 uint16_t h = 200;
555 if (vscroll < 0) {
556 h += vscroll;
557 p += -vscroll * 160;
558 } else {
559 h -= vscroll;
560 q += vscroll * 160;
561 }
562 memcpy(q, p, h * 160);
563 }
564 }
565
566
567#if TRACE_FRAMEBUFFER
568 char name[256];
569 rb->memset(name, 0, sizeof(name));
570 sprintf(name, "copyPage_0x%X_to_0x%X", (p - v->_pagePtrs[0]) / VID_PAGE_SIZE, (q - v->_pagePtrs[0]) / VID_PAGE_SIZE);
571 dumpFrameBuffers(name);
572#endif
573}
574
575
576
577
578void video_copyPagePtr(struct Video* v, const uint8_t *src) {
579 debug(DBG_VIDEO, "video_copyPagePtr()");
580 uint8_t *dst = v->_pagePtrs[0];
581 int h = 200;
582 while (h--) {
583 int w = 40;
584 while (w--) {
585 uint8_t p[] = {
586 *(src + 8000 * 3),
587 *(src + 8000 * 2),
588 *(src + 8000 * 1),
589 *(src + 8000 * 0)
590 };
591 for(int j = 0; j < 4; ++j) {
592 uint8_t acc = 0;
593 for (int i = 0; i < 8; ++i) {
594 acc <<= 1;
595 acc |= (p[i & 3] & 0x80) ? 1 : 0;
596 p[i & 3] <<= 1;
597 }
598 *dst++ = acc;
599 }
600 ++src;
601 }
602 }
603
604
605}
606
607/*
608 uint8_t *video_allocPage() {
609 uint8_t *buf = (uint8_t *)malloc(VID_PAGE_SIZE);
610 rb->memset(buf, 0, VID_PAGE_SIZE);
611 return buf;
612 }
613*/
614
615
616
617#if TRACE_FRAMEBUFFER
618int dumpPaletteCursor = 0;
619#endif
620
621/*
622 Note: The palettes set used to be allocated on the stack but I moved it to
623 the heap so I could dump the four framebuffer and follow how
624 frames are generated.
625*/
626uint8_t pal[NUM_COLORS * 3]; //3 = BYTES_PER_PIXEL
627void video_changePal(struct Video* v, uint8_t palNum) {
628 debug(DBG_VIDEO, "video_changePal(v=0x%08x, palNum=%d", v, palNum);
629 if (palNum >= 32)
630 return;
631
632 uint8_t *p = v->res->segPalettes + palNum * 32; //colors are coded on 2bytes (565) for 16 colors = 32
633 debug(DBG_VIDEO, "segPalettes: 0x%08x", v->res->segPalettes);
634 // Moved to the heap, legacy code used to allocate the palette
635 // on the stack.
636 //uint8_t pal[NUM_COLORS * 3]; //3 = BYTES_PER_PIXEL
637
638 for (int i = 0; i < NUM_COLORS; ++i)
639 {
640 debug(DBG_VIDEO, "i: %d", i);
641 debug(DBG_VIDEO, "p: 0x%08x", p);
642 uint8_t c1 = *(p + 0);
643 uint8_t c2 = *(p + 1);
644 p += 2;
645 pal[i * 3 + 0] = ((c1 & 0x0F) << 2) | ((c1 & 0x0F) >> 2); // r
646 pal[i * 3 + 1] = ((c2 & 0xF0) >> 2) | ((c2 & 0xF0) >> 6); // g
647 pal[i * 3 + 2] = ((c2 & 0x0F) >> 2) | ((c2 & 0x0F) << 2); // b
648 }
649
650 sys_setPalette(v->sys, 0, NUM_COLORS, pal);
651 v->currentPaletteId = palNum;
652
653
654#if TRACE_PALETTE
655 printf("\nuint8_t dumpPalette[48] = {\n");
656 for (int i = 0; i < NUM_COLORS; ++i)
657 {
658 printf("0x%X,0x%X,0x%X,", pal[i * 3 + 0], pal[i * 3 + 1], pal[i * 3 + 2]);
659 }
660 printf("\n};\n");
661#endif
662
663
664#if TRACE_FRAMEBUFFER
665 dumpPaletteCursor++;
666#endif
667}
668
669void video_updateDisplay(struct Video* v, uint8_t pageId) {
670
671 debug(DBG_VIDEO, "video_updateDisplay(%d)", pageId);
672
673 if (pageId != 0xFE) {
674 if (pageId == 0xFF) {
675 /* swap ptrs 2 and 3 */
676 uint8_t* temp = v->_curPagePtr3;
677 v->_curPagePtr3 = v->_curPagePtr2;
678 v->_curPagePtr2 = temp;
679 } else {
680 v->_curPagePtr2 = video_getPagePtr(v, pageId);
681 }
682 }
683
684 //Check if we need to change the palette
685 if (v->paletteIdRequested != NO_PALETTE_CHANGE_REQUESTED) {
686 video_changePal(v, v->paletteIdRequested);
687 v->paletteIdRequested = NO_PALETTE_CHANGE_REQUESTED;
688 }
689
690 //Q: Why 160 ?
691 //A: Because one byte gives two palette indices so
692 // we only need to move 320/2 per line.
693 sys_copyRect(v->sys, 0, 0, 320, 200, v->_curPagePtr2, 160);
694
695#if TRACE_FRAMEBUFFER
696 dumpFrameBuffer(v->_curPagePtr2, allFrameBuffers, 320, 200);
697#endif
698}
699
700void video_saveOrLoad(struct Video* v, struct Serializer *ser) {
701 uint8_t mask = 0;
702 if (ser->_mode == SM_SAVE) {
703 for (int i = 0; i < 4; ++i) {
704 if (v->_pagePtrs[i] == v->_curPagePtr1)
705 mask |= i << 4;
706 if (v->_pagePtrs[i] == v->_curPagePtr2)
707 mask |= i << 2;
708 if (v->_pagePtrs[i] == v->_curPagePtr3)
709 mask |= i << 0;
710 }
711 }
712 struct Entry entries[] = {
713 SE_INT(&v->currentPaletteId, SES_INT8, VER(1)),
714 SE_INT(&v->paletteIdRequested, SES_INT8, VER(1)),
715 SE_INT(&mask, SES_INT8, VER(1)),
716 SE_ARRAY(v->_pagePtrs[0], VID_PAGE_SIZE, SES_INT8, VER(1)),
717 SE_ARRAY(v->_pagePtrs[1], VID_PAGE_SIZE, SES_INT8, VER(1)),
718 SE_ARRAY(v->_pagePtrs[2], VID_PAGE_SIZE, SES_INT8, VER(1)),
719 SE_ARRAY(v->_pagePtrs[3], VID_PAGE_SIZE, SES_INT8, VER(1)),
720 SE_END()
721 };
722 ser_saveOrLoadEntries(ser, entries);
723
724 if (ser->_mode == SM_LOAD) {
725 v->_curPagePtr1 = v->_pagePtrs[(mask >> 4) & 0x3];
726 v->_curPagePtr2 = v->_pagePtrs[(mask >> 2) & 0x3];
727 v->_curPagePtr3 = v->_pagePtrs[(mask >> 0) & 0x3];
728 video_changePal(v, v->currentPaletteId);
729 }
730}
731
732
733
734#if TRACE_FRAMEBUFFER
735
736
737uint8_t allPalettesDump[][48] = {
738
739
740 {
741 0x4, 0x4, 0x4, 0x22, 0x0, 0x0, 0x4, 0x8, 0x11, 0x4, 0xC, 0x15, 0x8, 0x11, 0x19, 0xC, 0x15, 0x1D, 0x15, 0x1D, 0x26, 0x1D, 0x2A, 0x2E, 0x2E, 0x22, 0x0, 0x3F, 0x0, 0x0, 0x33, 0x26, 0x0, 0x37, 0x2A, 0x0, 0x3B, 0x33, 0x0, 0x3F, 0x3B, 0x0, 0x3F, 0x3F, 0x1D, 0x3F, 0x3F, 0x2A,
742 },
743
744 {
745 0x4, 0x4, 0x4, 0xC, 0xC, 0x11, 0x4, 0x8, 0x11, 0x4, 0xC, 0x15, 0x8, 0x11, 0x19, 0xC, 0x15, 0x1D, 0x15, 0x1D, 0x26, 0x1D, 0x2A, 0x2E, 0x2E, 0x22, 0x0, 0x15, 0x11, 0x11, 0x33, 0x26, 0x0, 0x37, 0x2A, 0x0, 0x3B, 0x33, 0x0, 0x3F, 0x3B, 0x0, 0x3F, 0x3F, 0x1D, 0x3F, 0x3F, 0x2A,
746 }
747
748 , {
749 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x4, 0x8, 0x11, 0x4, 0xC, 0x15, 0x8, 0x11, 0x19, 0xC, 0x15, 0x1D, 0x15, 0x1D, 0x26, 0x1D, 0x2A, 0x2E, 0x1D, 0x1D, 0x1D, 0x15, 0x15, 0x15, 0xC, 0x8, 0xC, 0x11, 0x11, 0x15, 0x1D, 0x15, 0x15, 0x15, 0x0, 0x0, 0x0, 0x4, 0xC, 0x3F, 0x3F, 0x2A,
750 }
751
752 , {
753 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x4, 0x8, 0x11, 0x4, 0xC, 0x15, 0x8, 0x11, 0x19, 0xC, 0x15, 0x1D, 0x15, 0x1D, 0x26, 0x1D, 0x2A, 0x2E, 0x1D, 0x1D, 0x1D, 0x15, 0x15, 0x15, 0xC, 0x8, 0xC, 0x11, 0x11, 0x15, 0x1D, 0x15, 0x15, 0x15, 0x0, 0x0, 0x0, 0x4, 0xC, 0x3F, 0x3F, 0x2A,
754 }
755
756 , {
757 0x0, 0x0, 0x0, 0x1D, 0x0, 0x0, 0x4, 0x8, 0x11, 0x4, 0xC, 0x15, 0x8, 0x11, 0x19, 0xC, 0x15, 0x1D, 0x15, 0x1D, 0x26, 0x1D, 0x2A, 0x2E, 0x1D, 0x1D, 0x1D, 0x15, 0x15, 0x15, 0xC, 0x8, 0xC, 0x15, 0x11, 0x19, 0x1D, 0x15, 0x15, 0x15, 0x0, 0x0, 0x0, 0x4, 0xC, 0x3F, 0x3F, 0x2A,
758 }
759
760 , {
761 0x0, 0x4, 0x8, 0x15, 0x1D, 0x1D, 0x0, 0x8, 0x11, 0x4, 0xC, 0x15, 0x8, 0x11, 0x19, 0xC, 0x15, 0x1D, 0xC, 0x19, 0x22, 0x11, 0x1D, 0x26, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x2E, 0x2E, 0x2E, 0xC, 0xC, 0xC, 0x15, 0xC, 0x15, 0xC, 0x15, 0x15, 0x11, 0x19, 0x19, 0x1D, 0x26, 0x26,
762 }
763
764 , {
765 0x0, 0x0, 0x0, 0x0, 0x4, 0xC, 0x4, 0x8, 0x11, 0x4, 0xC, 0x15, 0x8, 0x11, 0x19, 0xC, 0x15, 0x1D, 0x15, 0x1D, 0x26, 0x1D, 0x2A, 0x2E, 0x15, 0x0, 0x0, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0x11, 0x11, 0x11, 0x11, 0x15, 0x26, 0x0, 0x0, 0x33, 0x26, 0x0, 0x3B, 0x33, 0x11,
766 }
767
768 , {
769 0x0, 0x0, 0x0, 0x0, 0x4, 0xC, 0x0, 0x8, 0x11, 0x4, 0xC, 0x15, 0x8, 0x11, 0x19, 0xC, 0x15, 0x1D, 0x15, 0x1D, 0x26, 0x1D, 0x2A, 0x2E, 0x15, 0x0, 0x0, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0x11, 0x11, 0x11, 0x11, 0x15, 0x26, 0x0, 0x0, 0x26, 0x15, 0x0, 0x26, 0x1D, 0x0,
770 }
771
772 , {
773 0x0, 0x0, 0x0, 0x0, 0x4, 0xC, 0x0, 0x8, 0x11, 0x4, 0xC, 0x15, 0x8, 0x11, 0x19, 0xC, 0x15, 0x1D, 0x15, 0x1D, 0x26, 0x1D, 0x2A, 0x2E, 0x15, 0x0, 0x0, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0x11, 0x11, 0x11, 0x11, 0x15, 0x26, 0x0, 0x0, 0x3F, 0x0, 0x0, 0x26, 0x1D, 0x0,
774 }
775
776 , {
777 0x0, 0x0, 0x0, 0x8, 0x4, 0xC, 0x15, 0xC, 0x11, 0x1D, 0x11, 0x0, 0xC, 0x8, 0x11, 0x2E, 0x1D, 0x0, 0x37, 0x26, 0x8, 0x3F, 0x2E, 0x0, 0x0, 0x0, 0x0, 0x11, 0xC, 0x15, 0x26, 0x15, 0x0, 0x15, 0x11, 0x19, 0x1D, 0x15, 0x1D, 0x26, 0x19, 0x19, 0x0, 0x0, 0x0, 0x3F, 0x3F, 0x3F,
778 }
779
780 , {
781 0x0, 0x0, 0x0, 0x8, 0x4, 0xC, 0x37, 0x1D, 0x1D, 0x3B, 0x2A, 0x22, 0x11, 0xC, 0x15, 0x2A, 0x0, 0x0, 0x33, 0x11, 0x0, 0x3F, 0x33, 0x1D, 0x3B, 0x19, 0x0, 0x11, 0x11, 0x19, 0x19, 0x15, 0x1D, 0x22, 0x19, 0x22, 0x2A, 0x1D, 0x26, 0x33, 0x22, 0x26, 0x37, 0x26, 0x22, 0x1D, 0x37, 0x3F,
782 }
783
784 , {
785 0x0, 0x0, 0x0, 0x0, 0x0, 0x1D, 0x4, 0x8, 0xC, 0x2A, 0x1D, 0xC, 0x3F, 0x3B, 0x26, 0x3B, 0x2A, 0x11, 0x2A, 0x0, 0x0, 0x0, 0x11, 0x15, 0x2A, 0x1D, 0x26, 0xC, 0x8, 0xC, 0x8, 0x15, 0x1D, 0x37, 0x26, 0x22, 0x33, 0x11, 0x0, 0x2E, 0x1D, 0x19, 0x22, 0x0, 0x0, 0x3F, 0x33, 0x1D,
786 }
787
788 , {
789 0x0, 0x0, 0x0, 0x0, 0x15, 0x0, 0x4, 0x8, 0xC, 0x0, 0xC, 0x11, 0x8, 0x11, 0x19, 0x0, 0x19, 0x22, 0x2A, 0x0, 0x0, 0x19, 0x15, 0x22, 0x2E, 0x26, 0x2E, 0xC, 0x8, 0xC, 0x0, 0x2E, 0x0, 0x37, 0x26, 0x22, 0x33, 0x11, 0x0, 0x2E, 0x1D, 0x19, 0x1D, 0x0, 0x0, 0x3F, 0x3F, 0x19,
790 }
791
792 , {
793 0x0, 0x0, 0x0, 0x8, 0xC, 0x11, 0x11, 0x11, 0x15, 0x19, 0x15, 0x22, 0x26, 0x19, 0x2A, 0x2E, 0x26, 0x2E, 0x4, 0x4, 0xC, 0x0, 0xC, 0x15, 0x2A, 0x1D, 0x26, 0x0, 0x19, 0x0, 0x0, 0x2A, 0x0, 0x37, 0x26, 0x22, 0x0, 0x15, 0x1D, 0x37, 0x2E, 0x1D, 0x3F, 0x3F, 0x2E, 0x37, 0x37, 0x26,
794 }
795
796 , {
797 0x0, 0x0, 0x0, 0x0, 0x15, 0x0, 0x4, 0x8, 0xC, 0x0, 0xC, 0x11, 0x8, 0x11, 0x19, 0x0, 0x19, 0x22, 0x2A, 0x0, 0x0, 0x19, 0x15, 0x22, 0x2E, 0x26, 0x2E, 0xC, 0x8, 0xC, 0x0, 0x2E, 0x0, 0x37, 0x26, 0x22, 0x33, 0x11, 0x0, 0x2E, 0x1D, 0x19, 0x1D, 0x0, 0x0, 0x3F, 0x3F, 0x19,
798 }
799
800 , {
801 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0x8, 0x0, 0x4, 0xC, 0x8, 0xC, 0x19, 0x11, 0x11, 0x3F, 0x3F, 0x19, 0x0, 0x1D, 0x0, 0x0, 0x3F, 0x0, 0x0, 0x4, 0x8, 0x11, 0x19, 0x11, 0x19, 0x0, 0x0, 0x2E, 0x0, 0x0, 0x3F, 0x0, 0x0, 0x37, 0x1D, 0x15, 0x0, 0x11, 0x11, 0x0, 0x3F, 0x2A,
802 }
803
804 , {
805 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0x0, 0x11, 0x0, 0x0, 0x19, 0x0, 0xC, 0x26, 0x0, 0x15, 0x2E, 0x0, 0x4, 0x8, 0x0, 0x26, 0x11, 0x0, 0x2E, 0x3F, 0x0, 0x0, 0x15, 0x0, 0xC, 0x1D, 0x0, 0x15, 0x2E, 0x0, 0x15, 0x37, 0x0, 0x1D, 0x3F, 0x0, 0xC, 0x1D, 0xC, 0x\
806 1D, 0x26, 0x15,
807 }
808};
809
810
811
812#include "png.h"
813int GL_FCS_SaveAsSpecifiedPNG(char* path, uint8_t* pixels, int depth = 8, int format = PNG_COLOR_TYPE_RGB)
814{
815 png_structp png_ptr = NULL;
816 png_infop info_ptr = NULL;
817 png_byte ** row_pointers = NULL;
818 int status = -1;
819 int bytePerPixel = 0;
820 int y;
821
822 int fd = open (path, "wb");
823 if (fd < 0) {
824 goto fopen_failed;
825 }
826
827 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
828 if (png_ptr == NULL) {
829 goto png_create_write_struct_failed;
830 }
831
832 info_ptr = png_create_info_struct (png_ptr);
833 if (info_ptr == NULL) {
834 goto png_create_info_struct_failed;
835 }
836
837 if (setjmp (png_jmpbuf (png_ptr))) {
838 goto png_failure;
839 }
840
841 /* Set image attributes. */
842
843 png_set_IHDR (png_ptr,
844 info_ptr,
845 640,
846 400,
847 depth,
848 format,
849 PNG_INTERLACE_NONE,
850 PNG_COMPRESSION_TYPE_DEFAULT,
851 PNG_FILTER_TYPE_DEFAULT);
852
853 if (format == PNG_COLOR_TYPE_GRAY )
854 bytePerPixel = depth / 8 * 1;
855 else
856 bytePerPixel = depth / 8 * 3;
857
858 row_pointers = (png_byte **)png_malloc (png_ptr, 400 * sizeof (png_byte *));
859 //for (y = vid.height-1; y >=0; --y)
860 for (y = 0; y < 400; y++)
861 {
862 row_pointers[y] = (png_byte*)&pixels[640 * (400 - y) * bytePerPixel];
863 }
864
865 png_init_io (png_ptr, fp);
866 png_set_rows (png_ptr, info_ptr, row_pointers);
867 png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
868 //png_read_image (png_ptr, info_ptr);//
869
870 status = 0;
871
872 png_free (png_ptr, row_pointers);
873
874
875png_failure:
876png_create_info_struct_failed:
877 png_destroy_write_struct (&png_ptr, &info_ptr);
878
879png_create_write_struct_failed:
880 fclose (fp);
881fopen_failed:
882 return status;
883}
884
885void writeLine(uint8_t *dst, uint8_t *src, int size)
886{
887 uint8_t* dumpPalette;
888
889 if (!dumpPaletteCursor)
890 dumpPalette = allPalettesDump[dumpPaletteCursor];
891 else
892 dumpPalette = pal;
893
894 for( uint8_t twoPixels = 0 ; twoPixels < size ; twoPixels++)
895 {
896 int pixelIndex0 = (*src & 0xF0) >> 4;
897 pixelIndex0 &= 0x10 - 1;
898
899 int pixelIndex1 = (*src & 0xF);
900 pixelIndex1 &= 0x10 - 1;
901
902 //We need to write those two pixels
903 dst[0] = dumpPalette[pixelIndex0 * 3] << 2 | dumpPalette[pixelIndex0 * 3];
904 dst[1] = dumpPalette[pixelIndex0 * 3 + 1] << 2 | dumpPalette[pixelIndex0 * 3 + 1];
905 dst[2] = dumpPalette[pixelIndex0 * 3 + 2] << 2 | dumpPalette[pixelIndex0 * 3 + 2];
906 //dst[3] = 0xFF;
907 dst += SCREENSHOT_BPP;
908
909 dst[0] = dumpPalette[pixelIndex1 * 3] << 2 | dumpPalette[pixelIndex1 * 3];
910 dst[1] = dumpPalette[pixelIndex1 * 3 + 1] << 2 | dumpPalette[pixelIndex1 * 3 + 1];
911 dst[2] = dumpPalette[pixelIndex1 * 3 + 2] << 2 | dumpPalette[pixelIndex1 * 3 + 2];
912 //dst[3] = 0xFF;
913 dst += SCREENSHOT_BPP;
914
915 src++;
916 }
917}
918
919void video_dumpFrameBuffer(uint8_t *src, uint8_t *dst, int x, int y)
920{
921
922 for (int line = 199 ; line >= 0 ; line--)
923 {
924 writeLine(dst + x * SCREENSHOT_BPP + y * 640 * SCREENSHOT_BPP , src + line * 160, 160);
925 dst += 640 * SCREENSHOT_BPP;
926 }
927}
928
929void video_dumpFrameBuffers(char* comment)
930{
931
932 if (!traceFrameBufferCounter)
933 {
934 rb->memset(allFrameBuffers, 0, sizeof(allFrameBuffers));
935 }
936
937
938 dumpFrameBuffer(v->_pagePtrs[1], allFrameBuffers, 0, 0);
939 dumpFrameBuffer(v->_pagePtrs[0], allFrameBuffers, 0, 200);
940 dumpFrameBuffer(v->_pagePtrs[2], allFrameBuffers, 320, 0);
941 //dumpFrameBuffer(v->_pagePtrs[3],allFrameBuffers,320,200);
942
943
944 //if (v->_curPagePtr1 == v->_pagePtrs[3])
945 //
946
947 /*
948 uint8_t* offScreen = sys->getOffScreenFramebuffer();
949 for(int i=0 ; i < 200 ; i++)
950 writeLine(allFrameBuffers+320*3+640*i*3 + 200*640*3, offScreen+320*i/2 , 160);
951 */
952
953
954 int frameId = traceFrameBufferCounter++;
955 //Write bitmap to disk.
956
957
958
959 // Filling TGA header information
960 /*
961 char path[256];
962 sprintf(path,"test%d.tga",traceFrameBufferCounter);
963
964 #define IMAGE_WIDTH 640
965 #define IMAGE_HEIGHT 400
966
967 uint8_t tga_header[18];
968 rb->memset(tga_header, 0, 18);
969 tga_header[2] = 2;
970 tga_header[12] = (IMAGE_WIDTH & 0x00FF);
971 tga_header[13] = (IMAGE_WIDTH & 0xFF00) / 256;
972 tga_header[14] = (IMAGE_HEIGHT & 0x00FF) ;
973 tga_header[15] =(IMAGE_HEIGHT & 0xFF00) / 256;
974 tga_header[16] = 32 ;
975
976
977
978 // Open the file, write both header and payload, close, done.
979 char path[256];
980 sprintf(path,"test%d.tga",traceFrameBufferCounter);
981 FILE* pScreenshot = fopen(path, "wb");
982 fwrite(&tga_header, 18, sizeof(uint8_t), pScreenshot);
983 fwrite(allFrameBuffers, IMAGE_WIDTH * IMAGE_HEIGHT,SCREENSHOT_BPP * sizeof(uint8_t),pScreenshot);
984 fclose(pScreenshot);
985 */
986
987
988 char path[256];
989 //sprintf(path,"%4d%s.png",traceFrameBufferCounter,comment);
990 sprintf(path, "%4d.png", traceFrameBufferCounter);
991
992 GL_FCS_SaveAsSpecifiedPNG(path, allFrameBuffers);
993}
994#endif
995
996#if TRACE_BG_BUFFER
997
998
999
1000uint8_t bgPalette[48] = {
1001 0x8, 0x8, 0xC, 0xC, 0xC, 0x15, 0xC, 0x11, 0x1D, 0x15, 0x2A, 0x3F, 0x1D, 0x19, 0x19, 0x37, 0x2E, 0x2A, 0x26, 0x1D, 0x1D, 0x37, 0x26, 0x22, 0x22, 0xC, 0x0, 0x26, 0x33, 0x3F, 0x11, 0x11, 0x15, 0x11, 0x15, 0x1D, 0x15, 0x19, 0x26, 0x15, 0x1D, 0x37, 0x0, 0x26, 0x3F, 0x2E, 0x15, 0x0,
1002};
1003void bgWriteLine(uint8_t *dst, uint8_t *src, int size)
1004{
1005 uint8_t* dumpPalette;
1006
1007// if (!dumpPaletteCursor)
1008 // dumpPalette = allPalettesDump[dumpPaletteCursor];
1009// else
1010 dumpPalette = bgPalette;
1011
1012 for( uint8_t twoPixels = 0 ; twoPixels < size ; twoPixels++)
1013 {
1014 int pixelIndex0 = (*src & 0xF0) >> 4;
1015 pixelIndex0 &= 0x10 - 1;
1016
1017 int pixelIndex1 = (*src & 0xF);
1018 pixelIndex1 &= 0x10 - 1;
1019
1020 //We need to write those two pixels
1021 dst[0] = dumpPalette[pixelIndex0 * 3] << 2 | dumpPalette[pixelIndex0 * 3];
1022 dst[1] = dumpPalette[pixelIndex0 * 3 + 1] << 2 | dumpPalette[pixelIndex0 * 3 + 1];
1023 dst[2] = dumpPalette[pixelIndex0 * 3 + 2] << 2 | dumpPalette[pixelIndex0 * 3 + 2];
1024 //dst[3] = 0xFF;
1025 dst += 3;
1026
1027 dst[0] = dumpPalette[pixelIndex1 * 3] << 2 | dumpPalette[pixelIndex1 * 3];
1028 dst[1] = dumpPalette[pixelIndex1 * 3 + 1] << 2 | dumpPalette[pixelIndex1 * 3 + 1];
1029 dst[2] = dumpPalette[pixelIndex1 * 3 + 2] << 2 | dumpPalette[pixelIndex1 * 3 + 2];
1030 //dst[3] = 0xFF;
1031 dst += 3;
1032
1033 src++;
1034 }
1035}
1036
1037void bgDumpFrameBuffer(uint8_t *src, uint8_t *dst, int x, int y)
1038{
1039
1040 for (int line = 199 ; line >= 0 ; line--)
1041 {
1042 bgWriteLine(dst + x * 3 + y * 320 * 3 , src + line * 160, 160);
1043 dst += 320 * 3;
1044 }
1045}
1046
1047#include "png.h"
1048int bgSaveAsSpecifiedPNG(char* path, uint8_t* pixels, int depth = 8, int format = PNG_COLOR_TYPE_RGB)
1049{
1050#if 0
1051 FILE * fp;
1052 png_structp png_ptr = NULL;
1053 png_infop info_ptr = NULL;
1054 png_byte ** row_pointers = NULL;
1055 int status = -1;
1056 int bytePerPixel = 0;
1057 int y;
1058
1059 fp = fopen (path, "wb");
1060 if (! fp) {
1061 goto fopen_failed;
1062 }
1063
1064 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1065 if (png_ptr == NULL) {
1066 goto png_create_write_struct_failed;
1067 }
1068
1069 info_ptr = png_create_info_struct (png_ptr);
1070 if (info_ptr == NULL) {
1071 goto png_create_info_struct_failed;
1072 }
1073
1074 if (setjmp (png_jmpbuf (png_ptr))) {
1075 goto png_failure;
1076 }
1077
1078 /* Set image attributes. */
1079
1080 png_set_IHDR (png_ptr,
1081 info_ptr,
1082 320,
1083 200,
1084 depth,
1085 format,
1086 PNG_INTERLACE_NONE,
1087 PNG_COMPRESSION_TYPE_DEFAULT,
1088 PNG_FILTER_TYPE_DEFAULT);
1089
1090 if (format == PNG_COLOR_TYPE_GRAY )
1091 bytePerPixel = depth / 8 * 1;
1092 else
1093 bytePerPixel = depth / 8 * 3;
1094
1095 row_pointers = (png_byte **)png_malloc (png_ptr, 200 * sizeof (png_byte *));
1096 //for (y = vid.height-1; y >=0; --y)
1097 for (y = 0; y < 200; y++)
1098 {
1099 row_pointers[y] = (png_byte*)&pixels[320 * (200 - y) * bytePerPixel];
1100 }
1101
1102 png_init_io (png_ptr, fp);
1103 png_set_rows (png_ptr, info_ptr, row_pointers);
1104 png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
1105 //png_read_image (png_ptr, info_ptr);//
1106
1107 status = 0;
1108
1109 png_free (png_ptr, row_pointers);
1110
1111
1112png_failure:
1113png_create_info_struct_failed:
1114 png_destroy_write_struct (&png_ptr, &info_ptr);
1115
1116png_create_write_struct_failed:
1117 fclose (fp);
1118fopen_failed:
1119 return status;
1120#endif
1121}
1122
1123int bgFrameBufferCounter = 0;
1124
1125void video_dumpBackGroundBuffer()
1126{
1127 if (v->_curPagePtr1 != v->_pagePtrs[0])
1128 return;
1129
1130 uint8_t bgBuffer[320 * 200 * 3];
1131 bgDumpFrameBuffer(v->_curPagePtr1, bgBuffer, 0, 0);
1132
1133
1134 char path[256];
1135 //sprintf(path,"%4d%s.png",traceFrameBufferCounter,comment);
1136 sprintf(path, "bg%4d.png", bgFrameBufferCounter++);
1137
1138 bgSaveAsSpecifiedPNG(path, bgBuffer);
1139}
1140
1141#endif