Further GTK tinkering (EMU needs extra commands)

This commit is contained in:
Luxdragon 2024-01-19 22:45:49 +01:00
parent 37ce16ca8a
commit 75b647f9ac

View file

@ -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<<p)))
// *p1 = 1;
// else
// *p1 = 0;
// p1-=224; //next line
// }
// }
// }
// 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 = 1;
// uint8_t *video = malloc(sizeof(uint8_t) * 224 * 256);
// // Clear the drawing area
// cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
// cairo_paint(cr);
// // Copying the bitmap to video output
// for (int i = 0; i < 224; i++) {
// for (int j = 0; j < 32; j++) {
// uint8_t byte = bitmap[i*32 + j];
// for (int p = 0; p < 8; p++) {
// int pixel = (byte >> (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