-
-
Notifications
You must be signed in to change notification settings - Fork 498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding png chunk cartridge support #2045
Conversation
@@ -141,14 +165,25 @@ png_buffer png_write(png_img src) | |||
PNG_FILTER_TYPE_DEFAULT | |||
); | |||
|
|||
// Save cartridge data in a chunk too. This supports bigger cartridges than steganography | |||
if (cart.data && cart.size > 0 && cart.size <= 0x7fffff){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you store the cart data in the caRt
chunk in addition to the steganographic data and it looks redundant, we are doubling the cart data in two places. I suggest letting the user decide how to save the .png
by adding console command options like save cart.png [way=(steno | caRt | both)]
.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(bztsrc is having issues logging into github and asked someone to forward this response.)
Here you store the cart data in the caRt chunk in addition to the steganographic data and it looks redundant, we are doubling the cart data in two places.
Only for now to provide backward compatibility.
I suggest letting the user decide
I think it would be much wiser to abandon steganography entirely instead. My reasons:
- steganography has very limited storage capacity (98k tops)
- it silently fails if the cartridge data happens to be bigger than that
- it is extremely vulnerable to data corruption
- has no means at all to detect data corruption
On the other hand, chunk based storage
- has unlimited storage capacity (up to 2^31)
- can't silently fail on save, it always works
- has a CRC to detect data corruption (handled by libpng automatically)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I think we need to maintain backwards compatibility - to continue to READ old steganography but if you make changes and save that cartridge it should be encoded as PNG chunk metadata. Giving the user 3 different choices is kind of the worst of all approaches.
Ah, that stupid verification code email finally arrived, I can answer again.
Agree. I haven't removed the stegano writer part yet, because we have to wait until everybody starts using the new version, but I agree after a transition period stegano-write should go, leaving only stegano-read for backward compatibility. |
@nesbox: Review needed please. Plus here's a little addition to cart.c, which fixes issue #2048 It loads the cartridge data without using libpng (which is not linked with libtic80core.a), and this adds support for PNG cartridges in libretro (and probably on other systems as well). Needs this PNG chunk writer PR to be merged first of course, as it can only read the chunk. diff --git a/src/cart.c b/src/cart.c
index 9be32c7..2d66fe1 100644
--- a/src/cart.c
+++ b/src/cart.c
@@ -85,6 +85,37 @@ void tic_cart_load(tic_cartridge* cart, const u8* buffer, s32 size)
memset(cart, 0, sizeof(tic_cartridge));
const u8* end = buffer + size;
+ // NOTE by bzt: we do not have libpng support here in libtic80core.a, so steganography is
+ // completely out of question, but we can find and uncompress a chunk ourself pretty easily
+ u8 *chunk_cart = NULL;
+
+ // check if this cartridge is in PNG format
+ if (!memcmp(buffer, "\x89PNG", 4))
+ {
+ s32 siz;
+ const u8* ptr = buffer + 8;
+ // iterate on chunks until we find a cartridge
+ while (ptr < end)
+ {
+ siz = ((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]);
+ if (!memcmp(ptr + 4, "caRt", 4) && siz > 0)
+ {
+ chunk_cart = malloc(TIC_BINARY_SIZE);
+ if (chunk_cart)
+ {
+ size = tic_tool_unzip(chunk_cart, TIC_BINARY_SIZE, ptr + 8, siz);
+ buffer = chunk_cart;
+ end = buffer + size;
+ }
+ break;
+ }
+ ptr += siz + 12;
+ }
+ // error, no TIC-80 cartridge chunk in PNG???
+ if (!chunk_cart)
+ return;
+ }
+
#define LOAD_CHUNK(to) memcpy(&to, ptr, MIN(sizeof(to), chunk->size ? retro_le_to_cpu16(chunk->size) : TIC_BANK_SIZE))
// load palette chunk first
@@ -219,6 +250,10 @@ void tic_cart_load(tic_cartridge* cart, const u8* buffer, s32 size)
}
}
}
+
+ // if we have allocated the buffer from a PNG chunk
+ if (chunk_cart)
+ free(chunk_cart);
} Cheers, |
I like that we get this advantage effectively "for free" if we switch to chunks. |
Happy Xmas! @nesbox: any chance of a review please? Cheers, |
@bztsrc hi, sorry for the delay with the review, too little time due to moving to another country. |
@nesbox: no worries!
Not sure what you mean. This patch handles both, and with the cart.c patch it even handles both tic and png cartridges in libretro (a feature that's not working ATM).
Definitely, but that would require a refactor, out of scope of this PR which is about to introduce png chunk storage. Could be done a future PR, but first this functionality should be added.
But I do. Unnecessary bloat for nothing. Implementing steganography in tic80core requires a lot of work for a technology that's obsoleted by this PR. This PR isn't about hacking stegano into libtic80core, this is about the replace stegano with a much better solution (that as a side effect, solves the libtic80core png loading issue too). But the emphasis is on replacing the unreliable, vulnerable and limited capacity stegano in the first place. Cheers, |
Exactly, 100% agree. The new proposed solution paves the road for easily integrating PNG loading support in additional places, with almost (exactly?) zero new dependencies - that's a win win. If someone else LATER wanted to come along and add steganography support to libtic80core - that would be a sep PR. But if this new method is better in all regards I also don't see the point in continuing to push steganography, esp. with the states known issues and incompatibilities. Do you disagree with the new method is much better? |
Happy new year!
Exactly zero. The cart.c patch only needs
Yeah, I'd like to hear your opinion too, if you don't want this PR, I wouldn't force it any more. Cheers, |
@bztsrc Bigger picture would you be interested in doing any of the work to deprecate/remove steganography if we decided to go this direction? For example (one idea): removing the functionality completely - and replacing it with a tiny utility (or script) that converts a PNG from steganography to a DATA chunk. A webpage could possibly even do this... I wish we know how commonly cartridges are even passed around as PNGs out there in the wild... |
Considering that I've already done the bigger part in this PR, yes, sure. If this PR gets merged, I'll add a new PR that refactors png loading, removing stegano-write (I'd keep stegano-read for compatibility), and using one common function to decode png.
I've already created this tool, and it is also available as a web-service (via wasm) here, but you have my permission to add it to the TIC-80 webpage. Originally it was created to convert PICO-8 cartridges to TIC-80, but it can also convert .png files (either with stegano or chunk) to .tic and vice versa. If the input is a .tic file, then the output is a .png which includes the data as stegano (if it fits, for backward compatibility) as well as in a chunk. This tool uses the default cartridge image and the default font, grabs the title and the author from the script's comments, so the resulting png is 100% pixel correct with the png files saved using TIC-80. Cheers, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe the problem is me, because I implemented the stenography, I don't want to refuse it and because of this I don't see the advantages of the new way :)
ok, let's merge the PR and see how it goes
Isn't it pretty clear steno doesn't have enough bytes for large cartridges? |
As explained in isse #2042 steganography has certain limitations. This patch add support storing the cartridge data in
caRt
PNG chunk as well. For backward compatibility, it still tries to use steganography if the cartridge fits into the pixels, and on load if nocaRt
chunk found, still tries steganography.