changeset 2700:1cfd000dc750 default tip

WIP display screen border in plane debugger
author Michael Pavone <pavone@retrodev.com>
date Sun, 29 Jun 2025 23:38:56 -0700
parents 89c06782589f
children
files nuklear_ui/debug_ui.c vdp.c vdp.h
diffstat 3 files changed, 147 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/nuklear_ui/debug_ui.c	Fri Jun 27 23:39:37 2025 -0700
+++ b/nuklear_ui/debug_ui.c	Sun Jun 29 23:38:56 2025 -0700
@@ -62,9 +62,9 @@
 	struct nk_context *context = windows[DEBUG_PLANE].context;
 	nk_input_end(context);
 	struct nk_image main_image = nk_image_id((int)render_get_window_texture(windows[DEBUG_PLANE].win_idx));
-	if (nk_begin(context, "Plane Debug", nk_rect(0, 0, windows[DEBUG_PLANE].tex_width + 100 + 8, windows[DEBUG_PLANE].tex_height + 8), NK_WINDOW_NO_SCROLLBAR)) {
+	if (nk_begin(context, "Plane Debug", nk_rect(0, 0, windows[DEBUG_PLANE].tex_width + 150 + 8, windows[DEBUG_PLANE].tex_height + 8), NK_WINDOW_NO_SCROLLBAR)) {
 		nk_layout_space_begin(context, NK_STATIC, windows[DEBUG_PLANE].tex_height, INT_MAX);
-		nk_layout_space_push(context, nk_rect(100, 0, windows[DEBUG_PLANE].tex_width, windows[DEBUG_PLANE].tex_height));
+		nk_layout_space_push(context, nk_rect(150, 0, windows[DEBUG_PLANE].tex_width, windows[DEBUG_PLANE].tex_height));
 		nk_image(context, main_image);
 		struct nk_rect bounds = nk_layout_widget_bounds(context);
 		bounds.x += 100;
@@ -74,7 +74,7 @@
 			//TODO: display plane position
 			int x = context->input.mouse.pos.x - bounds.x;
 			int y = context->input.mouse.pos.y - bounds.y;
-			switch (vdp->debug_modes[DEBUG_PLANE])
+			switch (vdp->debug_modes[DEBUG_PLANE] & 3)
 			{
 			case 0:
 			case 1:
@@ -110,10 +110,10 @@
 				y -= 128;
 				break;
 			}
-			nk_layout_space_push(context, nk_rect(0, windows[DEBUG_PLANE].tex_height - 52, 100, 32));
+			nk_layout_space_push(context, nk_rect(0, windows[DEBUG_PLANE].tex_height - 52, 150, 32));
 			snprintf(buf, sizeof(buf), "X: %d", x);
 			nk_label(context, buf, NK_TEXT_LEFT);
-			nk_layout_space_push(context, nk_rect(0, windows[DEBUG_PLANE].tex_height - 32, 100, 32));
+			nk_layout_space_push(context, nk_rect(0, windows[DEBUG_PLANE].tex_height - 32, 150, 32));
 			snprintf(buf, sizeof(buf), "Y: %d", y);
 			nk_label(context, buf, NK_TEXT_LEFT);
 		}
@@ -125,13 +125,21 @@
 		};
 		for (int i = 0; i < 4; i++)
 		{
-			nk_layout_space_push(context, nk_rect(0, i * 32, 100, 32));
-			int selected = i == vdp->debug_modes[DEBUG_PLANE];
+			nk_layout_space_push(context, nk_rect(0, i * 32, 150, 32));
+			int selected = i == (vdp->debug_modes[DEBUG_PLANE] & 3);
 			nk_selectable_label(context, names[i], NK_TEXT_ALIGN_LEFT, &selected);
 			if (selected) {
 				vdp->debug_modes[DEBUG_PLANE] = i;
 			}
 		}
+		if ((vdp->debug_modes[DEBUG_PLANE] & 3) < 3) {
+			nk_layout_space_push(context, nk_rect(0, 5 * 32, 150, 32));
+			if (nk_check_label(context, "Screen Border", vdp->debug_flags & DEBUG_FLAG_PLANE_BORDER)) {
+				vdp->debug_flags |= DEBUG_FLAG_PLANE_BORDER;
+			} else {
+				vdp->debug_flags &= ~DEBUG_FLAG_PLANE_BORDER;
+			}
+		}
 		nk_end(context);
 	}
 	nk_sdl_render(context, NK_ANTI_ALIASING_ON, 512 * 1024, 128 * 1024);
@@ -225,7 +233,7 @@
 	switch (debug_type)
 	{
 	case DEBUG_PLANE:
-		win_width += 100;
+		win_width += 150;
 		render = plane_debug_ui;
 		break;
 	case DEBUG_CRAM:
--- a/vdp.c	Fri Jun 27 23:39:37 2025 -0700
+++ b/vdp.c	Sun Jun 29 23:38:56 2025 -0700
@@ -2460,6 +2460,134 @@
 			}
 		}
 	}
+	if (context->debug_flags & DEBUG_FLAG_PLANE_BORDER) {
+		pixel_t border_line = render_map_color(255, 0, 255);
+		if ((context->debug_modes[DEBUG_PLANE] & 3) < 2) {
+			uint16_t hscroll_base = (context->regs[REG_HSCROLL] & 0x3F) << 10;
+			hscroll_base += (context->debug_modes[DEBUG_PLANE] & 1) * 2;
+			uint16_t hscroll_mask = 0;
+			if (context->regs[REG_MODE_3] & 0x2) {
+				hscroll_mask |= 0xF8;
+			}
+			if (context->regs[REG_MODE_3] & 0x1) {
+				hscroll_mask |= 0x7;
+			}
+			uint16_t hscroll = 1023 - (context->vdpmem[hscroll_base] << 8 | context->vdpmem[hscroll_base+1]) & 1023;
+			uint16_t width = (context->regs[REG_MODE_4] & BIT_H40) ? 320 : 256;
+			if (context->regs[REG_MODE_3] & BIT_VSCROLL) {
+				//2-column vscroll
+				uint16_t num_cols = width >> 4;
+				for (int y_off = -2; y_off; y_off++)
+				{
+					for (uint16_t col = 0; col < num_cols; col++)
+					{
+						uint16_t vscroll = context->vsram[col * 2 + (context->debug_modes[DEBUG_PLANE] & 1)] & 1023;
+						int y = (vscroll + y_off) & 1023;
+						pixel_t *line = fb + y * pitch / sizeof(pixel_t);
+						for (int x = col ? hscroll + col * 16 : hscroll - 2, x_end = col == num_cols-1 ? hscroll + width + 2 : x + (col ? 16 : 18); x < x_end; x++)
+						{
+							line[x & 1023] = border_line;
+						}
+					}
+				}
+				for (int y = context->vsram[context->debug_modes[DEBUG_PLANE] & 1], y_end = y + context->inactive_start; y < y_end; y++)
+				{
+					pixel_t *line = fb + (y & 1023) * pitch / sizeof(pixel_t);
+					line[(hscroll - 2) & 1023] = border_line;
+					line[(hscroll - 1) & 1023] = border_line;
+					uint16_t hscroll_addr = hscroll_base + ((y - (y_end - context->inactive_start)) & hscroll_mask) * 4;
+					hscroll = 1024 - (context->vdpmem[hscroll_addr] << 8 | context->vdpmem[hscroll_addr+1]) & 1023;
+				}
+				for (int y = context->vsram[19 * 2 + (context->debug_modes[DEBUG_PLANE] & 1)], y_end = y + context->inactive_start; y < y_end; y++)
+				{
+					pixel_t *line = fb + (y & 1023) * pitch / sizeof(pixel_t);
+					line[(hscroll + width) & 1023] = border_line;
+					line[(hscroll + width + 1) & 1023] = border_line;
+					uint16_t hscroll_addr = hscroll_base + ((y - (y_end - context->inactive_start)) & hscroll_mask) * 4;
+					hscroll = 1024 - (context->vdpmem[hscroll_addr] << 8 | context->vdpmem[hscroll_addr+1]) & 1023;
+				}
+				for (int y_off = context->inactive_start; y_off < context->inactive_start + 2; y_off++)
+				{
+					for (uint16_t col = 0; col < num_cols; col++)
+					{
+						uint16_t vscroll = context->vsram[col * 2 + (context->debug_modes[DEBUG_PLANE] & 1)] & 1023;
+						int y = (vscroll + y_off) & 1023;
+						pixel_t *line = fb + y * pitch / sizeof(pixel_t);
+						for (int x = col ? hscroll + col * 16 : hscroll - 2, x_end = col == num_cols-1 ? hscroll + width + 2 : x + (col ? 16 : 18); x < x_end; x++)
+						{
+							line[x & 1023] = border_line;
+						}
+					}
+				}
+			} else {
+				//full screen vscroll
+				uint16_t vscroll = context->vsram[context->debug_modes[DEBUG_PLANE] & 1] & 1023;
+				int y = (vscroll - 2) & 1023;
+				pixel_t *line = fb + y * pitch / sizeof(pixel_t);
+				for (int x = hscroll - 2, x_end = hscroll + width + 2; x < x_end; x++)
+				{
+					line[x & 1023] = border_line;
+				}
+				y = (y + 1) & 1023;
+				line = fb + y * pitch / sizeof(pixel_t);
+				for (int x = hscroll - 1, x_end = hscroll + width + 1; x < x_end; x++)
+				{
+					line[x & 1023] = border_line;
+				}
+				int y_end = y + context->inactive_start + 1;
+				for (y++; y < y_end; y++)
+				{
+					line = fb + (y & 1023) * pitch / sizeof(pixel_t);
+					line[(hscroll - 2) & 1023] = border_line;
+					line[(hscroll - 1) & 1023] = border_line;
+					line[(hscroll + width) & 1023] = border_line;
+					line[(hscroll + width + 1) & 1023] = border_line;
+					uint16_t hscroll_last = hscroll;
+					uint16_t hscroll_addr = hscroll_base + ((y - vscroll) & hscroll_mask) * 4;
+					hscroll = 1024 - (context->vdpmem[hscroll_addr] << 8 | context->vdpmem[hscroll_addr+1]) & 1023;
+					if (abs(hscroll - hscroll_last) > 512) {
+						//handle wraparound
+						if (hscroll > hscroll_last) {
+							hscroll_last += 1024;
+						} else {
+							hscroll += 1024;
+						}
+					}
+					if (hscroll_last < hscroll) {
+						for (int x = hscroll_last + width + 2, x_end = hscroll + width; x < x_end; x++)
+						{
+							line[x & 1023] = border_line;
+						}
+						line = fb + ((y+1) & 1023) * pitch / sizeof(pixel_t);
+						for (int x = hscroll_last, x_end = hscroll; x < x_end; x++)
+						{
+							line[x & 1023] = border_line;
+						}
+					} else if (hscroll_last > hscroll) {
+						for (int x = hscroll, x_end = hscroll_last; x < x_end; x++)
+						{
+							line[x & 1023] = border_line;
+						}
+						line = fb + ((y+1) & 1023) * pitch / sizeof(pixel_t);
+						for (int x = hscroll + width + 2, x_end = hscroll_last + width; x < x_end; x++)
+						{
+							line[x & 1023] = border_line;
+						}
+					}
+				}
+				line = fb + (y_end & 1023) * pitch / sizeof(pixel_t);
+				for (int x = hscroll - 2, x_end = hscroll + width + 2; x < x_end; x++)
+				{
+					line[x & 1023] = border_line;
+				}
+				line = fb + ((y_end + 1) & 1023) * pitch / sizeof(pixel_t);
+				for (int x = hscroll - 2, x_end = hscroll + width + 2; x < x_end; x++)
+				{
+					line[x & 1023] = border_line;
+				}
+			}
+		}
+	}
 }
 
 static void sprite_debug_mode5(pixel_t *fb, uint32_t pitch, vdp_context *context)
--- a/vdp.h	Fri Jun 27 23:39:37 2025 -0700
+++ b/vdp.h	Sun Jun 29 23:38:56 2025 -0700
@@ -71,6 +71,8 @@
 #define FLAG2_BYTE_PENDING   0x40
 #define FLAG2_PAUSE          0x80
 
+#define DEBUG_FLAG_PLANE_BORDER 0x01
+
 #define DISPLAY_ENABLE 0x40
 
 enum {
@@ -266,6 +268,7 @@
 	uint8_t        enabled_debuggers;
 	uint8_t        debug_fb_indices[NUM_DEBUG_TYPES];
 	uint8_t        debug_modes[NUM_DEBUG_TYPES];
+	uint8_t        debug_flags;
 	uint8_t        pushed_frame;
 	uint8_t        type;
 	uint8_t        cram_latch;