Skip to content

Screenshots #1

Description

@lights0123

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions