From 0b1a59a4d43d468881a46c25c4de842d96ed0e88 Mon Sep 17 00:00:00 2001 From: Luxdragon Date: Sat, 20 Jan 2024 12:31:11 +0100 Subject: [PATCH] Further commands --- emulator_shell.c | 372 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 351 insertions(+), 21 deletions(-) diff --git a/emulator_shell.c b/emulator_shell.c index 4214d02..481540b 100644 --- a/emulator_shell.c +++ b/emulator_shell.c @@ -7,9 +7,6 @@ // gcc emulator_shell.c `pkg-config --cflags --libs gtk+-3.0` -lpthread -o emulator -#define WIDTH 224 -#define HEIGHT 256 - void keyDown(uint8_t key); void keyUp(uint8_t key); @@ -88,6 +85,7 @@ static gboolean on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer u uint8_t in_port; char which_interrupt; uint8_t upscaleFactor = 2; +uint8_t lauteco = 90; //GLOBAL GRAPHICS uint8_t *bitmap = NULL; @@ -780,6 +778,19 @@ int emulate8080(State8080* state) { state->pc += 2; } break; + case 0x3b: // DCX SP + { + state->sp--; + } + break; + case 0x3c: // INR A + { + state->a++; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + } + break; case 0x3d: // DCR A { state->a--; @@ -788,10 +799,14 @@ int emulate8080(State8080* state) { state->cc.p = parity(state->a, 8); } break; + case 0x3e: // MVI A, byte state->a = opcode[1]; state->pc++; break; + case 0x3f: // CMC + state->cc.cy = 0; + break; case 0x41: // MOV B, C state->b = state->c; break; @@ -1008,22 +1023,128 @@ int emulate8080(State8080* state) { state->cc.cy = (1 == (x & 1)); } break; + + case 0xa0: // ANA B + state->a = state->a & state->b; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; + case 0xa1: // ANA C + state->a = state->a & state->c; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; + case 0xa2: // ANA D + state->a = state->a & state->d; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; + case 0xa3: // ANA E + state->a = state->a & state->e; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; + case 0xa4: // ANA H + state->a = state->a & state->h; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; + case 0xa5: // ANA L + state->a = state->a & state->l; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; + case 0xa6: // ANA HL + { + uint16_t adress = (state->h << 8) | state->l; + state->a = state->a & state->memory[adress]; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + } + break; case 0xa7: // ANA A state->a &= state->a; state->cc.z = (state->a == 0); state->cc.s = (0x80 == (state->a & 0x80)); state->cc.p = parity(state->a, 8); - state->cc.cy = 0; - state->cc.ac = 0; + state->cc.cy = state->cc.ac = 0; + break; + case 0xa8: // XRA B + state->a ^= state->b; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + state->cc.cy = state->cc.ac = 0; + break; + case 0xa9: // XRA C + state->a ^= state->c; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + state->cc.cy = state->cc.ac = 0; + break; + case 0xaa: // XRA D + state->a ^= state->d; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + state->cc.cy = state->cc.ac = 0; + break; + + case 0xab: // XRA E + state->a ^= state->e; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + state->cc.cy = state->cc.ac = 0; + break; + + case 0xac: // XRA H + state->a ^= state->h; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + state->cc.cy = state->cc.ac = 0; + break; + + case 0xad: // XRA L + state->a ^= state->d; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + state->cc.cy = state->cc.ac = 0; + break; + case 0xae: // XRA HL + { + uint16_t adress = (state->h << 8) | state->l; + state->a ^= state->memory[adress]; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + } break; case 0xaf: // XRA A state->a ^= state->a; state->cc.z = (state->a == 0); state->cc.s = (0x80 == (state->a & 0x80)); state->cc.p = parity(state->a, 8); - state->cc.cy = 0; - state->cc.ac = 0; + state->cc.cy = state->cc.ac = 0; break; case 0xb0: // ORA B state->a |= state->b; @@ -1032,6 +1153,41 @@ int emulate8080(State8080* state) { state->cc.s = (0x80 == (state->a & 0x80)); state->cc.p = parity(state->a, 8); break; + case 0xb1: // ORA C + state->a |= state->c; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; + case 0xb2: // ORA D + state->a |= state->d; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; + case 0xb3: // ORA E + state->a |= state->e; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; + case 0xb4: // ORA H + state->a |= state->h; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; + case 0xb5: // ORA L + state->a |= state->l; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; case 0xb6: // ORA M { uint16_t offset = (state->h<<8) | (state->l); @@ -1042,6 +1198,13 @@ int emulate8080(State8080* state) { state->cc.p = parity(state->a, 8); } break; + case 0xb7: // ORA A + state->a |= state->a; + state->cc.cy = state->cc.ac = 0; + state->cc.z = (state->a == 0); + state->cc.s = (0x80 == (state->a & 0x80)); + state->cc.p = parity(state->a, 8); + break; case 0xc0: // RNZ { if (state->cc.z == 0) { @@ -1118,6 +1281,19 @@ int emulate8080(State8080* state) { } } break; + case 0xcc: // CZ adress + { + if (state->cc.z == 1) { + uint16_t ret = state->pc+2; + state->memory[state->sp-1] = (ret >> 8) & 0xff; + state->memory[state->sp-2] = ret & 0xff; + state->sp -= 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } else { + state->pc += 2; + } + } + break; case 0xcd: // CALL adress { @@ -1128,6 +1304,32 @@ int emulate8080(State8080* state) { state->pc = (opcode[2] << 8) | opcode[1]; } break; + case 0xce: // ACI byte + { + uint16_t answer = (uint16_t) state->a + (uint16_t) opcode[1] + state->cc.cy; + state->cc.z = ((answer & 0xff) == 0); + state->cc.s = (((answer & 0xff) & 0x80) == 0x80); + state->cc.p = parity(answer & 0xff, 8); + state->cc.cy = (answer > 0xff); + state->a = answer & 0xff; + state->pc++; + } + break; + case 0xcf: // RST 1 + { + uint16_t ret = state->pc+2; + state->memory[state->sp-1] = (ret >> 8) & 0xff; + state->memory[state->sp-2] = (ret & 0xff); + state->sp -= 2; + state->pc = 0x08; + } + break; + case 0xd0: // RNC + if (state->cc.cy == 0) { + state->pc = state->memory[state->sp] | (state->memory[state->sp+1]<<8); + state->sp += 2; + } + break; case 0xd1: // POP D state->e = state->memory[state->sp]; state->d = state->memory[state->sp+1]; @@ -1149,11 +1351,44 @@ int emulate8080(State8080* state) { state->pc++; } break; + case 0xd4: // CNC Adress + { + if (state->cc.cy == 0) { + uint16_t ret = state->pc+2; + state->memory[state->sp-1] = ((ret >> 8) & 0xff); + state->memory[state->sp-2] = (ret & 0xff); + state->sp -= 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } else { + state->pc += 2; + } + } + break; case 0xd5: // PUSH D state->memory[state->sp-1] = state->d; state->memory[state->sp-2] = state->e; state->sp -= 2; break; + case 0xd6: // SUI Byte + { + uint8_t x = state->a - opcode[1]; + state->cc.z = (x&0xff == 0); + state->cc.s = (0x80 == ((x&0xff) & 0x80)); + state->cc.p = parity(x&0xff, 8); + state->cc.cy = (state->a < opcode[1]); + state->a = x; + state->pc++; + } + break; + case 0xd7: // RST 2 + { + uint16_t ret = state->pc+2; + state->memory[state->sp-1] = ((ret >> 8) & 0xff); + state->memory[state->sp-2] = (ret & 0xff); + state->sp -= 2; + state->pc = 0x10; + } + break; case 0xd8: // RC { if (state->cc.cy != 0) { @@ -1178,6 +1413,46 @@ int emulate8080(State8080* state) { state->pc++; } break; + case 0xdc: // CC Adress + { + if (state->cc.cy != 0) { + uint16_t ret = state->pc+2; + state->memory[state->sp-1] = ((ret >> 8) & 0xff); + state->memory[state->sp-2] = (ret & 0xff); + state->sp -= 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } else { + state->pc += 2; + } + } + break; + case 0xde: // SBI byte + { + uint16_t x = state->a - opcode[1] - state->cc.cy; + state->cc.z = (x&0xff == 0); + state->cc.s = (0x80 == ((x&0xff) & 0x80)); + state->cc.p = parity(x&0xff, 8); + state->cc.cy = (x > 0xff); + state->a = x & 0xff; + state->pc++; + } + break; + case 0xdf: // RST 3 + { + uint16_t ret = state->pc+2; + state->memory[state->sp-1] = ((ret >> 8) & 0xff); + state->memory[state->sp-2] = (ret & 0xff); + state->sp -= 2; + state->pc = 0x18; + } + break; + case 0xe0: // RPO + if (state->cc.p == 0) + { + state->pc = state->memory[state->sp] | (state->memory[state->sp+1]<<8); + state->sp += 2; + } + break; case 0xe1: // POP H state->l = state->memory[state->sp]; state->h = state->memory[state->sp+1]; @@ -1349,11 +1624,60 @@ int emulate8080(State8080* state) { state->memory[state->sp-2] = (state->cc.z | (state->cc.s << 1) | (state->cc.p << 2) | (state->cc.cy << 3) | (state->cc.ac << 4)); state->sp -= 2; break; + case 0xf6: // ORI + { + uint8_t x = state->a | opcode[1]; + state->cc.z = (x == 0); + state->cc.s = (0x80 == (x & 0x80)); + state->cc.p = parity(x, 8); - case 0xfb: // EI - state->int_enable = 1; break; + state->cc.cy = 0; + state->a = x; + state->pc++; + } break; + case 0xf7: // RST 6 + { + uint16_t ret = state->pc+2; + state->memory[state->sp-1] = (ret >> 8) & 0xff; + state->memory[state->sp-2] = (ret & 0xff); + state->sp -=2; + state->pc = 0x30; + } + break; + case 0xf8: //RM + if (state->cc.s != 0) + { + state->pc = state->memory[state->sp] | (state->memory[state->sp+1]<<8); + state->sp += 2; + } + break; + case 0xf9: // SPHL + state->sp = state->l | (state->h << 8); + break; + case 0xfa: // JM + if (state->cc.s != 0) + state->pc = (opcode[2] << 8) | opcode[1]; + else + state->pc += 2; + break; + case 0xfb: // EI + state->int_enable = 1; + break; + case 0xfc: // CM + { + if (state->cc.s != 0) { + uint16_t ret = state->pc+2; + state->memory[state->sp-1] = (ret >> 8) & 0xff; + state->memory[state->sp-2] = (ret & 0xff); + state->sp -= 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } else { + state->pc += 2; + } + } + break; case 0xfe: // CPI byte { uint8_t x = state->a - opcode[1]; @@ -1364,7 +1688,15 @@ int emulate8080(State8080* state) { state->pc++; } break; - + case 0xff: // RST 7 + { + uint16_t ret = state->pc+2; + state->memory[state->sp-1] = (ret >> 8) & 0xff; + state->memory[state->sp-2] = (ret & 0xff); + state->sp -=2; + state->pc = 0x38; + } + break; default: unknownInstruction(state); break; } printState(state); @@ -1485,9 +1817,9 @@ void *cpu(void* arg) { static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { 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); - cairo_paint(cr); + // Clear the drawing area if you want + //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++) { @@ -1505,7 +1837,7 @@ static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { } // Rendering the graphics - for (int x = 0; x < 256; x++) { + for (int x = 0; x < 224; x++) { for (int y = 0; y < 256; y++) { if (video[y*256 + x]) { cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); // Set color to white @@ -1523,11 +1855,9 @@ static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { 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_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), "Lux8080-Emulator"); + gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), "This is a simple Intel 8080-Emulator for Space Invaders using C and GTK. Following the guide of @realemulator101"); + gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), "your logo"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } @@ -1577,8 +1907,8 @@ int main (int argc, char *argv[]) { // GTK init 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), "Luxulator"); + gtk_window_set_default_size(GTK_WINDOW(window), 448, 550); + 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);