Mercurial > repos > blastem
diff nuklear_ui/debug_ui.c @ 2693:46dba737b931
WIP Nuklear UI in VDP debug windows
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 19 Jun 2025 19:59:05 -0700 |
parents | |
children | 25fc676e3521 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nuklear_ui/debug_ui.c Thu Jun 19 19:59:05 2025 -0700 @@ -0,0 +1,162 @@ +#include <limits.h> +#include <string.h> +#include <stdlib.h> + +#include "blastem_nuklear.h" +#include "../blastem.h" +#include "../genesis.h" +#include "../sms.h" +#include "../coleco.h" + +typedef struct { + struct nk_context *context; + uint32_t tex_width; + uint32_t tex_height; + uint8_t win_idx; +} debug_window; + +static debug_window windows[NUM_DEBUG_TYPES]; + +static void debug_handle_event(uint8_t which, SDL_Event *event) +{ + for (int i = 0; i < NUM_DEBUG_TYPES; i++) + { + if (windows[i].win_idx == which) { + nk_sdl_handle_event(windows[i].context, event); + break; + } + } +} + +#ifndef DISABLE_OPENGL +vdp_context *get_vdp(void) +{ + if (!current_system) { + return NULL; + } + switch (current_system->type) + { + case SYSTEM_GENESIS: + case SYSTEM_SEGACD: + case SYSTEM_PICO: + case SYSTEM_COPERA: + return ((genesis_context *)current_system)->vdp; + case SYSTEM_SMS: + case SYSTEM_GAME_GEAR: + case SYSTEM_SG1000: + case SYSTEM_SC3000: + return ((sms_context *)current_system)->vdp; + case SYSTEM_COLECOVISION: + return ((coleco_context *)current_system)->vdp; + default: + return NULL; + } +} + +void write_cram_internal(vdp_context * context, uint16_t addr, uint16_t value); +static void cram_debug_ui(void) +{ + vdp_context *vdp = get_vdp(); + if (!vdp) { + return; + } + struct nk_context *context = windows[DEBUG_CRAM].context; + nk_input_end(context); + char buf[64]; + + struct nk_image main_image = nk_image_id((int)render_get_window_texture(windows[DEBUG_CRAM].win_idx)); + if (nk_begin(context, "CRAM Debug", nk_rect(0, 0, windows[DEBUG_CRAM].tex_width + 100 + 8, windows[DEBUG_CRAM].tex_height + 8), NK_WINDOW_NO_SCROLLBAR)) { + nk_layout_space_begin(context, NK_STATIC, windows[DEBUG_CRAM].tex_height, INT_MAX); + nk_layout_space_push(context, nk_rect(100, 0, windows[DEBUG_CRAM].tex_width, windows[DEBUG_CRAM].tex_height)); + nk_image(context, main_image); + struct nk_rect bounds = nk_layout_widget_bounds(context); + bounds.x += 100; + bounds.w -= 100; + bounds.h = (vdp->flags2 & FLAG2_REGION_PAL) ? 313 : 262; + if (nk_input_is_mouse_hovering_rect(&context->input, bounds)) { + int off_y = context->input.mouse.pos.y - bounds.y; + int off_x = context->input.mouse.pos.x - bounds.x; + pixel_t pix = vdp->debug_fbs[DEBUG_CRAM][off_y * vdp->debug_fb_pitch[DEBUG_CRAM] / sizeof(pixel_t) + off_x]; +#ifdef USE_GLES + pixel_t b = pix >> 20 & 0xE, g = pix >> 12 & 0xE, r = pix >> 4 & 0xE; +#else + pixel_t r = pix >> 20 & 0xE, g = pix >> 12 & 0xE, b = pix >> 4 & 0xE; +#endif + pix = b << 8 | g << 4 | r; + snprintf(buf, sizeof(buf), "Line: %d, Index: %d, Value: %03X", off_y- vdp->border_top, off_x >> 3, pix & 0xFFFFFF); + nk_layout_space_push(context, nk_rect(100, 512 - 32*5, windows[DEBUG_CRAM].tex_width, 32)); + nk_label(context, buf, NK_TEXT_LEFT); + } + bounds.y += 512-32*4; + bounds.h = 32*4; + if (nk_input_is_mouse_hovering_rect(&context->input, bounds)) { + int index = ((((int)(context->input.mouse.pos.y - bounds.y)) >> 1) & 0xF0) + (((int)(context->input.mouse.pos.x - bounds.x)) >> 5); + snprintf(buf, sizeof(buf), "Index: %2d, Value: %03X", index, vdp->cram[index]); + nk_layout_space_push(context, nk_rect(100, 512 - 32*5, windows[DEBUG_CRAM].tex_width, 32)); + nk_label(context, buf, NK_TEXT_LEFT); + } + + static struct nk_scroll scroll; + context->style.window.scrollbar_size.y = 0; + nk_layout_space_push(context, nk_rect(0, 0, 100, windows[DEBUG_CRAM].tex_height)); + if (nk_group_scrolled_begin(context, &scroll, "Entries", 0)) { + nk_layout_space_begin(context, NK_STATIC, windows[DEBUG_CRAM].tex_height * 4, INT_MAX); + for (int i = 0; i < 64; i++) + { + nk_layout_space_push(context, nk_rect(0, i *32, 25, 32)); + snprintf(buf, sizeof(buf), "%d", i); + nk_label(context, buf, NK_TEXT_RIGHT); + nk_layout_space_push(context, nk_rect(30, i *32, 50, 32)); + snprintf(buf, sizeof(buf), "%03X", vdp->cram[i] & 0xEEE); + nk_edit_string_zero_terminated(context, NK_EDIT_FIELD, buf, sizeof(buf), nk_filter_hex); + char *end; + long newv = strtol(buf, &end, 16); + if (end != buf && newv != vdp->cram[i]) { + write_cram_internal(vdp, i, newv & 0xEEE); + } + } + nk_layout_space_end(context); + nk_group_scrolled_end(context); + } + + nk_end(context); + } + nk_sdl_render(context, NK_ANTI_ALIASING_ON, 512 * 1024, 128 * 1024); + + nk_input_begin(context); +} +#endif + +uint8_t debug_create_window(uint8_t debug_type, char *caption, uint32_t width, uint32_t height, window_close_handler close_handler) +{ +#ifndef DISABLE_OPENGL + if (!render_has_gl()) { +#endif + return render_create_window(caption, width, height, close_handler); +#ifndef DISABLE_OPENGL + } + uint32_t win_width = width, win_height = height; + ui_render_fun render = NULL; + switch (debug_type) + { + case DEBUG_CRAM: + win_width += 100; + render = cram_debug_ui; + break; + } + if (render) { + //compensate for padding + win_width += 4 * 2; + win_height += 4 * 2; + windows[debug_type].win_idx = render_create_window_tex(caption, win_width, win_height, width, height, close_handler); + windows[debug_type].tex_width = width; + windows[debug_type].tex_height = width; + windows[debug_type].context = shared_nuklear_init(windows[debug_type].win_idx); + render_set_ui_render_fun(windows[debug_type].win_idx, render); + render_set_event_handler(windows[debug_type].win_idx, debug_handle_event); + return windows[debug_type].win_idx; + } else { + return render_create_window(caption, width, height, close_handler); + } +#endif +}