Graphics implemented! :D

This commit is contained in:
Luxdragon 2024-01-19 20:20:17 +01:00
parent 6eddacbba2
commit 37ce16ca8a

View file

@ -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<<p)))
*p1 = 1;
else
*p1 = 0;
p1-=224; //next line
// //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);
// uint8_t *p1 = (uint8_t*)(&video[offset]);
// for (int p=0; p<8; p++)
// {
// if ( 0!= (pix & (1<<p)))
// *p1 = 1;
// else
// *p1 = 0;
// p1-=224; //next line
// }
// }
// }
// 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 = 1;
// uint8_t *video = malloc(sizeof(uint8_t) * 224 * 256);
// // 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 >> (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);