Skip to content
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

Screenshots #1

Closed
lights0123 opened this issue Sep 21, 2020 · 4 comments
Closed

Screenshots #1

lights0123 opened this issue Sep 21, 2020 · 4 comments

Comments

@lights0123
Copy link

lights0123 commented Sep 21, 2020

I'm trying to figure out how to decode screenshots. On my CX running 4.5.0, TiLP takes this screenshot:
screenshot
However, when trying to decode with this library, I get:
test

As there's black on the bottom, this isn't a swapping-width-and-length issue, nor is it a color conversion error (or if it is, it's not the main issue) as then there would be patterns of identical colors. My guess is that it's a RLE decoding error, as here's what TiLP does:

switch (format)
{
	case CALC_PIXFMT_GRAY_4:
	{
		uint8_t *q;
		uint32_t i, j;

		for (i = 0, j = 0, q = dst; i < input_size;)
		{
			int8_t rec = src[i++];

			if (rec >= 0)
			{
				// Positive count: "repeat 8-bit value" block.
				uint8_t cnt = ((uint8_t)rec) + 1;
				uint8_t val = src[i++];

				if (j + cnt > max_output_size)
				{
					ret = ERR_INVALID_SCREENSHOT;
					break;
				}
				memset(q, val, cnt);
				q += cnt;
				j += cnt;
			}
			else
			{
				// Negative count: "verbatim" block of 8-bit values.
				uint8_t cnt = ((uint8_t)-rec) + 1;

				if (j + cnt > max_output_size)
				{
					ret = ERR_INVALID_SCREENSHOT;
					break;
				}
				memcpy(q, src+i, cnt);
				q += cnt;
				i += cnt;
				j += cnt;
			}
		}

		ret = 0;
	}
	break;

	case CALC_PIXFMT_RGB_565_LE:
	{
		uint8_t *q;
		uint32_t i, j;

		for (i = 0, j = 0, q = dst; i < input_size;)
		{
			int8_t rec = src[i++];

			if (rec >= 0)
			{
				// Positive count: "repeat 32-bit value" block.
				uint8_t cnt = ((uint8_t)rec) + 1;
				uint32_t val;
				uint8_t k;

				if (j + cnt * 4 > max_output_size)
				{
					ret = ERR_INVALID_SCREENSHOT;
					break;
				}
				memcpy(&val, src + i, sizeof(uint32_t));
				for (k = 0; k < cnt; k++)
				{
					memcpy(q, &val, 4);
					q += 4;
				}
				i += 4;
				j += cnt * 4;
			}
			else
			{
				// Negative count: "verbatim" block of 32-bit values.
				uint8_t cnt = ((uint8_t)-rec) + 1;

				if (j + cnt * 4 > max_output_size)
				{
					ret = ERR_INVALID_SCREENSHOT;
					break;
				}
				memcpy(q, src + i, cnt * 4);
				q += cnt * 4;
				i += cnt * 4;
				j += cnt * 4;
			}
		}

		ret = 0;
	}
	break;

	default:
	{
		ticalcs_critical(_("Unknown pixel format %d\n"), format);
		ret = ERR_INVALID_PARAMETER;
	}
}

versus this library:

while (in_size > 1 && out_size) {
	if (ptr->len < 0) {
		len = -(ptr->len) + 1;
		len = len < out_size ? len : out_size;
		len = len < in_size ? len : in_size;

		memcpy(out, &ptr->byte, len);

		in_size -= (1 + (len));
		ptr = (void*)((unsigned char*)ptr + (1 + (len)));
	} else {
		len = ptr->len + 1;
		len = len < out_size ? len : out_size;
		memset(out, ptr->byte, len);

		in_size -= sizeof(struct rle);
		ptr++;
	}

	out_size -= len;
	out += len;
}

This library doesn't switch between calculator variants and is considerably shorter, so I'd then assume that this library is implemented incorrectly.

@lights0123
Copy link
Author

lights0123 commented Sep 21, 2020

Yep:

==1181482==  Uninitialised value was created by a heap allocation
==1181482==    at 0x483A77F: malloc (vg_replace_malloc.c:307)
==1181482==    by 0x221292: nspire_screenshot (screenshot.c:93)

i = malloc(sizeof(*i) + out_len);

@Vogtinator
Copy link
Owner

Vogtinator commented Oct 1, 2020

Looking at the TILP code, for RGB565 the RLE works in 32-bit blocks instead of 8-bit ones, which it doesn't implement. This is missing on https://hackspire.org/index.php?title=USB_Protocol#Screenshot_.28RLE.29 as well.

Vogtinator added a commit that referenced this issue Nov 26, 2022
- Fix typo: bbp -> bpp
- Make the transfer work with big packets
- Fix rle_decode for other bpp values: work in units of 2px
@Vogtinator
Copy link
Owner

Vogtinator commented Nov 26, 2022

Implemented now with 7d7d962, tested with my CX II.

@adriweb
Copy link

adriweb commented Nov 26, 2022

Nice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants