From ba3a89628a3080a64e5068f6fd21149a31281e92 Mon Sep 17 00:00:00 2001 From: Luxdragon Date: Mon, 8 Jan 2024 18:07:28 +0100 Subject: [PATCH] DEBUG (major bug found) --- emulator_shell.c | 189 ++++++++++++++++++++++++++++++----------------- 1 file changed, 120 insertions(+), 69 deletions(-) diff --git a/emulator_shell.c b/emulator_shell.c index 6f04379..9bf21cc 100644 --- a/emulator_shell.c +++ b/emulator_shell.c @@ -2,40 +2,12 @@ #include #include // for the uintx_t's #include // for sleep +#include // for memset // gcc emulator_shell.c -o emulator -typedef struct buffer { - unsigned char* buffer; - int length; -} buffer; - -buffer* read_file(char** argv) { - FILE* file = fopen(argv[1], "rb"); - if (file == NULL) { - printf("Issue opening the file.\n"); - return NULL; - } - - //Get the file size and read it into a memory buffer - fseek(file, 0L, SEEK_END); - int fsize = ftell(file); - fseek(file, 0L, SEEK_SET); - - buffer *b = malloc(sizeof(buffer)); - b->buffer=malloc(fsize); - b->length=fsize; - - fread(b->buffer, fsize, 1, file); - fclose(file); - - return b; -} - -int disassemble8080(buffer* b, int pc) { - unsigned char *code = &(b->buffer[pc]); +int disassemble8080(unsigned char* code) { int opbytes = 1; - printf("%04x ", pc); switch (*code) { case 0x00: printf("NOP"); break; @@ -344,7 +316,8 @@ typedef struct ConditionCodes { uint8_t cy:1; uint8_t ac:1; uint8_t pad:3; -} ConditionCodes; +} ConditionCodes; + typedef struct State8080 { uint8_t a; @@ -357,7 +330,7 @@ typedef struct State8080 { uint16_t sp; uint16_t pc; uint8_t *memory; - struct ConditionCodes cc; + ConditionCodes cc; uint8_t int_enable; } State8080; @@ -382,7 +355,10 @@ int parity(int x, int size) int emulate8080(State8080* state) { unsigned char *opcode = &(state->memory[state->pc]); - disassemble8080(buff, pc); + printf("%04x ", state->pc); + + disassemble8080(opcode); + state->pc++; switch(*opcode) { case 0x00: break; // NOP does nothing @@ -392,68 +368,82 @@ int emulate8080(State8080* state) { state->pc += 2; break; case 0x05: // DCR B + { uint8_t res = state->b - 1; state->b = res; state->cc.z = (res == 0); - state->cc.s = ((res & 0x80) != 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 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 & 0xff) >> 8; + state->h = (result & 0xff00) >> 8; state->l = result & 0xff; - state->cc.cy = ((res & 0xffff0000) != 0); + state->cc.cy = ((result & 0xffff0000) != 0); + } break; case 0x0d: // DCR C + { uint8_t res = state->c - 1; state->c = res; state->cc.z = (res == 0); - state->cc.s = ((res & 0x80) != 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 += 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 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 & 0xff) >> 8; + 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 0x23: // INX H state->l++; if (state->l == 0) { @@ -462,38 +452,48 @@ int emulate8080(State8080* state) { break; case 0x26: // MVI H, byte state->h = opcode[1]; - state->pc += 1; + state->pc++; break; case 0x29: // DAD H - uint32_t h1 = (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); + { + 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 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[offset] = state->a; + state->memory[adress] = state->a; state->pc += 2; + } break; case 0x36: // MVI M, byte + { uint16_t adress = (state->h <<8) | (state->l); state->memory[adress] = opcode[1]; - state->pc += 1; + state->pc++; + } break; case 0x3a: // LDA adress + { uint16_t adress = (opcode[2]<<8) | (opcode[1]); state->a = state->memory[adress]; state->pc += 2; + } break; case 0x3e: // MVI A, byte state->a = opcode[1]; - state->pc += 1; + state->pc++; + break; case 0x41: // MOV B, C state->b = state->c; break; @@ -504,23 +504,31 @@ int emulate8080(State8080* state) { state->b = state->e; break; case 0x56: // MOV D, M + { uint16_t adress = (state->h<<8) | (state->l); state->d = state->memory[adress]; + } break; case 0x5e: // MOV E, M + { uint16_t adress = (state->h<<8) | (state->l); state->e = state->memory[adress]; + } break; case 0x66: // MOV H, M + { uint16_t adress = (state->h<<8) | (state->l); state->h = 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; @@ -532,19 +540,24 @@ int emulate8080(State8080* state) { state->a = state->h; break; case 0x7e: // MOV A, M + { uint16_t adress = (state->h<<8) | (state->l); state->a = state->memory[adress]; + } 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); @@ -552,17 +565,20 @@ int emulate8080(State8080* state) { 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 0xa7: // ANA A state->a &= state->a; state->cc.z = (state->a == 0); - state->cc.s = (0 != (state->a & 0x80)); + state->cc.s = (0x80 == (state->a & 0x80)); state->cc.p = parity(state->a, 8); state->cc.cy = 0; state->cc.ac = 0; @@ -570,7 +586,7 @@ int emulate8080(State8080* state) { case 0xaf: // XRA A state->a ^= state->a; state->cc.z = (state->a == 0); - state->cc.s = (0 != (state->a & 0x80)); + state->cc.s = (0x80 == (state->a & 0x80)); state->cc.p = parity(state->a, 8); state->cc.cy = 0; state->cc.ac = 0; @@ -582,7 +598,7 @@ int emulate8080(State8080* state) { break; case 0xc2: // JNZ adress - if (0 = state-> cc.z) { + if (0 == state-> cc.z) { state->pc = (opcode[2] << 8) | opcode[1]; } else { state->pc += 2; @@ -599,23 +615,27 @@ int emulate8080(State8080* state) { 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) != 0); + state->cc.s = ((state->a & 0x80) == 0x80); state->cc.cy = (state->a > 0xff); state->cc.p = parity(state->a & 0xff, 8); - state->pc += 1; + state->pc++; + } break; case 0xc9: // RET state->sp += 2; state->pc = (state->memory[state->sp+1] << 8) | state->memory[state->sp]; break; 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]; + } break; case 0xd1: // POP D state->e = state->memory[state->sp]; @@ -647,24 +667,29 @@ int emulate8080(State8080* state) { 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++; + } 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 0xf1: // POP PSW + { state->a = state->memory[state->sp+1]; uint8_t psw = state->memory[state->sp]; state->cc.z = (0x01 == (psw & 0x01)); @@ -673,6 +698,7 @@ int emulate8080(State8080* state) { state->cc.cy = (0x08 == (psw & 0x08)); state->cc.ac = (0x10 == (psw & 0x10)); state->sp += 2; + } break; case 0xf5: // PUSH PSW @@ -686,12 +712,14 @@ int emulate8080(State8080* state) { 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; default: unknownInstruction(state); break; @@ -701,35 +729,58 @@ int emulate8080(State8080* state) { printf("\tA $%02x B $%02x C $%02x D $%02x E $%02x H $%02x L $%02x SP %04x\n", state->a, state->b, state->c, state->d, state->e, state->h, state->l, state->sp); - state->pc+1; + } -int main (int argc, char** argv) { - - buffer* buff = read_file(argv); - if (buff == NULL) { - printf("Fatal error.\n"); - return 1; +void read_Space_Invaders_ROM(State8080* state, const char* filename, int offset) { + //Works exclusively with the memory system of Space Invaders + FILE* file = fopen(filename, "rb"); + if (file == NULL) { + printf("Issue opening the file.\n"); + exit(1); } + //Get the file size and read it into a memory buffer + fseek(file, 0L, SEEK_END); + int fsize = ftell(file); + fseek(file, 0L, SEEK_SET); + + uint8_t *buffer = &state->memory[offset]; + + fread(buffer, fsize, 1, file); + fclose(file); + +} + +int main (void) { //Initializations - ConditionCodes *cc = malloc(sizeof(ConditionCodes)); State8080 *state = (State8080*) malloc(sizeof(State8080)); memset(state, 0, sizeof(State8080)); - memset(cc, 0, sizeof(ConditionCodes)); - state->cc = cc; + state->cc.z = 1; + state->cc.s = 1; + state->cc.p = 1; + state->cc.cy = 0; + state->cc.ac = 1; state->pc = 0; - state->memory = (uint8_t*) buff->buffer; + state->memory = malloc(0x10000); + + 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); + + int i = 0; while (1) { //Show the command in the code - int a = disassemble8080(buff, state->pc); + printf("%d\t\t:", i); emulate8080(state); - sleep(0.5); + i++; + sleep(0.00001); } - - free(buff); + free(state->memory); + free(state); return 0; } \ No newline at end of file