this repo has no description
0
fork

Configure Feed

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

Merge pull request #2045 from bztsrc/main

Adding png chunk cartridge support

authored by

Vadim Grigoruk and committed by
GitHub
6d93f9a3 85b7eec9

+64 -19
+4 -4
build/tools/xplode.c
··· 110 110 for(s32 i = 0; i < TIC80_WIDTH * TIC80_HEIGHT; i++) 111 111 ((u32*)img.data)[i] = tic_rgba(&cart->bank0.palette.vbank0.colors[tic_tool_peek4(cart->bank0.screen.data, i)]); 112 112 113 - png_buffer png = png_write(img); 113 + png_buffer png = png_write(img, (png_buffer){NULL, 0}); 114 114 writeFile("cover.png", (FileBuffer){png.size, png.data}); 115 115 printf("cover.png successfully exported\n"); 116 116 ··· 159 159 ((u32*)img.data)[x + y * TIC_SPRITESHEET_SIZE] = tic_rgba(&cart->bank0.palette.vbank0.colors[index]); 160 160 } 161 161 162 - png_buffer png = png_write(img); 162 + png_buffer png = png_write(img, (png_buffer){NULL, 0}); 163 163 writeFile("tiles.png", (FileBuffer){png.size, png.data}); 164 164 printf("tiles.png successfully exported\n"); 165 165 ··· 180 180 ((u32*)img.data)[x + y * TIC_SPRITESHEET_SIZE] = tic_rgba(&cart->bank0.palette.vbank0.colors[index]); 181 181 } 182 182 183 - png_buffer png = png_write(img); 183 + png_buffer png = png_write(img, (png_buffer){NULL, 0}); 184 184 writeFile("sprites.png", (FileBuffer){png.size, png.data}); 185 185 printf("sprites.png successfully exported\n"); 186 186 ··· 195 195 else printf("usage: xplode <cart>\n"); 196 196 197 197 return 0; 198 - } 198 + }
+51 -6
src/ext/png.c
··· 1 1 // MIT License 2 2 3 3 // Copyright (c) 2021 Vadim Grigoruk @nesbox // grigoruk@gmail.com 4 + // Copyright (c) 2022 bzt png chunk stuff 4 5 5 6 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 7 // of this software and associated documentation files (the "Software"), to deal ··· 28 29 #include <png.h> 29 30 #include "tic_assert.h" 30 31 32 + #define EXTRA_CHUNK "caRt" 31 33 #define RGBA_SIZE sizeof(u32) 32 34 33 35 png_buffer png_create(s32 size) ··· 48 50 stream->pos += size; 49 51 } 50 52 51 - png_img png_read(png_buffer buf) 53 + png_img png_read(png_buffer buf, png_buffer *cart) 52 54 { 53 55 png_img res = { 0 }; 54 56 ··· 102 104 103 105 free(rows); 104 106 107 + // Read in cartridge data from chunk if possible 108 + if (cart) 109 + { 110 + png_unknown_chunkp unknowns = NULL; 111 + int num_unknowns; 112 + 113 + png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS, EXTRA_CHUNK, 1); 114 + png_read_end(png, info); 115 + num_unknowns = png_get_unknown_chunks(png, info, &unknowns); 116 + for(s32 i = 0; i < num_unknowns; i++) 117 + if (!memcmp(unknowns[i].name, EXTRA_CHUNK, 5)) 118 + { 119 + cart->size = unknowns[i].size; 120 + cart->data = (u8*)malloc(cart->size); 121 + if (cart->data) 122 + memcpy(cart->data, unknowns[i].data, cart->size); 123 + else 124 + cart->size = 0; 125 + break; 126 + } 127 + } 128 + 105 129 png_destroy_read_struct(&png, &info, NULL); 106 130 } 107 131 ··· 121 145 122 146 static void pngFlushCallback(png_structp png) {} 123 147 124 - png_buffer png_write(png_img src) 148 + png_buffer png_write(png_img src, png_buffer cart) 125 149 { 126 150 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 127 151 png_infop info = png_create_info_struct(png); ··· 141 165 PNG_FILTER_TYPE_DEFAULT 142 166 ); 143 167 168 + // Save cartridge data in a chunk too. This supports bigger cartridges than steganography 169 + if (cart.data && cart.size > 0 && cart.size <= 0x7fffff){ 170 + png_unknown_chunk unknowns = { 0 }; 171 + memcpy(&unknowns.name, EXTRA_CHUNK, 5); 172 + unknowns.data = cart.data; 173 + unknowns.size = cart.size; 174 + unknowns.location = PNG_AFTER_IDAT; 175 + png_set_unknown_chunks(png, info, &unknowns, 1); 176 + png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS, EXTRA_CHUNK, 1); 177 + } 178 + 144 179 png_write_info(png, info); 145 180 146 181 png_bytep* rows = malloc(sizeof(png_bytep) * src.height); ··· 148 183 rows[i] = src.data + src.width * i * RGBA_SIZE; 149 184 150 185 png_write_image(png, rows); 151 - png_write_end(png, NULL); 186 + png_write_end(png, info); 152 187 153 188 png_destroy_write_struct(&png, &info); 154 189 ··· 189 224 190 225 png_buffer png_encode(png_buffer cover, png_buffer cart) 191 226 { 192 - png_img png = png_read(cover); 227 + png_img png = png_read(cover, NULL); 193 228 194 229 const s32 cartBits = cart.size * BITS_IN_BYTE; 195 230 const s32 coverSize = png.width * png.height * RGBA_SIZE - HEADER_SIZE; ··· 206 241 for (s32 i = end; i < coverSize; i++) 207 242 bitcpy(dst, i << 3, (const u8[]){rand()}, 0, header.bits); 208 243 209 - png_buffer out = png_write(png); 244 + png_buffer out = png_write(png, cart); 210 245 211 246 free(png.data); 212 247 ··· 215 250 216 251 png_buffer png_decode(png_buffer cover) 217 252 { 218 - png_img png = png_read(cover); 253 + png_buffer cart = { 0 }; 254 + png_img png = png_read(cover, &cart); 219 255 256 + // if we have a data from a png chunk, use that 257 + if (cart.data && cart.size > 0) 258 + { 259 + if (png.data) 260 + free(png.data); 261 + return cart; 262 + } 263 + 264 + // otherwise fallback to steganography 220 265 if (png.data) 221 266 { 222 267 Header header;
+2 -2
src/ext/png.h
··· 60 60 61 61 png_buffer png_create(s32 size); 62 62 63 - png_img png_read(png_buffer buf); 64 - png_buffer png_write(png_img src); 63 + png_img png_read(png_buffer buf, png_buffer *cart); 64 + png_buffer png_write(png_img src, png_buffer cart); 65 65 66 66 png_buffer png_encode(png_buffer cover, png_buffer cart); 67 67 png_buffer png_decode(png_buffer cover);
+7 -7
src/studio/screens/console.c
··· 1747 1747 png_buffer png = {(u8*)buffer, size}; 1748 1748 bool error = true; 1749 1749 1750 - png_img img = png_read(png); 1750 + png_img img = png_read(png, NULL); 1751 1751 1752 1752 if(img.data) SCOPE(free(img.data)) 1753 1753 { ··· 1829 1829 png_buffer png = {(u8*)buffer, size}; 1830 1830 bool error = true; 1831 1831 1832 - png_img img = png_read(png); 1832 + png_img img = png_read(png, NULL); 1833 1833 1834 1834 if(img.data) SCOPE(free(img.data)) 1835 1835 { ··· 1948 1948 for(s32 i = 0; i < TIC_SPRITESHEET_SIZE * TIC_SPRITESHEET_SIZE; i++) 1949 1949 img.values[i] = tic_rgba(&pal->colors[getSpritePixel(base, i % TIC_SPRITESHEET_SIZE, i / TIC_SPRITESHEET_SIZE)]); 1950 1950 1951 - png_buffer png = png_write(img); 1951 + png_buffer png = png_write(img, (png_buffer){NULL, 0}); 1952 1952 1953 1953 SCOPE(free(png.data)) 1954 1954 { ··· 2258 2258 } 2259 2259 } 2260 2260 2261 - png_buffer png = png_write(img); 2261 + png_buffer png = png_write(img, (png_buffer){NULL, 0}); 2262 2262 2263 2263 SCOPE(free(png.data)) 2264 2264 { ··· 2306 2306 for(s32 i = 0; i < TIC80_WIDTH * TIC80_HEIGHT; i++) 2307 2307 img.values[i] = tic_rgba(&pal->colors[tic_tool_peek4(bank->screen.data, i)]); 2308 2308 2309 - png_buffer png = png_write(img); 2309 + png_buffer png = png_write(img, (png_buffer){NULL, 0}); 2310 2310 2311 2311 SCOPE(free(png.data)) 2312 2312 { ··· 2404 2404 }; 2405 2405 2406 2406 png_buffer template = {(u8*)Cartridge, sizeof Cartridge}; 2407 - png_img img = png_read(template); 2407 + png_img img = png_read(template, NULL); 2408 2408 2409 2409 // draw screen 2410 2410 { ··· 2452 2452 ptr[CoverWidth * y + x] = tic_rgba(pal + tic_tool_peek4(screen, y * TIC80_WIDTH + x)); 2453 2453 } 2454 2454 2455 - cover = png_write(img); 2455 + cover = png_write(img, (png_buffer){NULL, 0}); 2456 2456 2457 2457 free(img.data); 2458 2458 }