diff --git a/emulator_shell.c b/emulator_shell.c index fef0e10..4214d02 100644 --- a/emulator_shell.c +++ b/emulator_shell.c @@ -87,6 +87,7 @@ static gboolean on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer u //GLOBAL VARIABLES uint8_t in_port; char which_interrupt; +uint8_t upscaleFactor = 2; //GLOBAL GRAPHICS uint8_t *bitmap = NULL; @@ -1452,92 +1453,37 @@ typedef struct cpu_data { } cpu_data; +void *cpu(void* arg) { + cpu_data *cpu = (cpu_data*) arg; + char done = cpu->done; + State8080* state = cpu->state; + int counter; + + while (!done) { + counter = emulate8080(cpu->state); + cpu->total_cycles_count += counter; + printf("Total cycles: %d\n", cpu->total_cycles_count); + + //usleep(counter / 2); // EMULATION OF THE PROCESSOR ŠPEED + if ((cpu->total_cycles_count > 16000) && (state->int_enable)) //1/60 second has elapsed + { + //redraw screen() will be handeled by the gtk_main() function + if (which_interrupt == 2) { + generateInterrupt(state, 2); //interrupt 2 + cpu->total_cycles_count = 0; + which_interrupt = 1; + } else { + generateInterrupt(state, 1); //interrupt 1 + cpu->total_cycles_count = 0; + which_interrupt = 2; + } + } + } +} + // ===== GTK GRAPHICS ===== -// static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { - // int upscaleFactor = 1; - // uint8_t *video = malloc(sizeof(uint8_t) * 224 * 256); - // //ROTATION ALGORITHM - // for (int i=0; i< 224; i++) - // { - // for (int j = 0; j < 256; j+= 8) - // { - // //Read the first 1-bit pixel - // // divide by 8 because there are 8 pixels - // // in a byte - // uint8_t pix = bitmap[(i*(256/8)) + j/8]; - - // //That makes 8 output vertical pixels - // // we need to do a vertical flip - // // so j needs to start at the last line - // // and advance backward through the buffer - // int offset = (255-j)*(224*4) + (i*4); - // uint8_t *p1 = (uint8_t*)(&video[offset]); - // for (int p=0; p<8; p++) - // { - // if ( 0!= (pix & (1<> (7 - p)) & 1; // flip the bit order -// int x = 255 - (j*8 + p); // flip the x-coordinate -// int y = i; -// video[y*256 + x] = pixel; -// } -// } -// } - -// // Rendering the graphics -// for (int x = 0; x < 256; x++) { -// for (int y = 0; y < 224; y++) { -// if (video[y*256 + x]) { -// cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); // Set color to white -// } else { -// cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); // Set color to black -// } - -// cairo_rectangle(cr, x * upscaleFactor, y * upscaleFactor, upscaleFactor, upscaleFactor); -// cairo_fill(cr); -// } -// } - -// free(video); -// } - static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { - int upscaleFactor = 2; uint8_t *video = malloc(sizeof(uint8_t) * 256 * 256); // Adjusted size // Clear the drawing area cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); @@ -1575,36 +1521,17 @@ static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { free(video); } - -void *cpu(void* arg) { - cpu_data *cpu = (cpu_data*) arg; - char done = cpu->done; - State8080* state = cpu->state; - int counter; - - while (!done) { - counter = emulate8080(cpu->state); - cpu->total_cycles_count += counter; - printf("Total cycles: %d\n", cpu->total_cycles_count); - - //usleep(counter / 2); // EMULATION OF THE PROCESSOR ŠPEED - if ((cpu->total_cycles_count > 16000) && (state->int_enable)) //1/60 second has elapsed - { - //redraw screen() will be handeled by the gtk_main() function - if (which_interrupt == 2) { - generateInterrupt(state, 2); //interrupt 2 - cpu->total_cycles_count = 0; - which_interrupt = 1; - } else { - generateInterrupt(state, 1); //interrupt 1 - cpu->total_cycles_count = 0; - which_interrupt = 2; - } - } - } +void on_about_clicked(GtkToolButton *toolbutton, gpointer user_data) { + GtkWidget *dialog = gtk_about_dialog_new(); + gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), "Turi's Super Duper Emulatinator"); + gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), "This is a super duper emulatinator created by Turi."); + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file("Luka.png", NULL); + gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), pixbuf); + g_object_unref(pixbuf); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); } - gboolean update_ui(gpointer data) { // Seems like GTK is not thread safe // we fix it with update_ui using gtk_main_iteration_do(FALSE) @@ -1615,6 +1542,19 @@ gboolean update_ui(gpointer data) { return TRUE; } +void on_size_changed(GtkComboBox *combo_box, gpointer user_data) { + gchar *text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo_box)); + if (g_strcmp0(text, "1x") == 0) { + upscaleFactor = 1; + } else if (g_strcmp0(text, "2x") == 0) { + upscaleFactor = 2; + } else if (g_strcmp0(text, "3x") == 0) { + upscaleFactor = 3; + } + g_free(text); +} + + int main (int argc, char *argv[]) { // Emulator init @@ -1638,17 +1578,47 @@ int main (int argc, char *argv[]) { gtk_init(&argc, &argv); GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); - gtk_window_set_title(GTK_WINDOW(window), "Turi's Super Duper Emulatinator"); + gtk_window_set_title(GTK_WINDOW(window), "Luxulator"); g_signal_connect(window, "key-press-event", G_CALLBACK(on_key_press), NULL); g_signal_connect(window, "key-release-event", G_CALLBACK(on_key_release), NULL); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + // Toolbar init + GtkWidget *toolbar = gtk_toolbar_new(); + GtkCssProvider *provider = gtk_css_provider_new(); + gtk_css_provider_load_from_data(provider, "* { -GtkWidget-toolbar-style: both-horiz; }", -1, NULL); + gtk_style_context_add_provider(gtk_widget_get_style_context(toolbar), GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER); + + // Size option in the toolbar + GtkToolItem *size = gtk_tool_item_new(); + GtkWidget *combo_box = gtk_combo_box_text_new(); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), "1x"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), "2x"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), "3x"); + gtk_container_add(GTK_CONTAINER(size), combo_box); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), size, -1); + g_signal_connect(combo_box, "changed", G_CALLBACK(on_size_changed), NULL); + + // About option in the toolbar + + GtkToolItem *about = gtk_tool_button_new(NULL, "About"); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), about, -1); + g_signal_connect(about, "clicked", G_CALLBACK(on_about_clicked), NULL); + // Drawing area init bitmap = &(state->memory[0x2400]); GtkWidget *drawing_area = gtk_drawing_area_new(); gtk_widget_set_app_paintable(drawing_area, TRUE); - gtk_container_add(GTK_CONTAINER(window), drawing_area); g_signal_connect(drawing_area, "draw", G_CALLBACK(draw_callback), NULL); + + // VBox to hold toolbar and drawing area + GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), drawing_area, TRUE, TRUE, 0); + gtk_container_add(GTK_CONTAINER(window), vbox); + + + gtk_widget_show_all(window); // CPU-init