blob: 7a9841fe7279bb940a3c4d2fdea3221a1f6d5935 [file] [log] [blame]
swissChilidbbd5402020-08-07 15:07:39 -07001#include "gui.h"
2
3#include <GL/glew.h>
4#include <SDL2/SDL.h>
5#include <SDL2/SDL_opengl.h>
6
7#define NK_INCLUDE_FIXED_TYPES
8#define NK_INCLUDE_STANDARD_IO
9#define NK_INCLUDE_STANDARD_VARARGS
10#define NK_INCLUDE_DEFAULT_ALLOCATOR
11#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
12#define NK_INCLUDE_FONT_BAKING
13#define NK_INCLUDE_DEFAULT_FONT
14#define NK_IMPLEMENTATION
15#define NK_SDL_GL3_IMPLEMENTATION
16#include "nuklear/nuklear.h"
17#include "nuklear/demo/sdl_opengl3/nuklear_sdl_gl3.h"
swissChili94ba1f52020-08-08 11:39:10 -070018#undef SCREEN_ONLY_SDL
swissChilibb478f12020-08-07 20:45:07 -070019#include "screen.h"
swissChilidbbd5402020-08-07 15:07:39 -070020
21#define WINDOW_WIDTH 720
22#define WINDOW_HEIGHT 640
23#define MAX_VERTEX_MEMORY 512 * 1024
24#define MAX_ELEMENT_MEMORY 128 * 1024
25
swissChilic6b4f7e2020-08-09 16:36:36 -070026typedef struct
swissChilidbbd5402020-08-07 15:07:39 -070027{
swissChilic6b4f7e2020-08-09 16:36:36 -070028 cpu_t *cpu;
29 mqd_t mq;
30} gui_arg_t;
31
32void gui(gui_arg_t *arg)
33{
34 cpu_t *cpu = arg->cpu;
35 mqd_t mq = arg->mq;
36
37 free(arg);
38
swissChilidbbd5402020-08-07 15:07:39 -070039 SDL_Window *win;
40 SDL_GLContext glContext;
41 int win_width, win_height;
42 bool running = true;
43 bool cpu_running = false;
44
45 struct nk_context *ctx;
swissChilic51e9222020-08-07 16:09:14 -070046 struct nk_colorf bg =
47 {
48 .r = 0.29f,
49 .g = 0.28f,
50 .b = 0.50f,
51 .a = 1.0f,
52 };
swissChilie7ee6da2020-08-08 16:14:21 -070053 struct nk_color
54 selected = nk_rgb(28, 234, 79),
55 red = nk_rgb(226, 56, 76);
swissChilic51e9222020-08-07 16:09:14 -070056
swissChilibb478f12020-08-07 20:45:07 -070057 uint16_t disas_start = 0x600,
58 disas_end = 0x600 + 32;
59
60 uint8_t screen_scale = 4;
swissChilidbbd5402020-08-07 15:07:39 -070061
62 SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
63 SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS);
64 SDL_GL_SetAttribute (SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
65 SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
66 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
67 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
68 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
69 win = SDL_CreateWindow("6502",
70 SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
71 WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_ALLOW_HIGHDPI);
72 glContext = SDL_GL_CreateContext(win);
73 SDL_GetWindowSize(win, &win_width, &win_height);
74
75 /* OpenGL setup */
76 glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
77 glewExperimental = 1;
78 if (glewInit() != GLEW_OK) {
79 fprintf(stderr, "Failed to setup GLEW\n");
80 exit(1);
81 }
82
83 ctx = nk_sdl_init(win);
84
85 struct nk_font_atlas *atlas;
86 nk_sdl_font_stash_begin(&atlas);
87 struct nk_font *font = nk_font_atlas_add_default(atlas, 16, NULL);
88 nk_sdl_font_stash_end();
89 //nk_style_load_all_cursors(ctx, atlas->cursors);
90 nk_style_set_font(ctx, &font->handle);
91
swissChilidbbd5402020-08-07 15:07:39 -070092 while (running)
93 {
94 SDL_Event evt;
95 nk_input_begin(ctx);
96 while (SDL_PollEvent(&evt))
97 {
98 if (evt.type == SDL_QUIT) goto cleanup;
99 nk_sdl_handle_event(&evt);
100 }
101 nk_input_end(ctx);
102
103 if (cpu_running && cpu->running)
104 step(cpu);
105
106 if (!cpu->running)
107 cpu_running = false;
108
swissChilibb478f12020-08-07 20:45:07 -0700109 if (nk_begin(ctx, "Registers", nk_rect(50, 300, 500, 90),
swissChilidbbd5402020-08-07 15:07:39 -0700110 NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
111 NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
112 {
113 nk_layout_row_dynamic(ctx, 30, 4);
swissChilidbbd5402020-08-07 15:07:39 -0700114 cpu->pc = nk_propertyi(ctx, "PC", 0, cpu->pc, 0xFFFF, 1, 20.0f);
115 cpu->regs[A] = nk_propertyi(ctx, "A", 0, cpu->regs[A], 0xFF, 1, 20.0f);
116 cpu->regs[X] = nk_propertyi(ctx, "X", 0, cpu->regs[X], 0xFF, 1, 20.0f);
117 cpu->regs[Y] = nk_propertyi(ctx, "Y", 0, cpu->regs[Y], 0xFF, 1, 20.0f);
118 }
119 nk_end(ctx);
120
swissChilibb478f12020-08-07 20:45:07 -0700121 if (nk_begin(ctx, "Screen", nk_rect(50, 400, 150, 220),
122 NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
123 NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
124 {
125 nk_layout_row_dynamic(ctx, 24, 1);
126 screen_scale = nk_propertyi(ctx, "Scale", 1, screen_scale, 8, 1, 1);
swissChili94ba1f52020-08-08 11:39:10 -0700127
swissChilibb478f12020-08-07 20:45:07 -0700128 nk_layout_row_static(ctx, screen_scale * 32, screen_scale * 32, 1);
129 screen(ctx, cpu->mem + CPU_FB_ADDR, screen_scale);
130 }
131 nk_end(ctx);
132
133 if (nk_begin(ctx, "Disassembler", nk_rect(330, 50, 300, 200),
swissChilic51e9222020-08-07 16:09:14 -0700134 NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
135 NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
136 {
137 nk_layout_row_dynamic(ctx, 30, 2);
138 disas_start = nk_propertyi(ctx, "Start", 0, disas_start, 0xFFFF, 1, 20.0f);
139 disas_end = nk_propertyi(ctx, "End", 0, disas_end, 0xFFFF, 1, 20.0f);
140
141 uint16_t pc = cpu->pc;
142
143 for (cpu->pc = disas_start; cpu->pc < disas_end;)
144 {
145 nk_layout_row_begin(ctx, NK_STATIC, 24, 2);
146
147 uint16_t this_pc = cpu->pc;
148
149 char addr[6];
150 sprintf(addr, "$%x", this_pc);
151
152 nk_layout_row_push(ctx, 48);
153 nk_label(ctx, addr, NK_TEXT_LEFT);
154
155 nk_layout_row_push(ctx, 120);
156 char *line = disas_step(cpu);
157 if (pc == this_pc)
158 {
159 nk_label_colored(ctx, line, NK_TEXT_LEFT, selected);
160 }
161 else
162 {
163 nk_label(ctx, line, NK_TEXT_LEFT);
164 }
165 free(line);
166 }
167
168 cpu->pc = pc;
169 }
170 nk_end(ctx);
171
swissChilie7ee6da2020-08-08 16:14:21 -0700172 if (nk_begin(ctx, "Stack", nk_rect(250, 250, 230, 350),
173 NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
174 NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
175 {
176 nk_layout_row_static(ctx, 24, 48, 2);
swissChilib04a4022020-08-09 12:51:00 -0700177 for (int i = 0xFF; i >= 0; i--)
swissChilie7ee6da2020-08-08 16:14:21 -0700178 {
179 char line[6];
180 sprintf(line, "$%x", 0x100 + i);
181 nk_label(ctx, line, NK_TEXT_LEFT);
182
183 sprintf(line, "$%x", cpu->mem[0x100 + i]);
184 if (i == cpu->regs[SP])
185 {
186 nk_label_colored(ctx, line, NK_TEXT_LEFT, selected);
187 }
188 else
189 {
190 nk_label(ctx, line, NK_TEXT_LEFT);
191 }
192 }
193 }
194 nk_end(ctx);
195
swissChilidbbd5402020-08-07 15:07:39 -0700196 if (nk_begin(ctx, "Debugger", nk_rect(50, 50, 230, 150),
197 NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
198 NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
199 {
200 nk_layout_row_dynamic(ctx, 30, 2);
201 nk_label(ctx, cpu->running ? "CPU Running" : "CPU Halted", NK_TEXT_LEFT);
202 if (nk_button_label(ctx, "Reset"))
203 {
204 puts("cpu reset");
205 reset(cpu);
206 }
207
208 nk_layout_row_dynamic(ctx, 30, 2);
209 if (nk_button_label(ctx, "Step"))
210 {
211 printf("step pressed!\n");
212 step(cpu);
213 }
214
215 if (nk_button_label(ctx, cpu_running ? "Stop" : "Run"))
216 {
217 cpu_running = !cpu_running;
218 puts(cpu_running ? "cpu running" : "cpu stopped");
219 }
220 }
221 nk_end(ctx);
222
223 SDL_GetWindowSize(win, &win_width, &win_height);
224 glViewport(0, 0, win_width, win_height);
225 glClear(GL_COLOR_BUFFER_BIT);
226 glClearColor(bg.r, bg.g, bg.b, bg.a);
227 nk_sdl_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_MEMORY, MAX_ELEMENT_MEMORY);
228 SDL_GL_SwapWindow(win);
229 }
230
231cleanup:
232 nk_sdl_shutdown();
233 SDL_GL_DeleteContext(glContext);
234 SDL_DestroyWindow(win);
235 SDL_Quit();
236}
swissChilic6b4f7e2020-08-09 16:36:36 -0700237
238
239void start_gui(mqd_t mq, cpu_t *cpu)
240{
241 pthread_t gui_thread;
242 gui_arg_t *arg = malloc(sizeof(gui_arg_t));
243 arg->cpu = cpu;
244 arg->mq = mq;
245 pthread_create(&gui_thread, NULL, (void *(*)(void *))&gui, arg);
246}