Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,37 @@ debug_save_raw(struct debug_struct* p_debug,
util_file_close(p_file);
}

static void
debug_save_screen(struct debug_struct* p_debug, const char* p_file_name) {
struct util_file* p_file;
struct render_struct* p_render = p_debug->p_render;
uint32_t* p_buffer;
uint32_t size;

if (!render_has_buffer(p_render)) {
(void) printf("no render buffer; start with -headless-render or "
"-frame-cycles\n");
return;
}

p_buffer = render_get_buffer(p_render);
size = render_get_buffer_size(p_render);

p_file = util_file_try_open(p_file_name, 1, 1);
if (p_file == NULL) {
log_do_log(k_log_misc, k_log_warning, "cannot open file %s", p_file_name);
return;
}

util_file_write(p_file, p_buffer, size);
util_file_close(p_file);
(void) printf("saved %ux%u BGRA (%u bytes) to %s\n",
render_get_width(p_render),
render_get_height(p_render),
size,
p_file_name);
}

static void
debug_print_registers(uint8_t reg_a,
uint8_t reg_x,
Expand Down Expand Up @@ -2357,6 +2388,8 @@ debug_callback_common(struct debug_struct* p_debug,
(parse_hex_int3 >= 0) &&
(parse_hex_int3 < 65536)) {
debug_save_raw(p_debug, p_param_1_str, parse_hex_int2, parse_hex_int3);
} else if (!strcmp(p_command, "savescreen") && (p_param_1_str != NULL)) {
debug_save_screen(p_debug, p_param_1_str);
} else if (!strcmp(p_command, "ss")) {
state_save(p_bbc, p_param_1_str);
} else if (!strcmp(p_command, "d")) {
Expand Down Expand Up @@ -2526,6 +2559,7 @@ debug_callback_common(struct debug_struct* p_debug,
"find <a> <l> ... : find a byte sequence, starting at <a>, length <l>\n"
"loadmem <f> <a> : load memory to <a> from raw file <f>\n"
"savemem <f> <a> <l>: save memory from <a>, length <l> to raw file <f>\n"
"savescreen <f> : save render buffer to raw BGRA file <f>\n"
"sys : show system VIA registers\n"
"user : show user VIA registers\n"
"r : show regular registers\n"
Expand Down
6 changes: 5 additions & 1 deletion main.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ beebjit_main(void) {
int disc_mutable_flag = 0;
int terminal_flag = 0;
int headless_flag = 0;
int headless_render_flag = 0;
int fasttape_flag = 0;
int convert_hfe_flag = 0;
int convert_ssd_flag = 0;
Expand Down Expand Up @@ -307,6 +308,8 @@ beebjit_main(void) {
terminal_flag = 1;
} else if (!strcmp(arg, "-headless")) {
headless_flag = 1;
} else if (!strcmp(arg, "-headless-render")) {
headless_render_flag = 1;
} else if (!strcmp(arg, "-fasttape")) {
fasttape_flag = 1;
} else if (!strcmp(arg, "-convert-hfe")) {
Expand Down Expand Up @@ -394,6 +397,7 @@ beebjit_main(void) {
"-max-frames <m>: max frame images to save, default 1.\n"
"-exit-on-max-frames: exit the process once max-frames is hit.\n"
"-frames-dir <d>: directory for frame files, default '.'.\n"
"-headless-render : in -headless mode, allocate a render buffer.\n"
"-watford : for a model B with a 1770, load Watford DDFS ROM.\n"
"-opus : for a model B with a 1770, load Opus DDOS ROM.\n"
"-dfs12 : for a model B with an 8271, load newer DFS v1.2 ROM.\n"
Expand Down Expand Up @@ -594,7 +598,7 @@ beebjit_main(void) {
render_set_buffer(p_render, p_render_buffer);

window_handle = os_window_get_handle(p_window);
} else if (frame_cycles > 0) {
} else if ((frame_cycles > 0) || headless_render_flag) {
/* TODO: push this down into video.c. */
render_create_internal_buffer(p_render);
}
Expand Down
32 changes: 32 additions & 0 deletions run_functional_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,38 @@ echo 'Checking RVI rendering.'
-opt video:always-render \
-commands "breakat 11000000;c;eval '(frame_buffer_crc32==0x2c23c1b6)||bail';q"

echo 'Checking -headless-render produces matching framebuffer.'
# This re-runs the RVI rendering scenario in headless mode with
# -headless-render. The CRC must match the GUI-mode value above, proving
# that headless rendering is pixel-identical to GUI rendering and that the
# buffer allocation path triggered by -headless-render works.
./beebjit -0 test/display/raster-c.ssd \
-mode jit \
-autoboot \
-fast -accurate -debug \
-headless -headless-render \
-opt video:always-render \
-commands "breakat 11000000;c;eval '(frame_buffer_crc32==0x2c23c1b6)||bail';q"

echo 'Checking savescreen dumps render buffer to file.'
# This runs the same scenario and uses savescreen to dump the BGRA buffer.
# The file size must equal width * height * 4 = 768 * 640 * 4 = 1966080
# bytes for the current render dimensions.
TMP_BGRA=$(mktemp)
./beebjit -0 test/display/raster-c.ssd \
-mode jit \
-autoboot \
-fast -accurate -debug \
-headless -headless-render \
-opt video:always-render \
-commands "breakat 11000000;c;savescreen $TMP_BGRA;q" > /dev/null
SAVESCREEN_SIZE=$(wc -c < "$TMP_BGRA")
rm -f "$TMP_BGRA"
if [ "$SAVESCREEN_SIZE" -ne 1966080 ]; then
echo "savescreen file size $SAVESCREEN_SIZE != expected 1966080"
exit 1
fi

# This checks the framebuffer looks as expected, in an RVI test case that uses
# teletext output to implement pre-line blanking.
./beebjit -0 test/display/rvi-working.ssd \
Expand Down