Further commands
This commit is contained in:
parent
0b2aeb182f
commit
0b1a59a4d4
1 changed files with 351 additions and 21 deletions
372
emulator_shell.c
372
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;
|
||||
|
@ -1009,21 +1024,127 @@ int emulate8080(State8080* state) {
|
|||
}
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue