A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 1141 lines 34 kB view raw
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