// This file uses the 8080 emulator to run the test suite (roms in cpu_tests // directory). It uses a simple array as memory. #include #include #include #include #include "8080/i8080.h" // memory callbacks #define MEMORY_SIZE 0x10000 static uint8_t* memory = NULL; static bool test_finished = 0; static uint8_t rb(void* userdata, const uint16_t addr) { return memory[addr]; } static void wb(void* userdata, const uint16_t addr, const uint8_t val) { memory[addr] = val; } uint16_t dma_addr; uint8_t cur_disk = 'Z'-'A'; char filename[16]; void filename_from_fcb(void* userdata, uint16_t addr) { i8080* const c = (i8080*) userdata; memset(&filename, 0, sizeof(filename)); char* ptr = filename; while(rb(c, addr) != '.' && rb(c, addr) > ' ') { *ptr++ = rb(c, addr++); } if (rb(c, addr) == '.') { addr++; while(rb(c, addr) > ' ') { *ptr++ = rb(c, addr++); } } } void filename_to_fcb(void* userdata, uint16_t addr) { } static uint8_t port_in(void* userdata, uint8_t port) { i8080* const c = (i8080*) userdata; uint16_t de = (c->d << 8) | c->e; switch(c->c) { case 2: printf("%c", c->e); break; case 9: do { printf("%c", rb(c, de++)); } while(rb(c, de) != '$'); break; case 15: filename_from_fcb(userdata, de); printf("filename: %s\n", filename); exit(1); break; case 25: c->a = cur_disk; break; case 26: dma_addr = (c->d << 8) | c->e; break; default: i8080_debug_output(c); fprintf(stderr, "fatal: unknown syscall C=%02Xh (%d)\n", c->c, c->c); exit(255); } return c->a; } static int load_file(const char* filename, uint16_t addr) { FILE* f = fopen(filename, "rb"); if (f == NULL) { fprintf(stderr, "error: can't open file '%s'.\n", filename); return 1; } // file size check: fseek(f, 0, SEEK_END); size_t file_size = ftell(f); rewind(f); if (file_size + addr >= MEMORY_SIZE) { fprintf(stderr, "error: file %s can't fit in memory.\n", filename); return 1; } // copying the bytes in memory: size_t result = fread(&memory[addr], sizeof(uint8_t), file_size, f); if (result != file_size) { fprintf(stderr, "error: while reading file '%s'\n", filename); return 1; } fclose(f); return 0; } int main(int argc, char** argv) { memory = malloc(MEMORY_SIZE); if (memory == NULL) { return 255; } argc--; if (!argc) { fprintf(stderr, "No filename given\n"); } i8080 cpu; i8080_init(&cpu); cpu.userdata = &cpu; cpu.read_byte = rb; cpu.write_byte = wb; cpu.port_in = port_in; memset(memory, 0, MEMORY_SIZE); if (load_file(argv[0], 0x100) != 0) { return 255; } cpu.pc = 0x100; // inject "hlt" at 0x0000 memory[0x0000] = 0x76; // inject "in a,0" at 0x0005 (cpm syscall) memory[0x0005] = 0xDB; memory[0x0006] = 0x00; memory[0x0007] = 0xC9; while (!cpu.halted) { // i8080_debug_output(&cpu); i8080_step(&cpu); } free(memory); return cpu.a; }