Mercurial > repos > blastem
comparison 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 |
comparison
equal
deleted
inserted
replaced
2692:effbb52ab3f0 | 2693:46dba737b931 |
---|---|
1 #include <limits.h> | |
2 #include <string.h> | |
3 #include <stdlib.h> | |
4 | |
5 #include "blastem_nuklear.h" | |
6 #include "../blastem.h" | |
7 #include "../genesis.h" | |
8 #include "../sms.h" | |
9 #include "../coleco.h" | |
10 | |
11 typedef struct { | |
12 struct nk_context *context; | |
13 uint32_t tex_width; | |
14 uint32_t tex_height; | |
15 uint8_t win_idx; | |
16 } debug_window; | |
17 | |
18 static debug_window windows[NUM_DEBUG_TYPES]; | |
19 | |
20 static void debug_handle_event(uint8_t which, SDL_Event *event) | |
21 { | |
22 for (int i = 0; i < NUM_DEBUG_TYPES; i++) | |
23 { | |
24 if (windows[i].win_idx == which) { | |
25 nk_sdl_handle_event(windows[i].context, event); | |
26 break; | |
27 } | |
28 } | |
29 } | |
30 | |
31 #ifndef DISABLE_OPENGL | |
32 vdp_context *get_vdp(void) | |
33 { | |
34 if (!current_system) { | |
35 return NULL; | |
36 } | |
37 switch (current_system->type) | |
38 { | |
39 case SYSTEM_GENESIS: | |
40 case SYSTEM_SEGACD: | |
41 case SYSTEM_PICO: | |
42 case SYSTEM_COPERA: | |
43 return ((genesis_context *)current_system)->vdp; | |
44 case SYSTEM_SMS: | |
45 case SYSTEM_GAME_GEAR: | |
46 case SYSTEM_SG1000: | |
47 case SYSTEM_SC3000: | |
48 return ((sms_context *)current_system)->vdp; | |
49 case SYSTEM_COLECOVISION: | |
50 return ((coleco_context *)current_system)->vdp; | |
51 default: | |
52 return NULL; | |
53 } | |
54 } | |
55 | |
56 void write_cram_internal(vdp_context * context, uint16_t addr, uint16_t value); | |
57 static void cram_debug_ui(void) | |
58 { | |
59 vdp_context *vdp = get_vdp(); | |
60 if (!vdp) { | |
61 return; | |
62 } | |
63 struct nk_context *context = windows[DEBUG_CRAM].context; | |
64 nk_input_end(context); | |
65 char buf[64]; | |
66 | |
67 struct nk_image main_image = nk_image_id((int)render_get_window_texture(windows[DEBUG_CRAM].win_idx)); | |
68 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)) { | |
69 nk_layout_space_begin(context, NK_STATIC, windows[DEBUG_CRAM].tex_height, INT_MAX); | |
70 nk_layout_space_push(context, nk_rect(100, 0, windows[DEBUG_CRAM].tex_width, windows[DEBUG_CRAM].tex_height)); | |
71 nk_image(context, main_image); | |
72 struct nk_rect bounds = nk_layout_widget_bounds(context); | |
73 bounds.x += 100; | |
74 bounds.w -= 100; | |
75 bounds.h = (vdp->flags2 & FLAG2_REGION_PAL) ? 313 : 262; | |
76 if (nk_input_is_mouse_hovering_rect(&context->input, bounds)) { | |
77 int off_y = context->input.mouse.pos.y - bounds.y; | |
78 int off_x = context->input.mouse.pos.x - bounds.x; | |
79 pixel_t pix = vdp->debug_fbs[DEBUG_CRAM][off_y * vdp->debug_fb_pitch[DEBUG_CRAM] / sizeof(pixel_t) + off_x]; | |
80 #ifdef USE_GLES | |
81 pixel_t b = pix >> 20 & 0xE, g = pix >> 12 & 0xE, r = pix >> 4 & 0xE; | |
82 #else | |
83 pixel_t r = pix >> 20 & 0xE, g = pix >> 12 & 0xE, b = pix >> 4 & 0xE; | |
84 #endif | |
85 pix = b << 8 | g << 4 | r; | |
86 snprintf(buf, sizeof(buf), "Line: %d, Index: %d, Value: %03X", off_y- vdp->border_top, off_x >> 3, pix & 0xFFFFFF); | |
87 nk_layout_space_push(context, nk_rect(100, 512 - 32*5, windows[DEBUG_CRAM].tex_width, 32)); | |
88 nk_label(context, buf, NK_TEXT_LEFT); | |
89 } | |
90 bounds.y += 512-32*4; | |
91 bounds.h = 32*4; | |
92 if (nk_input_is_mouse_hovering_rect(&context->input, bounds)) { | |
93 int index = ((((int)(context->input.mouse.pos.y - bounds.y)) >> 1) & 0xF0) + (((int)(context->input.mouse.pos.x - bounds.x)) >> 5); | |
94 snprintf(buf, sizeof(buf), "Index: %2d, Value: %03X", index, vdp->cram[index]); | |
95 nk_layout_space_push(context, nk_rect(100, 512 - 32*5, windows[DEBUG_CRAM].tex_width, 32)); | |
96 nk_label(context, buf, NK_TEXT_LEFT); | |
97 } | |
98 | |
99 static struct nk_scroll scroll; | |
100 context->style.window.scrollbar_size.y = 0; | |
101 nk_layout_space_push(context, nk_rect(0, 0, 100, windows[DEBUG_CRAM].tex_height)); | |
102 if (nk_group_scrolled_begin(context, &scroll, "Entries", 0)) { | |
103 nk_layout_space_begin(context, NK_STATIC, windows[DEBUG_CRAM].tex_height * 4, INT_MAX); | |
104 for (int i = 0; i < 64; i++) | |
105 { | |
106 nk_layout_space_push(context, nk_rect(0, i *32, 25, 32)); | |
107 snprintf(buf, sizeof(buf), "%d", i); | |
108 nk_label(context, buf, NK_TEXT_RIGHT); | |
109 nk_layout_space_push(context, nk_rect(30, i *32, 50, 32)); | |
110 snprintf(buf, sizeof(buf), "%03X", vdp->cram[i] & 0xEEE); | |
111 nk_edit_string_zero_terminated(context, NK_EDIT_FIELD, buf, sizeof(buf), nk_filter_hex); | |
112 char *end; | |
113 long newv = strtol(buf, &end, 16); | |
114 if (end != buf && newv != vdp->cram[i]) { | |
115 write_cram_internal(vdp, i, newv & 0xEEE); | |
116 } | |
117 } | |
118 nk_layout_space_end(context); | |
119 nk_group_scrolled_end(context); | |
120 } | |
121 | |
122 nk_end(context); | |
123 } | |
124 nk_sdl_render(context, NK_ANTI_ALIASING_ON, 512 * 1024, 128 * 1024); | |
125 | |
126 nk_input_begin(context); | |
127 } | |
128 #endif | |
129 | |
130 uint8_t debug_create_window(uint8_t debug_type, char *caption, uint32_t width, uint32_t height, window_close_handler close_handler) | |
131 { | |
132 #ifndef DISABLE_OPENGL | |
133 if (!render_has_gl()) { | |
134 #endif | |
135 return render_create_window(caption, width, height, close_handler); | |
136 #ifndef DISABLE_OPENGL | |
137 } | |
138 uint32_t win_width = width, win_height = height; | |
139 ui_render_fun render = NULL; | |
140 switch (debug_type) | |
141 { | |
142 case DEBUG_CRAM: | |
143 win_width += 100; | |
144 render = cram_debug_ui; | |
145 break; | |
146 } | |
147 if (render) { | |
148 //compensate for padding | |
149 win_width += 4 * 2; | |
150 win_height += 4 * 2; | |
151 windows[debug_type].win_idx = render_create_window_tex(caption, win_width, win_height, width, height, close_handler); | |
152 windows[debug_type].tex_width = width; | |
153 windows[debug_type].tex_height = width; | |
154 windows[debug_type].context = shared_nuklear_init(windows[debug_type].win_idx); | |
155 render_set_ui_render_fun(windows[debug_type].win_idx, render); | |
156 render_set_event_handler(windows[debug_type].win_idx, debug_handle_event); | |
157 return windows[debug_type].win_idx; | |
158 } else { | |
159 return render_create_window(caption, width, height, close_handler); | |
160 } | |
161 #endif | |
162 } |