From 37ce16ca8a998dccab48795a666025e74de488a3 Mon Sep 17 00:00:00 2001 From: Luxdragon Date: Fri, 19 Jan 2024 20:20:17 +0100 Subject: [PATCH] Graphics implemented! :D --- emulator_shell.c | 722 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 578 insertions(+), 144 deletions(-) diff --git a/emulator_shell.c b/emulator_shell.c index 8b92eb9..fef0e10 100644 --- a/emulator_shell.c +++ b/emulator_shell.c @@ -556,6 +556,13 @@ int emulate8080(State8080* state) { 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; @@ -608,6 +615,10 @@ int emulate8080(State8080* state) { 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; @@ -627,22 +638,31 @@ int emulate8080(State8080* state) { case 0x21: // LXI H, word { - state->h = opcode[2]; - state->l = opcode[1]; - state->pc += 2; - break; + 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++; - }} + state->l++; + if (state->l == 0) { + state->h++; + } + } break; case 0x26: // MVI H, byte { - state->h = opcode[1]; - state->pc++; + state->h = opcode[1]; + state->pc++; } break; case 0x27: // DAA @@ -661,22 +681,62 @@ int emulate8080(State8080* state) { 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); + 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; + uint16_t adress = (opcode[2]<<8) | (opcode[1]); + state->memory[adress] = state->a; + state->pc += 2; } break; @@ -702,9 +762,9 @@ int emulate8080(State8080* state) { break; case 0x36: // MVI M, byte { - uint16_t adress = (state->h <<8) | (state->l); - state->memory[adress] = opcode[1]; - state->pc++; + uint16_t adress = (state->h <<8) | (state->l); + state->memory[adress] = opcode[1]; + state->pc++; } break; @@ -714,9 +774,9 @@ int emulate8080(State8080* state) { case 0x3a: // LDA adress { - uint16_t adress = (opcode[2]<<8) | (opcode[1]); - state->a = state->memory[adress]; - state->pc += 2; + uint16_t adress = (opcode[2]<<8) | (opcode[1]); + state->a = state->memory[adress]; + state->pc += 2; } break; case 0x3d: // DCR A @@ -740,22 +800,147 @@ int emulate8080(State8080* state) { 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]; + 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]; + 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]; + 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 @@ -763,52 +948,63 @@ int emulate8080(State8080* state) { break; case 0x77: // MOV M, A { - uint16_t adress = (state->h<<8) | (state->l); - state->memory[adress] = state->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]; + 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; + 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; + 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)); + uint8_t x = state->a; + state->a = (state->cc.cy << 7) | (x >> 1); + state->cc.cy = (1 == (x & 1)); } break; @@ -828,6 +1024,23 @@ int emulate8080(State8080* state) { state->cc.cy = 0; 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 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 0xc0: // RNZ { if (state->cc.z == 0) { @@ -853,6 +1066,19 @@ int emulate8080(State8080* state) { 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; @@ -861,12 +1087,12 @@ int emulate8080(State8080* state) { 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++; + 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; @@ -894,11 +1120,11 @@ int emulate8080(State8080* state) { case 0xcd: // CALL adress { - 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]; + 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]; } break; case 0xd1: // POP D @@ -917,9 +1143,9 @@ int emulate8080(State8080* state) { 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++; + uint8_t port = opcode[1]; + machineOut(state, port, 0x00); // PROBLEM: We need to pass a value to machineOUT + state->pc++; } break; case 0xd5: // PUSH D @@ -927,6 +1153,14 @@ int emulate8080(State8080* state) { state->memory[state->sp-2] = state->e; state->sp -= 2; 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) { @@ -938,9 +1172,9 @@ int emulate8080(State8080* state) { break; case 0xdb: // IN byte { - uint8_t port = opcode[1]; - state->a = machineIn(state, port); - state->pc++; + uint8_t port = opcode[1]; + state->a = machineIn(state, port); + state->pc++; } break; case 0xe1: // POP H @@ -948,50 +1182,167 @@ int emulate8080(State8080* state) { 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 0x2f: // CMA (NOT) - state->a = ~state->a; - 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++; + 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; + break; + 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 tmp = state->h; - state->h = state->d; - state->d = tmp; - tmp = state->l; - state->l = state->e; - state->e = tmp; + 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; + 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)); @@ -1004,12 +1355,12 @@ int emulate8080(State8080* state) { 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++; + 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; @@ -1103,43 +1454,114 @@ typedef struct cpu_data { // ===== GTK GRAPHICS ===== -static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { - int x, y; - int upscaleFactor = 1; - uint8_t *video = malloc(sizeof(uint8_t) * 224 * 256 * 4); - - //ROTATION ALGORITHM - for (int i=0; i< 224; i++) - { - for (int j = 0; j < 256; j+= 8) - { - int p; - //Read the first 1-bit pixel - // divide by 8 because there are 8 pixels - // in a byte - unsigned char pix = bitmap[(i*(256/8)) + j/8]; +// static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { + // int upscaleFactor = 1; + // uint8_t *video = malloc(sizeof(uint8_t) * 224 * 256); + // //ROTATION ALGORITHM + // for (int i=0; i< 224; i++) + // { + // for (int j = 0; j < 256; j+= 8) + // { + // //Read the first 1-bit pixel + // // divide by 8 because there are 8 pixels + // // in a byte + // uint8_t pix = bitmap[(i*(256/8)) + j/8]; - //That makes 8 output vertical pixels - // we need to do a vertical flip - // so j needs to start at the last line - // and advance backward through the buffer - int offset = (255-j)*(224*4) + (i*4); - unsigned int *p1 = (unsigned int*)(&video[offset]); - for (p=0; p<8; p++) - { - if ( 0!= (pix & (1<> (7 - p)) & 1; // flip the bit order +// int x = 255 - (j*8 + p); // flip the x-coordinate +// int y = i; +// video[y*256 + x] = pixel; +// } +// } +// } + +// // Rendering the graphics +// for (int x = 0; x < 256; x++) { +// for (int y = 0; y < 224; y++) { +// if (video[y*256 + x]) { +// cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); // Set color to white +// } else { +// cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); // Set color to black +// } + +// cairo_rectangle(cr, x * upscaleFactor, y * upscaleFactor, upscaleFactor, upscaleFactor); +// cairo_fill(cr); +// } +// } + +// free(video); +// } + +static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { + int upscaleFactor = 2; + uint8_t *video = malloc(sizeof(uint8_t) * 256 * 256); // Adjusted size + // Clear the drawing area + cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); + cairo_paint(cr); + + // Copying the bitmap to video output + for (int i = 0; i < 224; i++) { + for (int j = 0; j < 32; j++) { + uint8_t byte = bitmap[i*32 + j]; + for (int p = 0; p < 8; p++) { + int pixel = (byte >> p) & 1; // flip the bit order within each byte + 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; + } } } } - // RENDERING GRAPHICS - - for (x = 0; x < 224; x++) { - for (y = 0; y < 256; y++) { - if (video[y * 224 + x]) { + + // Rendering the graphics + for (int x = 0; x < 256; 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 @@ -1149,9 +1571,11 @@ static void draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data) { cairo_fill(cr); } } + free(video); } + void *cpu(void* arg) { cpu_data *cpu = (cpu_data*) arg; char done = cpu->done; @@ -1163,8 +1587,8 @@ void *cpu(void* arg) { cpu->total_cycles_count += counter; printf("Total cycles: %d\n", cpu->total_cycles_count); - usleep(counter / 2); // EMULATION OF THE PROCESSOR ŠPEED - if ((cpu->total_cycles_count > 16600) && (state->int_enable)) //1/60 second has elapsed + //usleep(counter / 2); // EMULATION OF THE PROCESSOR ŠPEED + if ((cpu->total_cycles_count > 16000) && (state->int_enable)) //1/60 second has elapsed { //redraw screen() will be handeled by the gtk_main() function if (which_interrupt == 2) { @@ -1181,9 +1605,19 @@ void *cpu(void* arg) { } +gboolean update_ui(gpointer data) { + // Seems like GTK is not thread safe + // we fix it with update_ui using gtk_main_iteration_do(FALSE) + GtkWidget *drawing_area = (GtkWidget*)data; + gtk_widget_queue_draw(drawing_area); + while (gtk_events_pending()) + gtk_main_iteration_do(FALSE); + return TRUE; +} + int main (int argc, char *argv[]) { - // EMULATOR INIT + // Emulator init State8080 *state = (State8080*) calloc(1, sizeof(State8080)); //memset obsolte with calloc state->cc.z = 1; @@ -1193,23 +1627,23 @@ int main (int argc, char *argv[]) { state->cc.ac = 1; state->int_enable = 1; state->pc = 0; - state->memory = malloc(0x10000); + state->memory = calloc(0x10000, 1); read_Space_Invaders_ROM(state, "ROM/invaders.h", 0); read_Space_Invaders_ROM(state, "ROM/invaders.g", 0x800); read_Space_Invaders_ROM(state, "ROM/invaders.f", 0x1000); read_Space_Invaders_ROM(state, "ROM/invaders.e", 0x1800); - // GTK INIT + // 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), "Lux8080-Emulator"); + gtk_window_set_title(GTK_WINDOW(window), "Turi's Super Duper Emulatinator"); g_signal_connect(window, "key-press-event", G_CALLBACK(on_key_press), NULL); g_signal_connect(window, "key-release-event", G_CALLBACK(on_key_release), NULL); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); - // DRAWING AREA INIT + // Drawing area init bitmap = &(state->memory[0x2400]); GtkWidget *drawing_area = gtk_drawing_area_new(); gtk_widget_set_app_paintable(drawing_area, TRUE); @@ -1217,20 +1651,20 @@ int main (int argc, char *argv[]) { g_signal_connect(drawing_area, "draw", G_CALLBACK(draw_callback), NULL); gtk_widget_show_all(window); - // CPU INIT + // CPU-init cpu_data *cpu_eco = malloc(sizeof(cpu_data)); cpu_eco->state = state; cpu_eco->drawing_area = drawing_area; cpu_eco->done = 0; cpu_eco->total_cycles_count = 0; - // PTHREAD + // Pthread pthread_t pid; pthread_create(&pid, NULL, cpu, (void*) cpu_eco); - //MAIN LOOP & TERMINATION //gtk_widget_queue_draw - g_timeout_add(16, (GSourceFunc)gtk_widget_queue_draw, drawing_area); + // Main GTK Loop + g_timeout_add(200, update_ui, drawing_area); gtk_main(); pthread_join(pid, NULL); free(state->memory);