16 #define MEM_SIZE 0x10000
17 uint8_t mem[MEM_SIZE];
19 // read and write are separated for I/O
21 uint8_t io_read[IO_SIZE];
22 uint8_t io_write[IO_SIZE];
24 int load_ihx(char *name) {
25 FILE *fp = fopen(name, "r");
31 int base = 0, entry_point = 0;
34 while (fgets(line, 0x100, fp)) {
35 for (char *p = line; *p; ++p)
42 fprintf(stderr, "garbage after EOF record: %s\n", line);
47 fprintf(stderr, "require colon: %s\n", line);
53 for (len = 0; len < 0x7f; ++len) {
54 char *p = line + 1 + len * 2;
65 buf[len] = (uint8_t)strtol(p, &q, 16);
68 fprintf(stderr, "not hex byte: %s\n", p);
74 fprintf(stderr, "empty line: %s\n", line);
79 for (int i = 0; i < len; ++i)
82 checksum -= buf[len - 1];
85 "checksum %02x, should be %02x\n",
94 fprintf(stderr, "incorrect length: %s\n", line);
98 int addr = (buf[1] << 8) | buf[2], end_addr;
102 end_addr = addr + len;
103 if (end_addr < addr || end_addr > MEM_SIZE) {
104 fprintf(stderr, "invalid load range: [0x%x, 0x%x)\n", addr, end_addr);
107 memcpy(mem + addr, buf + 4, len);
114 fprintf(stderr, "invalid extended linear address record: %s\n", line);
117 base = (buf[4] << 24) | (buf[5] << 16);
121 fprintf(stderr, "invalid start linear address record: %s\n", line);
124 entry_point = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
127 fprintf(stderr, "unknown record type: 0x%x\n", buf[3]);
132 fprintf(stderr, "no EOF record\n");
140 int bdos(int c, int de) {
148 while (mem[de] != '$') {
151 de = (de + 1) & 0xffff;
155 fprintf(stderr, "unimplemented BDOS call 0x%02x\n", c);
161 int read_byte(void *context, int addr) {
163 int data = mem[addr];
164 fprintf(stderr, "addr=%04x rd=%02x\n", addr, data);
171 void write_byte(void *context, int addr, int data) {
173 fprintf(stderr, "addr=%04x wr=%02x\n", addr, data);
178 int in_byte(void *context, int addr) {
181 int data = io_read[addr];
182 printf("io=%02x rd=%02x\n", addr, data);
185 return io_read[addr];
189 void out_byte(void *context, int addr, int data) {
192 printf("io=%02x wr=%02x\n", addr, data);
194 io_write[addr] = data;
198 uint8_t rb(void *userdata, uint16_t addr) {
199 return read_byte(NULL, addr);
202 void wb(void *userdata, uint16_t addr, uint8_t val) {
203 write_byte(NULL, addr, val);
206 uint8_t in(z80 *const z, uint8_t port) {
207 return in_byte(NULL, port);
210 void out(z80 *const z, uint8_t port, uint8_t val) {
211 out_byte(NULL, port, val);
215 int main(int argc, char **argv) {
217 printf("usage: %s image.ihx\n", argv[0]);
220 int entry_point = load_ihx(argv[1]);
222 mem[5] = 0xc9; // ret, for bdos emulation
223 mem[6] = 0xff; // memory top, lo byte
224 mem[7] = 0xff; // memory top, hi byte
233 cpu.pc = entry_point;
239 "pc=%04x af=%04x bc=%04x de=%04x hl=%04x sp=%04x ix=%04x iy=%04x cf=%d nf=%d pvf=%d hf=%d zf=%d sf=%d\n",
250 cpu.c | (cpu.b << 8),
251 cpu.e | (cpu.d << 8),
252 cpu.l | (cpu.h << 8),
270 int de = cpu.e | (cpu.d << 8);
271 de = bdos(cpu.c, de);
291 cpu.regs.word.pc = entry_point;
297 "pc=%04x af=%04x bc=%04x de=%04x hl=%04x sp=%04x ix=%04x iy=%04x cf=%d nf=%d pvf=%d hf=%d zf=%d sf=%d\n",
315 if (cpu.regs.word.pc == 0) {
319 if (cpu.regs.word.pc == 5) {
320 cpu.regs.word.de = bdos(
325 cpu_z80_execute(&cpu);