diff --git a/emulator_shell.c b/emulator_shell.c index 481540b..86757fb 100644 --- a/emulator_shell.c +++ b/emulator_shell.c @@ -7,88 +7,15 @@ // gcc emulator_shell.c `pkg-config --cflags --libs gtk+-3.0` -lpthread -o emulator -void keyDown(uint8_t key); -void keyUp(uint8_t key); - -//===== GTK SETUP ===== - -static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) -{ - switch (event->keyval) - { - case GDK_KEY_Left: - // Code to be executed when the left arrow key is pressed down - g_print("Left arrow key pressed down\n"); - keyDown(1); - break; - case GDK_KEY_Right: - // Code to be executed when the right arrow key is pressed down - g_print("Right arrow key pressed down\n"); - keyDown(2); - break; - case GDK_KEY_space: - // Code to be executed when the space bar is pressed down - g_print("Space bar pressed down\n"); - keyDown(3); - break; - case GDK_KEY_c: - // Code to be executed when the 'c' key is pressed down - g_print("'c' key pressed down\n"); - keyDown(0); - break; - case GDK_KEY_s: - // Code to be executed when the 's' key is pressed down - g_print("'s' key pressed down\n"); - keyDown(4); - break; - } - - return FALSE; -} - -static gboolean on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer user_data) -{ - switch (event->keyval) - { - case GDK_KEY_Left: - // Code to be executed when the left arrow key is released - g_print("Left arrow key released\n"); - keyUp(1); - break; - case GDK_KEY_Right: - // Code to be executed when the right arrow key is released - g_print("Right arrow key released\n"); - keyUp(2); - break; - case GDK_KEY_space: - // Code to be executed when the space bar is pressed down - g_print("Space bar released\n"); - keyUp(3); - break; - case GDK_KEY_c: - // Code to be executed when the 'c' key is pressed down - g_print("'c' key released\n"); - keyUp(0); - break; - case GDK_KEY_s: - // Code to be executed when the 's' key is pressed down - g_print("'s' key released\n"); - keyUp(4); - break; - } - return FALSE; -} - //===== EMULATOR SETUP ===== //GLOBAL VARIABLES uint8_t in_port; char which_interrupt; uint8_t upscaleFactor = 2; -uint8_t lauteco = 90; //GLOBAL GRAPHICS -uint8_t *bitmap = NULL; +uint8_t *bitmap = NULL; @@ -144,6 +71,117 @@ unsigned char cycles8080[] = { 11, 10, 10, 4, 17, 11, 7, 11, 11, 5, 10, 4, 17, 17, 7, 11, }; +//===== GTK SETUP ===== + +void keyDown(uint8_t key) +{ + switch(key) { + case 0: // COIN + in_port |= 0x1; + break; + case 1: // LEFT + in_port |= 0x20; + break; + case 2: // RIGHT + in_port |= 0x40; + break; + case 3: // FIRE + in_port |= 0x10; + break; + case 4: // START + in_port |= 0x04; + break; + } +} + +void keyUp(uint8_t key) +{ + switch(key) { + case 0: // COIN + in_port &= ~0x1; + break; + case 1: // LEFT + in_port &= ~0x20; + break; + case 2: // RIGHT + in_port &= ~0x40; + break; + case 3: // FIRE + in_port &= ~0x10; + break; + case 4: // START + in_port &= ~0x04; + break; + } +} + +static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + switch (event->keyval) + { + case GDK_KEY_a: + // Code to be executed when the left arrow key is pressed down + g_print("Left arrow key pressed down\n"); + keyDown(1); + break; + case GDK_KEY_d: + // Code to be executed when the right arrow key is pressed down + g_print("Right arrow key pressed down\n"); + keyDown(2); + break; + case GDK_KEY_w: + // Code to be executed when the space bar is pressed down + g_print("w down\n"); + keyDown(3); + break; + case GDK_KEY_c: + // Code to be executed when the 'c' key is pressed down + g_print("'c' key pressed down\n"); + keyDown(0); + break; + case GDK_KEY_s: + // Code to be executed when the 's' key is pressed down + g_print("'s' key pressed down\n"); + keyDown(4); + break; + } + + return FALSE; +} + +static gboolean on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + switch (event->keyval) + { + case GDK_KEY_a: + // Code to be executed when the left arrow key is released + g_print("Left arrow key released\n"); + keyUp(1); + break; + case GDK_KEY_d: + // Code to be executed when the right arrow key is released + g_print("Right arrow key released\n"); + keyUp(2); + break; + case GDK_KEY_w: + // Code to be executed when the space bar is pressed down + g_print("w released\n"); + keyUp(3); + break; + case GDK_KEY_c: + // Code to be executed when the 'c' key is pressed down + g_print("'c' key released\n"); + keyUp(0); + break; + case GDK_KEY_s: + // Code to be executed when the 's' key is pressed down + g_print("'s' key released\n"); + keyUp(4); + break; + } + return FALSE; +} + //===== EMULATOR FUNCTIONS ===== int disassemble8080(unsigned char* code) { @@ -444,7 +482,7 @@ int disassemble8080(unsigned char* code) { } -void unknownInstruction(State8080* state) { +void UnimplementedInstruction(State8080* state) { printf("Error: Unknown instruction"); return exit(1); } @@ -474,10 +512,13 @@ uint8_t machineIn(State8080* state, uint8_t port) { uint8_t a; switch(port) { case 0: - a = 1; + a = 0xf; + break; + case 1: + a = in_port; break; case 2: - a = in_port; + a = 0; break; case 3: { @@ -503,1203 +544,991 @@ void machineOut(State8080* state, uint8_t port, uint8_t value) { } } } +// Due to problems in code, many commands were replaced by the ones from the guide + +static void LogicFlagsA(State8080 *state) +{ + 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); +} + +static void ArithFlagsA(State8080 *state, uint16_t res) +{ + state->cc.cy = (res > 0xff); + state->cc.z = ((res&0xff) == 0); + state->cc.s = (0x80 == (res & 0x80)); + state->cc.p = parity(res&0xff, 8); +} + +static void WriteMem(State8080* state, uint16_t address, uint8_t value) +{ + if (address < 0x2000) + { + // printf("Writing ROM not allowed %x\n", address); + return; + } + if (address >=0x4000) + { + // printf("Writing out of Space Invaders RAM not allowed %x\n", address); + return; + } + + state->memory[address] = value; +} + +static uint8_t ReadFromHL(State8080* state) +{ + uint16_t offset = (state->h << 8) | state->l; + return state->memory[offset]; +} + +static void WriteToHL(State8080* state, uint8_t value) +{ + uint16_t offset = (state->h << 8) | state->l; + WriteMem(state, offset, value); +} + +static void Push(State8080* state, uint8_t high, uint8_t low) +{ + WriteMem(state, state->sp-1, high); + WriteMem(state, state->sp-2, low); + state->sp = state->sp - 2; + // printf ("%04x %04x\n", state->pc, state->sp); +} + +static void Pop(State8080* state, uint8_t *high, uint8_t *low) +{ + *low = state->memory[state->sp]; + *high = state->memory[state->sp+1]; + state->sp += 2; + // printf ("%04x %04x pop\n", state->pc, state->sp); +} + +static void FlagsZSP(State8080 *state, uint8_t value) +{ + state->cc.z = (value == 0); + state->cc.s = (0x80 == (value & 0x80)); + state->cc.p = parity(value, 8); +} + int emulate8080(State8080* state) { unsigned char *opcode = &(state->memory[state->pc]); - printf("%04x ", state->pc); + //printf("%04x ", state->pc); - disassemble8080(opcode); + //disassemble8080(opcode); state->pc++; switch(*opcode) { - case 0x00: break; // NOP does nothing - case 0x01: // LXI B, word - state->c = opcode[1]; - state->b = opcode[2]; - state->pc += 2; - break; - case 0x02: // STAX B - { - uint16_t offset = (state->b << 8) | state->c; - state->memory[offset] = state->a; - } - break; - case 0x03: // INX B - { - state->c++; - if (state->c == 0) { - state->b++; - } - state->cc.z = (state->b == 0); - state->cc.s = (0x80 == (state->b & 0x80)); - state->cc.p = parity(state->b, 8); - } - break; - case 0x04: // INR B - { - state->b++; - } - break; - case 0x05: // DCR B - { - uint8_t res = state->b - 1; - state->b = res; - state->cc.z = (res == 0); - state->cc.s = (0x80 == (res & 0x80)); - state->cc.p = parity(res, 8); - } - break; - case 0x06: // MVI B, byte - state->b = opcode[1]; - state->pc += 1; - break; - case 0x07: // RLC - { - uint8_t x = state->a; - state->a = ((x & 0x80) >> 7) | (x << 1); - state->cc.cy = (0x80 == (x & 0x80)); - } - break; - case 0x09: // DAD B - { - uint32_t h1 = (state->h << 8) | state->l; - uint32_t bc = (state->b << 8) | state->c; - uint32_t result = h1 + bc; - state->h = (result & 0xff00) >> 8; - state->l = result & 0xff; - state->cc.cy = ((result & 0xffff0000) != 0); - } - break; - - case 0x0a: // LDAX B - { - uint16_t address = (state->b << 8) | state->c; - state->a = state->memory[address]; - } - break; - - case 0x0d: // DCR C - { - uint8_t res = state->c - 1; - state->c = res; - state->cc.z = (res == 0); - state->cc.s = ((res & 0x80) == 0x80); - state->cc.p = parity(res, 8); - } - break; - case 0x0e: // MVI C, byte - state->c = opcode[1]; - state->pc++; - break; - case 0x0f: // RRC - { + case 0x00: break; //NOP + case 0x01: //LXI B,word + state->c = opcode[1]; + state->b = opcode[2]; + state->pc += 2; + break; + case 0x02: //STAX B + { + uint16_t offset=(state->b<<8) | state->c; + WriteMem(state, offset, state->a); + } + break; + case 0x03: //INX B + state->c++; + if (state->c == 0) + state->b++; + break; + case 0x04: //INR B + state->b += 1; + FlagsZSP(state,state->b); + break; + case 0x05: //DCR B + state->b -= 1; + FlagsZSP(state,state->b); + break; + case 0x06: //MVI B,byte + state->b = opcode[1]; + state->pc++; + break; + case 0x07: //RLC + { + uint8_t x = state->a; + state->a = ((x & 0x80) >> 7) | (x << 1); + state->cc.cy = (0x80 == (x&0x80)); + } + break; + case 0x08: UnimplementedInstruction(state); break; + case 0x09: //DAD B + { + uint32_t hl = (state->h << 8) | state->l; + uint32_t bc = (state->b << 8) | state->c; + uint32_t res = hl + bc; + state->h = (res & 0xff00) >> 8; + state->l = res & 0xff; + state->cc.cy = ((res & 0xffff0000) != 0); + } + break; + case 0x0a: //LDAX B + { + uint16_t offset=(state->b<<8) | state->c; + state->a = state->memory[offset]; + } + break; + case 0x0b: //DCX B + state->c -= 1; + if (state->c==0xff) + state->b-=1; + break; + case 0x0c: //INR C + state->c += 1; + FlagsZSP(state,state->c); + break; + + case 0x0d: //DCR C + state->c -= 1; + FlagsZSP(state,state->c); + break; + case 0x0e: //MVI C,byte + state->c = opcode[1]; + state->pc++; + break; + case 0x0f: //RRC + { uint8_t x = state->a; state->a = ((x & 1) << 7) | (x >> 1); - state->cc.cy = (1 == (x & 1)); - } - break; - case 0x11: // LXI D, word - { - state->d = opcode[2]; - state->e = opcode[1]; - state->pc += 2; - } - break; - case 0x13: // INX D - { - state->e++; - if (state->e == 0) { - state->d++; - }} - break; - case 0x16: // MVI D, byte - state->d = opcode[1]; - state->pc++; - break; - case 0x19: // DAD D - { - uint32_t h1 = (state->h << 8) | state->l; - uint32_t de = (state->d << 8) | state->e; - uint32_t result = h1 + de; - state->h = (result & 0xff00) >> 8; - state->l = result & 0xff; - state->cc.cy = ((result & 0xffff0000) != 0); - } - break; - case 0x1a: // LDAX D - { - uint16_t de = (state->d << 8) | state->e; - state->a = state->memory[de]; - } - break; - - case 0x21: // LXI H, word - { - state->h = opcode[2]; - state->l = opcode[1]; - state->pc += 2; - } - break; - case 0x22: // SHLD - { - uint16_t address = (opcode[2] << 8) | opcode[1]; - state->memory[address] = state->l; - state->memory[address+1] = state->h; - state->pc += 2; - } - break; - case 0x23: // INX H - { - state->l++; - if (state->l == 0) { - state->h++; - } - } - break; - case 0x26: // MVI H, byte - { - state->h = opcode[1]; - state->pc++; - } - break; - case 0x27: // DAA - { - if ((state->a & 0x0f) > 9) { - state->a += 6; - } else if ((state->a & 0xf0) > 0x90) { - uint16_t res = (uint16_t) state->a + 0x60; - state->a = res & 0xff; - state->cc.cy = (res > 0xff); - state->cc.z = ((res & 0xff) == 0); - state->cc.s = (0x80 == (res & 0x80)); - state->cc.p = parity((res & 0xff), 8); - } - } - break; - case 0x29: // DAD H - { - uint32_t hl = (state->h << 8) | state->l; - uint32_t result = hl + hl; - state->h = (result & 0xff00) >> 8; - state->l = result & 0xff; - state->cc.cy = ((result & 0xffff0000) != 0); - } - break; - - case 0x2a: // LHLD adress - { - uint16_t adress = (opcode[2]<<8) | (opcode[1]); - state->h = state->memory[adress]; - state->l = state->memory[adress+1]; - state->pc += 2; - } - break; - case 0x2b: // DCX H - { - state->l--; - if (state->l == 0xff) { - state->h--; - } - } - break; - case 0x2c: // INR L - { - state->l++; - state->cc.z = (state->l == 0); - state->cc.s = (0x80 == (state->l & 0x80)); - state->cc.p = parity(state->l, 8); - } - break; - case 0x2d: // DCR L - { - state->l--; - state->cc.z = (state->l == 0); - state->cc.s = (0x80 == (state->l & 0x80)); - state->cc.p = parity(state->l, 8); - } - break; - case 0x2e: // MVI L, Adress - state->l = opcode[1]; - state->pc++; - break; - case 0x2f: // CMA (NOT) - state->a = ~state->a; - break; - case 0x31: // LXI SP, word - state->sp = ((opcode[2] << 8) | opcode[1]); - state->pc += 2; - break; - case 0x32: // STA adress - { - uint16_t adress = (opcode[2]<<8) | (opcode[1]); - state->memory[adress] = state->a; - state->pc += 2; - } - break; - - case 0x34: // ICR M - { - uint16_t offset = (state->h << 8) | state->l; - uint8_t res = state->memory[offset] + 1; - state->cc.z = (res == 0); - state->cc.s = (0x80 == (res & 0x80)); - state->cc.p = parity(res, 8); - state->memory[offset] = res; - } - break; - case 0x35: // DCR M - { - uint16_t offset = (state->h << 8) | state->l; - uint8_t res = state->memory[offset] - 1; - state->cc.z = (res == 0); - state->cc.s = (0x80 == (res & 0x80)); - state->cc.p = parity(res, 8); - state->memory[offset] = res; - } - break; - case 0x36: // MVI M, byte - { - uint16_t adress = (state->h <<8) | (state->l); - state->memory[adress] = opcode[1]; - state->pc++; - } - break; - - case 0x37: // STC - state->cc.cy = 1; - break; - - case 0x3a: // LDA adress - { - uint16_t adress = (opcode[2]<<8) | (opcode[1]); - state->a = state->memory[adress]; - 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--; - state->cc.z = (state->a == 0); - state->cc.s = (0x80 == (state->a & 0x80)); - 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; - case 0x42: // MOV B, D - state->b = state->d; - break; - case 0x43: // MOV B, E - state->b = state->e; - break; - case 0x44: // MOV B, H - state->b = state->h; - break; - case 0x45: // MOV B, L - state->b = state->l; - break; - case 0x46: // MOV B, M - { - uint16_t adress = (state->h<<8) | (state->l); - state->b = state->memory[adress]; - } - case 0x47: // MOV B, A - state->b = state->a; - break; - case 0x48: // MOV C, B - state->c = state->b; - break; - case 0x49: // MOV C, C - break; - case 0x4a: // MOV C, D - state->c = state->d; - break; - case 0x4b: // MOV C, E - state->c = state->e; - break; - case 0x4c: // MOV C, H - state->c = state->h; - break; - case 0x4d: // MOV C, L - state->c = state->l; - break; - case 0x4e: // MOV C, M - { - uint16_t adress = (state->h<<8) | (state->l); - state->c = state->memory[adress]; - } - break; - case 0x4f: // MOV C, A - state->c = state->a; - break; - case 0x50: // MOV D, B - state->d = state->b; - break; - case 0x51: // MOV D, C - state->d = state->c; - break; - case 0x52: // MOV D, D - break; - case 0x53: // MOV D, E - state->d = state->e; - break; - case 0x54: // MOV D, H - state->d = state->h; - break; - case 0x55: // MOV D, L - state->d = state->l; - break; - case 0x56: // MOV D, M - { - uint16_t adress = (state->h<<8) | (state->l); - state->d = state->memory[adress]; - } - break; - case 0x57: // MOV D, A - state->d = state->a; - break; - case 0x58: // MOV E, B - state->e = state->b; - break; - case 0x59: // MOV E, C - state->e = state->c; - break; - case 0x5a: // MOV E, D - state->e = state->d; - break; - case 0x5b: // MOV E, E - break; - case 0x5c: // MOV E, H - state->e = state->h; - break; - case 0x5d: // MOV E, L - state->e = state->l; - break; - case 0x5e: // MOV E, M - { - uint16_t adress = (state->h<<8) | (state->l); - state->e = state->memory[adress]; - } - break; - case 0x5f: // MOV E, A - state->e = state->a; - break; - case 0x60: // MOV H, B - state->h = state->b; - break; - case 0x61: // MOV H, C - state->h = state->c; - break; - case 0x62: // MOV H, D - state->h = state->d; - break; - case 0x63: // MOV H, E - state->h = state->e; - break; - case 0x64: // MOV H, H - break; - case 0x65: // MOV H, L - state->h = state->l; - break; - case 0x66: // MOV H, M - { - uint16_t adress = (state->h<<8) | (state->l); - state->h = state->memory[adress]; - } - break; - case 0x67: // MOV H, A - { - state->h = state->a; - } - break; - case 0x68: // MOV L, B - state->l = state->b; - break; - case 0x69: // MOV L, C - state->l = state->c; - break; - case 0x6a: // MOV L, D - state->l = state->d; - break; - case 0x6b: // MOV L, E - state->l = state->e; - break; - case 0x6c: // MOV L, H - state->l = state->h; - break; - case 0x6d: // MOV L, L - break; - case 0x6e: // MOV L, M - { - uint16_t adress = (state->h<<8) | (state->l); - state->l = state->memory[adress]; - } - break; - case 0x6f: // MOV L, A - state->l = state->a; - break; - case 0x77: // MOV M, A - { - uint16_t adress = (state->h<<8) | (state->l); - state->memory[adress] = state->a; - } - break; - case 0x7a: // MOV A, D - state->a = state->d; - break; - case 0x78: // MOV A, B - state->a = state->b; - break; - case 0x79: // MOV A, C - state->a = state->c; - break; - case 0x7b: // MOV A, E - state->a = state->e; - break; - case 0x7c: // MOV A, H - state->a = state->h; - break; - case 0x7d: // MOV A, L - state->a = state->l; - break; - case 0x7e: // MOV A, M - { - uint16_t adress = (state->h<<8) | (state->l); - state->a = state->memory[adress]; - } - break; - case 0x7f: // MOV A, A - break; - case 0x80: // ADD B - { - uint16_t answer = (uint16_t) state->a + (uint16_t) state->b; - state->cc.z = ((answer & 0xff) == 0); - state->cc.s = ((answer & 0x80) != 0); - state->cc.cy = (answer > 0xff); - state->cc.p = parity(answer & 0xff, 8); - state->a = answer & 0xff; - } - break; - - case 0x86: // ADD M - { - uint16_t offset = (state->h<<8) | (state->l); - uint16_t answer = (uint16_t) state->a + state->memory[offset]; - state->cc.z = ((answer & 0xff) == 0); - state->cc.s = ((answer & 0x80) != 0); - state->cc.cy = (answer > 0xff); - state->cc.p = parity(answer & 0xff, 8); - state->a = answer & 0xff; - } - break; - case 0x1f: // RAR - { - uint8_t x = state->a; - state->a = (state->cc.cy << 7) | (x >> 1); - 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 = 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 = state->cc.ac = 0; - break; - case 0xb0: // ORA B - 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 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); - state->a |= state->memory[offset]; - 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 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) { - state->pc = state->memory[state->sp] | (state->memory[state->sp+1] << 8); - state->sp += 2; - } - } - break; - case 0xc1: // POP B - state->c = state->memory[state->sp]; - state->b = state->memory[state->sp+1]; - state->sp += 2; - break; - - case 0xc2: // JNZ adress - if (0 == state-> cc.z) { - state->pc = (opcode[2] << 8) | opcode[1]; - } else { - state->pc += 2; - } - break; - - case 0xc3: // JMP adress - state->pc = (opcode[2] << 8) | opcode[1]; - break; - case 0xc4: // CNZ adress - { - if (0 == state->cc.z) { - 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 0xc5: // PUSH B - state->memory[state->sp-1] = state->b; - state->memory[state->sp-2] = state->c; - state->sp -= 2; - break; - case 0xc6: // ADI byte - { - uint16_t answer = (uint16_t) state->a + (uint16_t) opcode[1]; - state->cc.z = ((state->a & 0xff) == 0); - state->cc.s = ((state->a & 0x80) == 0x80); - state->cc.cy = (state->a > 0xff); - state->cc.p = parity(state->a & 0xff, 8); - state->pc++; - } - break; - - case 0xc8: // RZ - { - if (state->cc.z) { - state->pc = state->memory[state->sp] | (state->memory[state->sp+1] << 8); - state->sp += 2; - } - } - break; - case 0xc9: // RET - state->pc = (state->memory[state->sp+1] << 8) | state->memory[state->sp]; - state->sp += 2; - break; - case 0xca: // JZ adress - { - if (state->cc.z) { - state->pc = (opcode[2] << 8) | opcode[1]; - } else { - state->pc +=2; - } - } - 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; + state->cc.cy = (1 == (x&1)); + } + break; + + case 0x10: UnimplementedInstruction(state); break; + case 0x11: //LXI D,word + state->e = opcode[1]; + state->d = opcode[2]; + state->pc += 2; + break; + case 0x12: //STAX D + { + uint16_t offset=(state->d<<8) | state->e; + WriteMem(state, offset, state->a); + } + break; + case 0x13: //INX D + state->e++; + if (state->e == 0) + state->d++; + break; + case 0x14: //INR D + state->d += 1; + FlagsZSP(state,state->d); + break; + case 0x15: //DCR D + state->d -= 1; + FlagsZSP(state,state->d); + break; + case 0x16: //MVI D,byte + state->d = opcode[1]; + state->pc++; + break; + case 0x17: //RAL + { + uint8_t x = state->a; + state->a = state->cc.cy | (x << 1); + state->cc.cy = (0x80 == (x&0x80)); + } + break; + case 0x18: UnimplementedInstruction(state); break; + case 0x19: //DAD D + { + uint32_t hl = (state->h << 8) | state->l; + uint32_t de = (state->d << 8) | state->e; + uint32_t res = hl + de; + state->h = (res & 0xff00) >> 8; + state->l = res & 0xff; + state->cc.cy = ((res & 0xffff0000) != 0); + } + break; + case 0x1a: //LDAX D + { + uint16_t offset=(state->d<<8) | state->e; + state->a = state->memory[offset]; + } + break; + case 0x1b: //DCX D + state->e -= 1; + if (state->e==0xff) + state->d-=1; + break; + case 0x1c: //INR E + state->e += 1; + FlagsZSP(state,state->e); + break; - case 0xcd: // CALL adress + case 0x1d: //DCR E + state->e -= 1; + FlagsZSP(state,state->e); + break; + case 0x1e: //MVI E,byte + state->e = opcode[1]; + state->pc++; + break; + case 0x1f: //RAR + { + uint8_t x = state->a; + state->a = (state->cc.cy << 7) | (x >> 1); + state->cc.cy = (1 == (x&1)); + } + break; + case 0x20: UnimplementedInstruction(state); break; + case 0x21: //LXI H,word + state->l = opcode[1]; + state->h = opcode[2]; + state->pc += 2; + break; + case 0x22: //SHLD + { + uint16_t offset = opcode[1] | (opcode[2] << 8); + WriteMem(state, offset, state->l); + WriteMem(state, offset+1, state->h); + state->pc += 2; + } + break; + case 0x23: //INX H + state->l++; + if (state->l == 0) + state->h++; + break; + case 0x24: //INR H + state->h += 1; + FlagsZSP(state,state->h); + break; + case 0x25: //DCR H + state->h -= 1; + FlagsZSP(state,state->h); + break; + case 0x26: //MVI H,byte + state->h = opcode[1]; + state->pc++; + break; + case 0x27: + if ((state->a &0xf) > 9) + state->a += 6; + if ((state->a&0xf0) > 0x90) { - uint16_t ret = state -> pc+2; - state->memory[state->sp-1] = (ret >> 8) & 0xff; - state->memory[state->sp-2] = (ret & 0xff); - state->sp -= 2; + uint16_t res = (uint16_t) state->a + 0x60; + state->a = res & 0xff; + ArithFlagsA(state, res); + } + break; + case 0x28: UnimplementedInstruction(state); break; + case 0x29: //DAD H + { + uint32_t hl = (state->h << 8) | state->l; + uint32_t res = hl + hl; + state->h = (res & 0xff00) >> 8; + state->l = res & 0xff; + state->cc.cy = ((res & 0xffff0000) != 0); + } + break; + case 0x2a: //LHLD adr + { + uint16_t offset = opcode[1] | (opcode[2] << 8); + state->l = state->memory[offset]; + state->h = state->memory[offset+1]; + state->pc += 2; + } + break; + case 0x2b: //DCX H + state->l -= 1; + if (state->l==0xff) + state->h-=1; + break; + case 0x2c: //INR L + state->l += 1; + FlagsZSP(state,state->l); + break; + case 0x2d: //DCR L + state->l -= 1; + FlagsZSP(state,state->l); + break; + case 0x2e: //MVI L,byte + state->l = opcode[1]; + state->pc++; + break; + case 0x2f: + state->a = ~state->a; //CMA + break; + case 0x30: UnimplementedInstruction(state); break; + case 0x31: //LXI SP,word + state->sp = (opcode[2]<<8) | opcode[1]; + state->pc += 2; + break; + case 0x32: //STA (word) + { + uint16_t offset = (opcode[2]<<8) | (opcode[1]); + WriteMem(state, offset, state->a); + state->pc += 2; + } + break; + case 0x33: //INX SP + state->sp++; + break; + case 0x34: //INR M + { + uint8_t res = ReadFromHL(state) + 1; + FlagsZSP(state, res); + WriteToHL(state, res); + } + break; + case 0x35: //DCR M + { + uint8_t res = ReadFromHL(state) - 1; + FlagsZSP(state, res); + WriteToHL(state, res); + } + break; + case 0x36: //MVI M,byte + { + WriteToHL(state, opcode[1]); + state->pc++; + } + break; + case 0x37: state->cc.cy = 1; break; + case 0x38: UnimplementedInstruction(state); break; + case 0x39: //DAD SP + { + uint32_t hl = (state->h << 8) | state->l; + uint32_t res = hl + state->sp; + state->h = (res & 0xff00) >> 8; + state->l = res & 0xff; + state->cc.cy = ((res & 0xffff0000) > 0); + } + break; + case 0x3a: //LDA (word) + { + uint16_t offset = (opcode[2]<<8) | (opcode[1]); + state->a = state->memory[offset]; + state->pc+=2; + } + break; + case 0x3b: //DCX SP + state->sp -= 1; + break; + case 0x3c: //INR A + state->a += 1; + FlagsZSP(state,state->a); + break; + case 0x3d: //DCR A + state->a -= 1; + FlagsZSP(state,state->a); + break; + case 0x3e: //MVI A,byte + state->a = opcode[1]; + state->pc++; + break; + case 0x3f: state->cc.cy = 0; break; + + case 0x40: state->b = state->b; break; + case 0x41: state->b = state->c; break; + case 0x42: state->b = state->d; break; + case 0x43: state->b = state->e; break; + case 0x44: state->b = state->h; break; + case 0x45: state->b = state->l; break; + case 0x46: state->b = ReadFromHL(state); break; + case 0x47: state->b = state->a; break; + + case 0x48: state->c = state->b; break; + case 0x49: state->c = state->c; break; + case 0x4a: state->c = state->d; break; + case 0x4b: state->c = state->e; break; + case 0x4c: state->c = state->h; break; + case 0x4d: state->c = state->l; break; + case 0x4e: state->c = ReadFromHL(state); break; + case 0x4f: state->c = state->a; break; + + case 0x50: state->d = state->b; break; + case 0x51: state->d = state->c; break; + case 0x52: state->d = state->d; break; + case 0x53: state->d = state->e; break; + case 0x54: state->d = state->h; break; + case 0x55: state->d = state->l; break; + case 0x56: state->d = ReadFromHL(state); break; + case 0x57: state->d = state->a; break; + + case 0x58: state->e = state->b; break; + case 0x59: state->e = state->c; break; + case 0x5a: state->e = state->d; break; + case 0x5b: state->e = state->e; break; + case 0x5c: state->e = state->h; break; + case 0x5d: state->e = state->l; break; + case 0x5e: state->e = ReadFromHL(state); break; + case 0x5f: state->e = state->a; break; + + case 0x60: state->h = state->b; break; + case 0x61: state->h = state->c; break; + case 0x62: state->h = state->d; break; + case 0x63: state->h = state->e; break; + case 0x64: state->h = state->h; break; + case 0x65: state->h = state->l; break; + case 0x66: state->h = ReadFromHL(state); break; + case 0x67: state->h = state->a; break; + + case 0x68: state->l = state->b; break; + case 0x69: state->l = state->c; break; + case 0x6a: state->l = state->d; break; + case 0x6b: state->l = state->e; break; + case 0x6c: state->l = state->h; break; + case 0x6d: state->l = state->l; break; + case 0x6e: state->l = ReadFromHL(state); break; + case 0x6f: state->l = state->a; break; + + case 0x70: WriteToHL(state, state->b); break; //MOV M,B + case 0x71: WriteToHL(state, state->c); break; //MOV M,C + case 0x72: WriteToHL(state, state->d); break; //MOV M,D + case 0x73: WriteToHL(state, state->e); break; //MOV M,E + case 0x74: WriteToHL(state, state->h); break; //MOV M,H + case 0x75: WriteToHL(state, state->l); break; //MOV M,L + case 0x76: break; //HLT + case 0x77: WriteToHL(state, state->a); break; //MOV M,A + + case 0x78: state->a = state->b; break; + case 0x79: state->a = state->c; break; + case 0x7a: state->a = state->d; break; + case 0x7b: state->a = state->e; break; + case 0x7c: state->a = state->h; break; + case 0x7d: state->a = state->l; break; + case 0x7e: state->a = ReadFromHL(state); break; + case 0x7f: break; + + case 0x80: { uint16_t res = (uint16_t) state->a + (uint16_t) state->b; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADD B + case 0x81: { uint16_t res = (uint16_t) state->a + (uint16_t) state->c; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADD C + case 0x82: { uint16_t res = (uint16_t) state->a + (uint16_t) state->d; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADD D + case 0x83: { uint16_t res = (uint16_t) state->a + (uint16_t) state->e; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADD E + case 0x84: { uint16_t res = (uint16_t) state->a + (uint16_t) state->h; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADD H + case 0x85: { uint16_t res = (uint16_t) state->a + (uint16_t) state->l; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADD L + case 0x86: //ADD M + { + uint16_t res = (uint16_t) state->a + (uint16_t) ReadFromHL(state); + ArithFlagsA(state, res); + state->a=(res&0xff); + } break; + case 0x87: { uint16_t res = (uint16_t) state->a + (uint16_t) state->a; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADC A + + case 0x88: { uint16_t res = (uint16_t) state->a + (uint16_t) state->b + state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADC B + case 0x89: { uint16_t res = (uint16_t) state->a + (uint16_t) state->c + state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADC C + case 0x8a: { uint16_t res = (uint16_t) state->a + (uint16_t) state->d + state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADC D + case 0x8b: { uint16_t res = (uint16_t) state->a + (uint16_t) state->e + state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADC E + case 0x8c: { uint16_t res = (uint16_t) state->a + (uint16_t) state->h + state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADC H + case 0x8d: { uint16_t res = (uint16_t) state->a + (uint16_t) state->l + state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADC L + case 0x8e: //ADC M + { + uint16_t res = (uint16_t) state->a + (uint16_t) ReadFromHL(state) + state->cc.cy; + ArithFlagsA(state, res); + state->a=(res&0xff); + } break; + case 0x8f: { uint16_t res = (uint16_t) state->a + (uint16_t) state->a + state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //ADC A + + + case 0x90: { uint16_t res = (uint16_t) state->a - (uint16_t) state->b; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SUB B + case 0x91: { uint16_t res = (uint16_t) state->a - (uint16_t) state->c; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SUB C + case 0x92: { uint16_t res = (uint16_t) state->a - (uint16_t) state->d; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SUB D + case 0x93: { uint16_t res = (uint16_t) state->a - (uint16_t) state->e; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SUB E + case 0x94: { uint16_t res = (uint16_t) state->a - (uint16_t) state->h; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SUB H + case 0x95: { uint16_t res = (uint16_t) state->a - (uint16_t) state->l; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SUB L + case 0x96: //SUB M + { + uint16_t res = (uint16_t) state->a - (uint16_t) ReadFromHL(state); + ArithFlagsA(state, res); + state->a=(res&0xff); + } break; + case 0x97: { uint16_t res = (uint16_t) state->a - (uint16_t) state->a; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SUB A + + case 0x98: { uint16_t res = (uint16_t) state->a - (uint16_t) state->b - state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SBB B + case 0x99: { uint16_t res = (uint16_t) state->a - (uint16_t) state->c - state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SBB C + case 0x9a: { uint16_t res = (uint16_t) state->a - (uint16_t) state->d - state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SBB D + case 0x9b: { uint16_t res = (uint16_t) state->a - (uint16_t) state->e - state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SBB E + case 0x9c: { uint16_t res = (uint16_t) state->a - (uint16_t) state->h - state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SBB H + case 0x9d: { uint16_t res = (uint16_t) state->a - (uint16_t) state->l - state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SBB L + case 0x9e: //SBB M + { + uint16_t res = (uint16_t) state->a - (uint16_t) ReadFromHL(state) - state->cc.cy; + ArithFlagsA(state, res); + state->a=(res&0xff); + } break; + case 0x9f: { uint16_t res = (uint16_t) state->a - (uint16_t) state->a - state->cc.cy; ArithFlagsA(state, res); state->a=(res&0xff); } break; //SBB A + + case 0xa0: state->a = state->a & state->b; LogicFlagsA(state); break; + case 0xa1: state->a = state->a & state->c; LogicFlagsA(state); break; + case 0xa2: state->a = state->a & state->d; LogicFlagsA(state); break; + case 0xa3: state->a = state->a & state->e; LogicFlagsA(state); break; + case 0xa4: state->a = state->a & state->h; LogicFlagsA(state); break; + case 0xa5: state->a = state->a & state->l; LogicFlagsA(state); break; + case 0xa6: state->a = state->a & ReadFromHL(state); LogicFlagsA(state); break; + case 0xa7: state->a = state->a & state->a; LogicFlagsA(state); break; + + case 0xa8: state->a = state->a ^ state->b; LogicFlagsA(state); break; + case 0xa9: state->a = state->a ^ state->c; LogicFlagsA(state); break; + case 0xaa: state->a = state->a ^ state->d; LogicFlagsA(state); break; + case 0xab: state->a = state->a ^ state->e; LogicFlagsA(state); break; + case 0xac: state->a = state->a ^ state->h; LogicFlagsA(state); break; + case 0xad: state->a = state->a ^ state->l; LogicFlagsA(state); break; + case 0xae: state->a = state->a ^ ReadFromHL(state); LogicFlagsA(state); break; + case 0xaf: state->a = state->a ^ state->a; LogicFlagsA(state); break; + + case 0xb0: state->a = state->a | state->b; LogicFlagsA(state); break; + case 0xb1: state->a = state->a | state->c; LogicFlagsA(state); break; + case 0xb2: state->a = state->a | state->d; LogicFlagsA(state); break; + case 0xb3: state->a = state->a | state->e; LogicFlagsA(state); break; + case 0xb4: state->a = state->a | state->h; LogicFlagsA(state); break; + case 0xb5: state->a = state->a | state->l; LogicFlagsA(state); break; + case 0xb6: state->a = state->a | ReadFromHL(state); LogicFlagsA(state); break; + case 0xb7: state->a = state->a | state->a; LogicFlagsA(state); break; + + case 0xb8: { uint16_t res = (uint16_t) state->a - (uint16_t) state->b; ArithFlagsA(state, res); } break; //CMP B + case 0xb9: { uint16_t res = (uint16_t) state->a - (uint16_t) state->c; ArithFlagsA(state, res); } break; //CMP C + case 0xba: { uint16_t res = (uint16_t) state->a - (uint16_t) state->d; ArithFlagsA(state, res); } break; //CMP D + case 0xbb: { uint16_t res = (uint16_t) state->a - (uint16_t) state->e; ArithFlagsA(state, res); } break; //CMP E + case 0xbc: { uint16_t res = (uint16_t) state->a - (uint16_t) state->h; ArithFlagsA(state, res); } break; //CMP H + case 0xbd: { uint16_t res = (uint16_t) state->a - (uint16_t) state->l; ArithFlagsA(state, res); } break; //CMP L + case 0xbe: { uint16_t res = (uint16_t) state->a - (uint16_t) ReadFromHL(state); ArithFlagsA(state, res); } break; //CMP L + case 0xbf: { uint16_t res = (uint16_t) state->a - (uint16_t) state->a; ArithFlagsA(state, res); } break; //CMP A + + case 0xc0: //RNZ + if (state->cc.z == 0) + { + state->pc = state->memory[state->sp] | (state->memory[state->sp+1]<<8); + state->sp += 2; + } + break; + + case 0xc1: //POP B + Pop(state, &state->b, &state->c); + break; + case 0xc2: //JNZ address + if (0 == state->cc.z) + state->pc = (opcode[2] << 8) | opcode[1]; + else + state->pc += 2; + break; + case 0xc3: //JMP address + state->pc = (opcode[2] << 8) | opcode[1]; + break; + case 0xc4: //CNZ adr + if (state->cc.z == 0) + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } + else + state->pc += 2; + break; + + case 0xc5: //PUSH B + Push(state, state->b, state->c); + break; + case 0xc6: //ADI byte + { + uint16_t x = (uint16_t) state->a + (uint16_t) opcode[1]; + FlagsZSP(state, x&0xff); + state->cc.cy = (x > 0xff); + state->a = x&0xff; + state->pc++; + } + break; + case 0xc7: //RST 0 + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = 0x0000; + } + break; + case 0xc8: //RZ + if (state->cc.z) + { + state->pc = state->memory[state->sp] | (state->memory[state->sp+1] << 8); + state->sp += 2; + } + break; + case 0xc9: //RET + state->pc = state->memory[state->sp] | (state->memory[state->sp+1] << 8); + state->sp += 2; + break; + case 0xca: //JZ adr + if (state->cc.z) + state->pc = (opcode[2] << 8) | opcode[1]; + else + state->pc += 2; + break; + case 0xcb: UnimplementedInstruction(state); break; + case 0xcc: //CZ adr + if (state->cc.z == 1) + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; 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) { + } + else + state->pc += 2; + break; + case 0xcd: //CALL address + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } + break; + case 0xce: //ACI byte + { + uint16_t x = state->a + opcode[1] + state->cc.cy; + FlagsZSP(state, x&0xff); + state->cc.cy = (x > 0xff); + state->a = x & 0xff; + state->pc++; + } + break; + case 0xcf: //RST 1 + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = 0x0008; + } + 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 + Pop(state, &state->d, &state->e); + break; + case 0xd2: //JNC + if (state->cc.cy == 0) + state->pc = (opcode[2] << 8) | opcode[1]; + else + state->pc += 2; + break; + case 0xd3: //OUT d8 + machineOut(state, opcode[1], state->a); + state->pc++; + break; + case 0xd4: //CNC adr + if (state->cc.cy == 0) + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } + else + state->pc += 2; + break; + case 0xd5: //PUSH D + Push(state, state->d, state->e); + break; + case 0xd6: //SUI byte + { + uint8_t x = state->a - opcode[1]; + FlagsZSP(state, x&0xff); + state->cc.cy = (state->a < opcode[1]); + state->a = x; + state->pc++; + } + break; + case 0xd7: //RST 2 + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = 0x10; + } + break; + case 0xd8: //RC + 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]; - state->sp += 2; - break; - case 0xd2: // JNC adress - { - if (0 == state->cc.cy) { - state->pc = (opcode[2] << 8) | opcode[1]; - } else { - state->pc += 2; - } - } - break; - case 0xd3: // OUT byte - { - uint8_t port = opcode[1]; - machineOut(state, port, 0x00); // PROBLEM: We need to pass a value to machineOUT - 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) { - state->pc = state->memory[state->sp] | (state->memory[state->sp+1] << 8); - state->sp += 2; - } - } - break; - case 0xda: // JC adress - { - if (state->cc.cy != 0) { - state->pc = (opcode[2] << 8) | opcode[1]; - } else { - state->pc += 2; - } - } - break; - case 0xdb: // IN byte - { - uint8_t port = opcode[1]; - state->a = machineIn(state, port); - 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) + } + break; + case 0xd9: UnimplementedInstruction(state); break; + case 0xda: //JC + if (state->cc.cy != 0) + state->pc = (opcode[2] << 8) | opcode[1]; + else + state->pc += 2; + break; + case 0xdb: //IN d8 + state->a = machineIn(state, opcode[1]); //Check if this works + state->pc++; + break; + case 0xdc: //CC adr + if (state->cc.cy != 0) + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } + else + state->pc += 2; + break; + case 0xdd: UnimplementedInstruction(state); break; + case 0xde: //SBI byte + { + uint16_t x = state->a - opcode[1] - state->cc.cy; + FlagsZSP(state, x&0xff); + state->cc.cy = (x > 0xff); + state->a = x & 0xff; + state->pc++; + } + break; + case 0xdf: //RST 3 + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = 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 + case 0xe1: //POP H + Pop(state, &state->h, &state->l); + break; + case 0xe2: //JPO + if (state->cc.p == 0) + state->pc = (opcode[2] << 8) | opcode[1]; + else + state->pc += 2; + break; + case 0xe3: //XTHL + { + uint8_t h = state->h; + uint8_t l = state->l; state->l = state->memory[state->sp]; - state->h = state->memory[state->sp+1]; - state->sp += 2; - break; - case 0xe2: // JPO adress - { - if (0 == state->cc.p) { - state->pc = (opcode[2] << 8) | opcode[1]; - } else { - state->pc += 2; - } - } - break; - case 0xe3: // XTHL - { - uint8_t tmp = state->l; - state->l = state->memory[state->sp]; - state->memory[state->sp] = tmp; - tmp = state->h; - state->h = state->memory[state->sp+1]; - state->memory[state->sp+1] = tmp; - } - break; - - case 0xe4: // CPO adress - { - if (0 == state->cc.p) { - 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 0xe5: // PUSH H - state->memory[state->sp-1] = state->h; - state->memory[state->sp-2] = state->l; - state->sp -= 2; - break; - case 0xe6: // ANI byte - { - uint8_t x = state->a & opcode[1]; - state->cc.z = (x == 0); - state->cc.s = (0x80 == (x & 0x80)); - state->cc.cy = 0; - state->cc.p = parity(x, 8); - state->pc++; - } - break; - case 0xe7: // RST 4 - { - 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 = 0x20; - } - break; - case 0xe8: // RPE - { - if (0 != state->cc.p) { - state->pc = state->memory[state->sp] | (state->memory[state->sp+1] << 8); - state->sp += 2; - } - } - break; - case 0xe9: // PCHL - state->pc = (state->h << 8) | state->l; + state->h = state->memory[state->sp+1]; + WriteMem(state, state->sp, l ); + WriteMem(state, state->sp+1, h ); + } break; - case 0xea: // JPE - if (state->cc.p != 0) + case 0xe4: //CPO adr + if (state->cc.p == 0) + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; state->pc = (opcode[2] << 8) | opcode[1]; + } else state->pc += 2; break; - case 0xeb: // XCHG - { - uint8_t tmp = state->h; - state->h = state->d; - state->d = tmp; - tmp = state->l; - state->l = state->e; - state->e = tmp; - } - break; - case 0xec: // CPE Adress - { - if (state->cc.p != 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 0xee: // XRI Data - { - uint8_t x = state->a ^opcode[1]; - state->cc.z = (x == 0); - state->cc.s = (0x80 == (x & 0x80)); - state->cc.p = parity(x, 8); - state->cc.cy = 0; - state->a = x; - state->pc++; - } - break; - case 0xef: // RST 5 - { - 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 = 0x28; - } - break; - case 0xf0: // RP - { - if (state->cc.s == 0) { - state->pc = state->memory[state->sp] | (state->memory[state->sp+1]<<8); - state->pc += 2; - } - } - break; - case 0xf1: // POP PSW - { - state->a = state->memory[state->sp+1]; - uint8_t psw = state->memory[state->sp]; - state->cc.z = (0x01 == (psw & 0x01)); - state->cc.s = (0x02 == (psw & 0x02)); - state->cc.p = (0x04 == (psw & 0x04)); - state->cc.cy = (0x08 == (psw & 0x08)); - state->cc.ac = (0x10 == (psw & 0x10)); - state->sp += 2; - } - break; - case 0xf2: // JP Adress - { - if (state->cc.s == 0) { - state->pc = (opcode[2] << 8) | opcode[1]; - } else { - state->pc += 2; - } - } - case 0xf3: // DI - state->int_enable = 0; - break; - case 0xf4: // CP - { - 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 0xf5: // PUSH PSW - state->memory[state->sp-1] = state->a; - 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); - - 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) + case 0xe5: //PUSH H + Push(state, state->h, state->l); + break; + case 0xe6: //ANI byte + { + state->a = state->a & opcode[1]; + LogicFlagsA(state); + state->pc++; + } + break; + case 0xe7: //RST 4 + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = 0x20; + } + break; + case 0xe8: //RPE + if (state->cc.p != 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); + case 0xe9: //PCHL + state->pc = (state->h << 8) | state->l; break; - case 0xfa: // JM - if (state->cc.s != 0) + case 0xea: //JPE + if (state->cc.p != 0) + state->pc = (opcode[2] << 8) | opcode[1]; + else + state->pc += 2; + break; + case 0xeb: //XCHG + { + uint8_t save1 = state->d; + uint8_t save2 = state->e; + state->d = state->h; + state->e = state->l; + state->h = save1; + state->l = save2; + } + break; + case 0xec: //CPE adr + if (state->cc.p != 0) + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } + else + state->pc += 2; + break; + case 0xed: UnimplementedInstruction(state); break; + case 0xee: //XRI data + { + uint8_t x = state->a ^ opcode[1]; + FlagsZSP(state, x); + state->cc.cy = 0; //data book says clear cy + state->a = x; + state->pc++; + } + break; + case 0xef: //RST 5 + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = 0x28; + } + break; + + case 0xf0: //RP + if (state->cc.s == 0) + { + state->pc = state->memory[state->sp] | (state->memory[state->sp+1]<<8); + state->sp += 2; + } + break; + case 0xf1: //POP PSW + Pop(state, &state->a,(unsigned char*) &state->cc); + break; + case 0xf2: + 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]; - state->cc.z = (x == 0); - state->cc.s = (0x80 == (x & 0x80)); - state->cc.cy = (state->a < opcode[1]); - state->cc.p = parity(x, 8); - 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; + case 0xf3: state->int_enable = 0; break; + case 0xf4: //CP + if (state->cc.s == 0) + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } + else + state->pc += 2; + break; + + case 0xf5: //PUSH PSW + Push(state, state->a, *(unsigned char*)&state->cc); + break; + + case 0xf6: //ORI byte + { + //AC set if lower nibble of h was zero prior to dec + uint8_t x = state->a | opcode[1]; + FlagsZSP(state, x); + state->cc.cy = 0; + state->a = x; + state->pc++; + } + break; + case 0xf7: //RST 6 + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = 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: state->int_enable = 1; break; + case 0xfc: //CM + if (state->cc.s != 0) + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = (opcode[2] << 8) | opcode[1]; + } + else + state->pc += 2; + break; + + case 0xfd: UnimplementedInstruction(state); break; + case 0xfe: //CPI byte + { + uint8_t x = state->a - opcode[1]; + FlagsZSP(state, x); + state->cc.cy = (state->a < opcode[1]); + state->pc++; + } + break; + case 0xff: //RST 7 + { + uint16_t ret = state->pc+2; + WriteMem(state, state->sp-1, (ret >> 8) & 0xff); + WriteMem(state, state->sp-2, (ret & 0xff)); + state->sp = state->sp - 2; + state->pc = 0x38; + } + break; + default: UnimplementedInstruction(state); break; } - printState(state); + //printState(state); return cycles8080[*opcode]; } @@ -1735,48 +1564,6 @@ void read_Space_Invaders_ROM(State8080* state, const char* filename, int offset) fclose(file); } -void keyDown(uint8_t key) -{ - switch(key) { - case 0: // COIN - in_port |= 0x1; - break; - case 1: // LEFT - in_port |= 0x20; - break; - case 2: // RIGHT - in_port |= 0x40; - break; - case 3: // FIRE - in_port |= 0x10; - break; - case 4: // START - in_port |= 0x04; - break; - } -} - -void keyUp( uint8_t key) -{ - switch(key) { - case 0: // COIN - in_port &= ~0x1; - break; - case 1: // LEFT - in_port &= ~0x20; - break; - case 2: // RIGHT - in_port &= ~0x40; - break; - case 3: // FIRE - in_port &= ~0x10; - break; - case 4: // START - in_port &= ~0x04; - break; - } -} - typedef struct cpu_data { char done; int total_cycles_count; @@ -1791,12 +1578,14 @@ void *cpu(void* arg) { State8080* state = cpu->state; int counter; + sleep(2); + 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 + //usleep(1); // 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 @@ -1813,15 +1602,12 @@ void *cpu(void* arg) { } } -// ===== GTK GRAPHICS ===== +//===== GTK GRAPHICS ===== 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 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++) { for (int j = 0; j < 32; j++) { uint8_t byte = bitmap[i*32 + j]; @@ -1830,38 +1616,40 @@ static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { int x = i; // swap x and y int y = 255 - (j*8 + p); // flip the y-coordinate if (x >= 0 && x < 256 && y >= 0 && y < 256) { // Check bounds - video[y*256 + x] = pixel; + if (pixel) { + 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); } } } } - - // Rendering the graphics - 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 - } 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); } void on_about_clicked(GtkToolButton *toolbutton, gpointer user_data) { GtkWidget *dialog = gtk_about_dialog_new(); + GtkWidget *image = gtk_image_new_from_file("space.png"); + + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); + gtk_box_pack_start(GTK_BOX(box), image, TRUE, TRUE, 0); + 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_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), "8080.ico"); + + GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + gtk_box_pack_start(GTK_BOX(content_area), box, TRUE, TRUE, 0); + + gtk_widget_show_all(box); 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) @@ -1884,6 +1672,19 @@ void on_size_changed(GtkComboBox *combo_box, gpointer user_data) { g_free(text); } +gboolean close_splash_screen(gpointer data) { + GtkWidget *splash_screen = (GtkWidget*)data; + gtk_widget_hide(splash_screen); + return FALSE; +} + +gboolean open_screen(gpointer data) { + GtkWidget *window = (GtkWidget*)data; + gtk_widget_show_all(window); + return FALSE; +} + + int main (int argc, char *argv[]) { @@ -1913,12 +1714,23 @@ int main (int argc, char *argv[]) { g_signal_connect(window, "key-release-event", G_CALLBACK(on_key_release), NULL); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + // Splashscreen + + GtkWidget *splash_screen = gtk_window_new(GTK_WINDOW_POPUP); + gtk_window_set_position(GTK_WINDOW(splash_screen), GTK_WIN_POS_CENTER); + GtkWidget *image = gtk_image_new_from_file("space.png"); + gtk_container_add(GTK_CONTAINER(splash_screen), image); + gtk_widget_show_all(splash_screen); + g_timeout_add(2000, close_splash_screen, splash_screen); + g_timeout_add(2002, open_screen, window); + // 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(); @@ -1935,6 +1747,10 @@ int main (int argc, char *argv[]) { gtk_toolbar_insert(GTK_TOOLBAR(toolbar), about, -1); g_signal_connect(about, "clicked", G_CALLBACK(on_about_clicked), NULL); + gtk_widget_set_can_focus(GTK_WIDGET(combo_box), FALSE); + gtk_widget_set_can_focus(GTK_WIDGET(about), FALSE); + + // Drawing area init bitmap = &(state->memory[0x2400]); GtkWidget *drawing_area = gtk_drawing_area_new(); @@ -1949,7 +1765,7 @@ int main (int argc, char *argv[]) { - gtk_widget_show_all(window); + //gtk_widget_show_all(window); // CPU-init cpu_data *cpu_eco = malloc(sizeof(cpu_data)); @@ -1964,8 +1780,9 @@ int main (int argc, char *argv[]) { // Main GTK Loop - g_timeout_add(200, update_ui, drawing_area); + g_timeout_add(80, update_ui, drawing_area); gtk_main(); + cpu_eco->done = 1; pthread_join(pid, NULL); free(state->memory); free(state); diff --git a/space.png b/space.png new file mode 100644 index 0000000..692943d Binary files /dev/null and b/space.png differ