diff --git a/emulator_shell.c b/emulator_shell.c index 6c578f1..e03d7ed 100644 --- a/emulator_shell.c +++ b/emulator_shell.c @@ -7,6 +7,9 @@ // gcc emulator_shell.c `pkg-config --cflags --libs gtk+-3.0` -o emulator #define FREQUENCY 500 +#define WIDTH 224 +#define HEIGHT 256 + void keyDown(uint8_t key); void keyUp(uint8_t key); @@ -81,13 +84,14 @@ static gboolean on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer u //===== EMULATOR SETUP ===== -uint8_t in_port; //GLOBAL VAR -char which_interrupt = 1; //GLOBAL VAR +//GLOBAL VARIABLES +uint8_t in_port; +char which_interrupt; //GLOBAL GRAPHICS uint8_t *bitmap = NULL; -int bitmap_width = 224; -int bitmap_height = 256; + + typedef struct ConditionCodes { //bitfields for condition codes @@ -992,65 +996,58 @@ void simulateNanoseconds(unsigned int numNanoseconds) nanosleep(&sleepTime, NULL); } +typedef struct cpu_data { + char done; + int total_cycles_count; + GtkWidget* drawing_area; + State8080 *state; + +} cpu_data; + // ===== GTK GRAPHICS ===== -// Callback function to handle the "draw" signal of the Drawing Area -gboolean draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) -{ - // Check if the bitmap image data is available - if (bitmap != NULL && bitmap_width > 0 && bitmap_height > 0) - { - // Get the width and height of the drawing area - int width, height; - gtk_widget_get_size_request(widget, &width, &height); - - // Calculate the width and height of each pixel - int pixel_width = width / bitmap_width; - int pixel_height = height / bitmap_height; - - // Iterate over each pixel in the bitmap image - for (int y = 0; y < bitmap_height; y++) - { - for (int x = 0; x < bitmap_width; x++) - { - // Determine the color of the pixel - unsigned char pixel = bitmap[y * bitmap_width + x]; - - // Set the color based on the pixel value - if (pixel == 0) - { - // Black pixel - cairo_set_source_rgb(cr, 0, 0, 0); - } - else - { - // White pixel - cairo_set_source_rgb(cr, 1, 1, 1); - } - - // Draw the pixel - cairo_rectangle(cr, x * pixel_width, y * pixel_height, pixel_width, pixel_height); +static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { + int x, y; + for (y = 0; y < HEIGHT; y++) { + for (x = 0; x < WIDTH; x++) { + if (bitmap[y * WIDTH + x]) { + cairo_rectangle(cr, x, y, 1, 1); cairo_fill(cr); } } } +} - return FALSE; +static gboolean cpu(gpointer user_data) { + cpu_data *cpu = user_data; + char done = cpu->done; + State8080* state = cpu->state; + int counter; + + while (!done) { + counter = emulate8080(cpu->state); + cpu->total_cycles_count += counter; + + simulateNanoseconds(FREQUENCY * counter); // EMULATION OF THE PROCESSOR ŠPEED + if ((cpu->total_cycles_count > 16000000) && (state->int_enable)) //1/60 second has elapsed + { + gtk_widget_queue_draw(user_data); + 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; + } + } + } } int main (int argc, char *argv[]) { - // GTK INIT - gtk_init(&argc, &argv); - GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - g_print("Test\n"); - gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); - gtk_window_set_title(GTK_WINDOW(window), "Lux8080-Emulator"); - 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); - // EMULATOR INIT State8080 *state = (State8080*) calloc(1, sizeof(State8080)); //memset obsolte with calloc @@ -1067,9 +1064,17 @@ int main (int argc, char *argv[]) { read_Space_Invaders_ROM(state, "ROM/invaders.f", 0x1000); read_Space_Invaders_ROM(state, "ROM/invaders.e", 0x1800); - - // DRAWING AREA INIT + // GTK INIT + gtk_init(&argc, &argv); + GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + g_print("Test\n"); + gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); + gtk_window_set_title(GTK_WINDOW(window), "Lux8080-Emulator"); + 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); + // DRAWING AREA INIT bitmap = &(state->memory[0x2400]); GtkWidget *drawing_area = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER(window), drawing_area); @@ -1078,36 +1083,20 @@ int main (int argc, char *argv[]) { + // CPU INIT + cpu_data *cpu_eco = malloc(sizeof(cpu_data)); + cpu_eco->state = state; + cpu_eco->drawing_area = drawing_area; + cpu_eco->done = 0; + cpu_eco->total_cycles_count = 0; + g_idle_add(cpu, cpu_eco); - int i = 0; - char done = 0; - int counter; - int total_count = 0; - while (!done) { - counter = emulate8080(state); - total_count += counter; - - i++; - simulateNanoseconds(FREQUENCY * counter); // EMULATION OF THE PROCESSOR ŠPEED - if ((total_count > 16000000) && (state->int_enable)) //1/60 second has elapsed - { - gtk_widget_queue_draw(drawing_area); - if (which_interrupt == 2) { - generateInterrupt(state, 2); //interrupt 2 - total_count = 0; - which_interrupt = 1; - } else { - generateInterrupt(state, 1); //interrupt 0 - total_count = 0; - which_interrupt = 2; - } - } - } + //MAIN LOOP & TERMINATION gtk_main(); free(state->memory); free(state); + free(cpu_eco); return 0; - } \ No newline at end of file