Screenshot
Source: src/screenshot.c · 112 lines · 4 functions.
Module entry points
These functions are exposed to the rest of the project. Open one to follow its decisions and the helpers it calls.
How to read these diagrams
Each function has its own expandable diagram using the actual expressions and statements from this file. Decisions split into True and False; loop bodies are indented. Returns end the function immediately; break and continue follow their C meanings. Arrows between statements show their order when execution reaches them.
These are structural source diagrams before preprocessing, not runtime traces. Conditional compilation and macros remain source expressions. Ternary choices remain inside their statement. Calls are linked separately; callback execution and task scheduling are not inferred.
Functions in this file
encodeScreenshotBase64() · source line 32
static size_t encodeScreenshotBase64(const uint8_t *input, size_t input_size, char *output)
- Execute
size_t input_index = 0U; - Execute
size_t output_index = 0U; - WHILE loop
input_index < input_sizeRepeat body while the loop condition permits; then continue below.
- Execute
const size_t remaining = input_size - input_index; - Execute
const uint32_t block = (uint32_t)input[input_index] << 16U | (remaining > 1U ? (uint32_t)input[input_index + 1U] << 8U : 0U) | (remaining > 2U ? input[input_index + 2U] : 0U); - Execute
output[output_index++] = screenshot_base64_alphabet[(block >> 18U) & 0x3fU]; - Execute
output[output_index++] = screenshot_base64_alphabet[(block >> 12U) & 0x3fU]; - Execute
output[output_index++] = remaining > 1U ? screenshot_base64_alphabet[(block >> 6U) & 0x3fU] : '='; - Execute
output[output_index++] = remaining > 2U ? screenshot_base64_alphabet[block & 0x3fU] : '='; - Execute
input_index += remaining >= 3U ? 3U : remaining;
- Exit this function
return output_index;
Read original function source
static size_t encodeScreenshotBase64(const uint8_t *input, size_t input_size, char *output)
{
size_t input_index = 0U;
size_t output_index = 0U;
while (input_index < input_size) {
const size_t remaining = input_size - input_index;
const uint32_t block = (uint32_t)input[input_index] << 16U |
(remaining > 1U ? (uint32_t)input[input_index + 1U] << 8U : 0U) |
(remaining > 2U ? input[input_index + 2U] : 0U);
output[output_index++] = screenshot_base64_alphabet[(block >> 18U) & 0x3fU];
output[output_index++] = screenshot_base64_alphabet[(block >> 12U) & 0x3fU];
output[output_index++] = remaining > 1U ?
screenshot_base64_alphabet[(block >> 6U) & 0x3fU] : '=';
output[output_index++] = remaining > 2U ? screenshot_base64_alphabet[block & 0x3fU] : '=';
input_index += remaining >= 3U ? 3U : remaining;
}
return output_index;
}sendScreenshotBase64() · source line 51
static bool sendScreenshotBase64(const uint8_t *pixels)
Calls into this documentation:
- FOR loop
size_t offset = 0U; offset < SCREENSHOT_RGB565_BYTES; offset += SCREENSHOT_BASE64_INPUT_BYTESRepeat body while the loop condition permits; then continue below.
- Execute
const size_t remaining = SCREENSHOT_RGB565_BYTES - offset; - Execute
const size_t input_size = remaining < SCREENSHOT_BASE64_INPUT_BYTES ? remaining : SCREENSHOT_BASE64_INPUT_BYTES; - Execute
char line[sizeof(screenshot_data_prefix) + SCREENSHOT_BASE64_OUTPUT_BYTES + 1U]; - Execute
const size_t prefix_size = sizeof(screenshot_data_prefix) - 1U; - Execute
memcpy(line, screenshot_data_prefix, prefix_size); - Execute
const size_t encoded_size = encodeScreenshotBase64(pixels + offset, input_size, line + prefix_size); - Execute
line[prefix_size + encoded_size] = '\n'; - Execute
const size_t line_size = prefix_size + encoded_size + 1U; - Decision
fwrite(line, 1U, line_size, stdout) != line_sizeTrue- Exit this function
return false;
FalseContinue after this decision.
- Exit this function
return fflush(stdout) == 0;
Read original function source
static bool sendScreenshotBase64(const uint8_t *pixels)
{
for (size_t offset = 0U; offset < SCREENSHOT_RGB565_BYTES;
offset += SCREENSHOT_BASE64_INPUT_BYTES) {
const size_t remaining = SCREENSHOT_RGB565_BYTES - offset;
const size_t input_size = remaining < SCREENSHOT_BASE64_INPUT_BYTES ?
remaining : SCREENSHOT_BASE64_INPUT_BYTES;
char line[sizeof(screenshot_data_prefix) + SCREENSHOT_BASE64_OUTPUT_BYTES + 1U];
const size_t prefix_size = sizeof(screenshot_data_prefix) - 1U;
memcpy(line, screenshot_data_prefix, prefix_size);
const size_t encoded_size = encodeScreenshotBase64(pixels + offset, input_size,
line + prefix_size);
line[prefix_size + encoded_size] = '\n';
const size_t line_size = prefix_size + encoded_size + 1U;
if (fwrite(line, 1U, line_size, stdout) != line_size) return false;
}
return fflush(stdout) == 0;
}screenshotRequest() · source line 70
void screenshotRequest(const char *source_label)
- Decision
source_label == NULL || source_label[0] == '\0'True- Execute
source_label = "unknown";
FalseContinue after this decision.
- Execute
const size_t label_length = strnlen(source_label, sizeof(screenshot_source_label) - 1U); - Execute
memcpy(screenshot_source_label, source_label, label_length); - Execute
screenshot_source_label[label_length] = '\0'; - Execute
screenshot_requested = true;
Read original function source
void screenshotRequest(const char *source_label)
{
if (source_label == NULL || source_label[0] == '\0') source_label = "unknown";
const size_t label_length = strnlen(source_label, sizeof(screenshot_source_label) - 1U);
memcpy(screenshot_source_label, source_label, label_length);
screenshot_source_label[label_length] = '\0';
screenshot_requested = true;
}screenshotCapturePresentation() · source line 79
void screenshotCapturePresentation(const uint16_t *presentation_frame)
Calls into this documentation:
- Decision
screenshot_notice_visible && (xTaskGetTickCount() - screenshot_notice_started_at) >= pdMS_TO_TICKS(SCREENSHOT_NOTICE_MS)True- Execute
globalOverlayClearItem(SCREENSHOT_NOTICE_OVERLAY_ITEM); - Execute
screenshot_notice_visible = false;
FalseContinue after this decision.
- Decision
!screenshot_requested || presentation_frame == NULLTrue- Exit this function
return;
FalseContinue after this decision.
- Execute
screenshot_requested = false; - Execute
char header[SCREENSHOT_SOURCE_LABEL_LENGTH + 48U]; - Execute
const int header_length = snprintf(header, sizeof(header), "\nMINI_ARCADE_SCREENSHOT BASE64RGB565LE 320 170 %s\n", screenshot_source_label); - Execute
const bool header_valid = header_length > 0 && (size_t)header_length < sizeof(header); - Execute
const bool sent = header_valid && fwrite(header, 1U, (size_t)header_length, stdout) == (size_t)header_length && sendScreenshotBase64((const uint8_t *)presentation_frame) && fputs("MINI_ARCADE_SCREENSHOT END\n", stdout) >= 0 && fflush(stdout) == 0; - Decision
!sentTrue- Execute
ESP_LOGE(TAG, "Screenshot USB write incomplete"); - Exit this function
return;
FalseContinue after this decision.
- Execute
ESP_LOGI(TAG, "Screenshot sent: %u RGB565 bytes", (unsigned)SCREENSHOT_RGB565_BYTES); - Execute
(void)globalOverlaySetItem(SCREENSHOT_NOTICE_OVERLAY_ITEM, "SCREENSHOT SENT", 40, 76, 2, C64_COLOR_LIGHT_GREEN); - Execute
screenshot_notice_started_at = xTaskGetTickCount(); - Execute
screenshot_notice_visible = true;
Read original function source
void screenshotCapturePresentation(const uint16_t *presentation_frame)
{
if (screenshot_notice_visible &&
(xTaskGetTickCount() - screenshot_notice_started_at) >=
pdMS_TO_TICKS(SCREENSHOT_NOTICE_MS)) {
globalOverlayClearItem(SCREENSHOT_NOTICE_OVERLAY_ITEM);
screenshot_notice_visible = false;
}
if (!screenshot_requested || presentation_frame == NULL) return;
screenshot_requested = false;
// Text-only Base64 lines keep arbitrary RGB565 byte values separate from console logging.
char header[SCREENSHOT_SOURCE_LABEL_LENGTH + 48U];
const int header_length = snprintf(header, sizeof(header),
"\nMINI_ARCADE_SCREENSHOT BASE64RGB565LE 320 170 %s\n",
screenshot_source_label);
const bool header_valid = header_length > 0 && (size_t)header_length < sizeof(header);
const bool sent = header_valid && fwrite(header, 1U, (size_t)header_length, stdout) ==
(size_t)header_length &&
sendScreenshotBase64((const uint8_t *)presentation_frame) &&
fputs("MINI_ARCADE_SCREENSHOT END\n", stdout) >= 0 && fflush(stdout) == 0;
if (!sent) {
ESP_LOGE(TAG, "Screenshot USB write incomplete");
return;
}
ESP_LOGI(TAG, "Screenshot sent: %u RGB565 bytes", (unsigned)SCREENSHOT_RGB565_BYTES);
// Set this after the bytes are sent, so the saved image remains an exact screen capture.
(void)globalOverlaySetItem(SCREENSHOT_NOTICE_OVERLAY_ITEM, "SCREENSHOT SENT", 40, 76, 2,
C64_COLOR_LIGHT_GREEN);
screenshot_notice_started_at = xTaskGetTickCount();
screenshot_notice_visible = true;
}Complete original file, including constants and data
/* Coded By JD(2026) */
#error "Reference listing only — not provided as build-ready source."
#include "screenshot.h"
#include "c64_colors.h"
#include "esp_log.h"
#include "global_overlay.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <stdio.h>
#include <string.h>
#define SCREENSHOT_WIDTH 320U
#define SCREENSHOT_HEIGHT 170U
#define SCREENSHOT_RGB565_BYTES (SCREENSHOT_WIDTH * SCREENSHOT_HEIGHT * sizeof(uint16_t))
#define SCREENSHOT_BASE64_INPUT_BYTES 192U
#define SCREENSHOT_BASE64_OUTPUT_BYTES \
(((SCREENSHOT_BASE64_INPUT_BYTES + 2U) / 3U) * 4U)
#define SCREENSHOT_SOURCE_LABEL_LENGTH 48U
#define SCREENSHOT_NOTICE_MS 1000U
#define SCREENSHOT_NOTICE_OVERLAY_ITEM 1U
static const char *const TAG = "screenshot";
static const char screenshot_base64_alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char screenshot_data_prefix[] = "MINI_ARCADE_SCREENSHOT DATA ";
static bool screenshot_requested;
static char screenshot_source_label[SCREENSHOT_SOURCE_LABEL_LENGTH] = "unknown";
static bool screenshot_notice_visible;
static TickType_t screenshot_notice_started_at;
static size_t encodeScreenshotBase64(const uint8_t *input, size_t input_size, char *output)
{
size_t input_index = 0U;
size_t output_index = 0U;
while (input_index < input_size) {
const size_t remaining = input_size - input_index;
const uint32_t block = (uint32_t)input[input_index] << 16U |
(remaining > 1U ? (uint32_t)input[input_index + 1U] << 8U : 0U) |
(remaining > 2U ? input[input_index + 2U] : 0U);
output[output_index++] = screenshot_base64_alphabet[(block >> 18U) & 0x3fU];
output[output_index++] = screenshot_base64_alphabet[(block >> 12U) & 0x3fU];
output[output_index++] = remaining > 1U ?
screenshot_base64_alphabet[(block >> 6U) & 0x3fU] : '=';
output[output_index++] = remaining > 2U ? screenshot_base64_alphabet[block & 0x3fU] : '=';
input_index += remaining >= 3U ? 3U : remaining;
}
return output_index;
}
static bool sendScreenshotBase64(const uint8_t *pixels)
{
for (size_t offset = 0U; offset < SCREENSHOT_RGB565_BYTES;
offset += SCREENSHOT_BASE64_INPUT_BYTES) {
const size_t remaining = SCREENSHOT_RGB565_BYTES - offset;
const size_t input_size = remaining < SCREENSHOT_BASE64_INPUT_BYTES ?
remaining : SCREENSHOT_BASE64_INPUT_BYTES;
char line[sizeof(screenshot_data_prefix) + SCREENSHOT_BASE64_OUTPUT_BYTES + 1U];
const size_t prefix_size = sizeof(screenshot_data_prefix) - 1U;
memcpy(line, screenshot_data_prefix, prefix_size);
const size_t encoded_size = encodeScreenshotBase64(pixels + offset, input_size,
line + prefix_size);
line[prefix_size + encoded_size] = '\n';
const size_t line_size = prefix_size + encoded_size + 1U;
if (fwrite(line, 1U, line_size, stdout) != line_size) return false;
}
return fflush(stdout) == 0;
}
void screenshotRequest(const char *source_label)
{
if (source_label == NULL || source_label[0] == '\0') source_label = "unknown";
const size_t label_length = strnlen(source_label, sizeof(screenshot_source_label) - 1U);
memcpy(screenshot_source_label, source_label, label_length);
screenshot_source_label[label_length] = '\0';
screenshot_requested = true;
}
void screenshotCapturePresentation(const uint16_t *presentation_frame)
{
if (screenshot_notice_visible &&
(xTaskGetTickCount() - screenshot_notice_started_at) >=
pdMS_TO_TICKS(SCREENSHOT_NOTICE_MS)) {
globalOverlayClearItem(SCREENSHOT_NOTICE_OVERLAY_ITEM);
screenshot_notice_visible = false;
}
if (!screenshot_requested || presentation_frame == NULL) return;
screenshot_requested = false;
// Text-only Base64 lines keep arbitrary RGB565 byte values separate from console logging.
char header[SCREENSHOT_SOURCE_LABEL_LENGTH + 48U];
const int header_length = snprintf(header, sizeof(header),
"\nMINI_ARCADE_SCREENSHOT BASE64RGB565LE 320 170 %s\n",
screenshot_source_label);
const bool header_valid = header_length > 0 && (size_t)header_length < sizeof(header);
const bool sent = header_valid && fwrite(header, 1U, (size_t)header_length, stdout) ==
(size_t)header_length &&
sendScreenshotBase64((const uint8_t *)presentation_frame) &&
fputs("MINI_ARCADE_SCREENSHOT END\n", stdout) >= 0 && fflush(stdout) == 0;
if (!sent) {
ESP_LOGE(TAG, "Screenshot USB write incomplete");
return;
}
ESP_LOGI(TAG, "Screenshot sent: %u RGB565 bytes", (unsigned)SCREENSHOT_RGB565_BYTES);
// Set this after the bytes are sent, so the saved image remains an exact screen capture.
(void)globalOverlaySetItem(SCREENSHOT_NOTICE_OVERLAY_ITEM, "SCREENSHOT SENT", 40, 76, 2,
C64_COLOR_LIGHT_GREEN);
screenshot_notice_started_at = xTaskGetTickCount();
screenshot_notice_visible = true;
}