Mercurial > repos > blastem
comparison blastcpm.c @ 820:cf6149b7c6e5
Implement a tiny bit of CPM BDOS and add a corresponding Z80 core driver so that simple CPM programs like ZEXDOC/ZEXALL can be run against my Z80 core
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 29 Jul 2015 00:05:21 -0700 |
parents | |
children | fe8c79f82c22 |
comparison
equal
deleted
inserted
replaced
819:ab017fb09e77 | 820:cf6149b7c6e5 |
---|---|
1 #include <stdio.h> | |
2 #include <stdlib.h> | |
3 #include <stddef.h> | |
4 #include <string.h> | |
5 #include <sys/select.h> | |
6 | |
7 #include "z80_to_x86.h" | |
8 #include "util.h" | |
9 | |
10 uint8_t ram[64 * 1024]; | |
11 | |
12 #define START_OFF 0x100 | |
13 #define OS_START 0xE400 | |
14 #define OS_RESET 0xE403 | |
15 int headless = 1; | |
16 | |
17 void z80_next_int_pulse(z80_context * context) | |
18 { | |
19 context->int_pulse_start = context->int_pulse_end = CYCLE_NEVER; | |
20 } | |
21 | |
22 void render_errorbox(char *title, char *message) | |
23 { | |
24 } | |
25 | |
26 void render_infobox(char *title, char *message) | |
27 { | |
28 } | |
29 | |
30 void *console_write(uint32_t address, void *context, uint8_t value) | |
31 { | |
32 putchar(value); | |
33 return context; | |
34 } | |
35 | |
36 uint8_t console_read(uint32_t address, void *context) | |
37 { | |
38 return getchar(); | |
39 } | |
40 | |
41 void *console_flush_write(uint32_t address, void *context, uint8_t value) | |
42 { | |
43 fflush(stdout); | |
44 return context; | |
45 } | |
46 | |
47 uint8_t console_status_read(uint32_t address, void *context) | |
48 { | |
49 fd_set read_fds; | |
50 FD_ZERO(&read_fds); | |
51 struct timeval timeout; | |
52 timeout.tv_sec = 0; | |
53 timeout.tv_usec = 0; | |
54 FD_SET(fileno(stdin), &read_fds); | |
55 return select(fileno(stdin)+1, &read_fds, NULL, NULL, &timeout) > 0; | |
56 } | |
57 | |
58 void *exit_write(uint32_t address, void *context, uint8_t value) | |
59 { | |
60 exit(0); | |
61 return context; | |
62 } | |
63 | |
64 const memmap_chunk z80_map[] = { | |
65 { 0x0000, 0x10000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, NULL, NULL, NULL, NULL}, | |
66 }; | |
67 | |
68 const memmap_chunk io_map[] = { | |
69 { 0x0, 0x1, 0xFFFF, 0, 0, NULL, NULL, NULL, console_read, console_write}, | |
70 { 0x1, 0x2, 0xFFFF, 0, 0, NULL, NULL, NULL, console_status_read, console_flush_write}, | |
71 { 0x2, 0x3, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, exit_write}, | |
72 }; | |
73 | |
74 int main(int argc, char **argv) | |
75 { | |
76 FILE *f = fopen("fake_cpm.bin", "rb"); | |
77 long fsize = file_size(f); | |
78 if (fsize > sizeof(ram) - OS_START) { | |
79 fsize = sizeof(ram) - OS_START; | |
80 } | |
81 if (fread(ram + OS_START, 1, fsize, f) != fsize) { | |
82 fprintf(stderr, "Error reading from fake_cpm.bin\n"); | |
83 exit(1); | |
84 } | |
85 f = fopen(argv[1], "rb"); | |
86 fsize = file_size(f); | |
87 if (fsize > OS_START - START_OFF) { | |
88 fsize = OS_START - START_OFF; | |
89 } | |
90 if (fread(ram + START_OFF, 1, fsize, f) != fsize) { | |
91 fprintf(stderr, "Error reading from file %s\n", argv[1]); | |
92 exit(1); | |
93 } | |
94 fclose(f); | |
95 ram[0] = 0xC3; | |
96 ram[1] = OS_RESET & 0xFF; | |
97 ram[2] = OS_RESET >> 8; | |
98 ram[5] = 0xC3; | |
99 ram[6] = OS_START & 0xFF; | |
100 ram[7] = OS_START >> 8; | |
101 | |
102 z80_options opts; | |
103 z80_context context; | |
104 init_z80_opts(&opts, z80_map, 1, io_map, 3, 1); | |
105 init_z80_context(&context, &opts); | |
106 for(;;) | |
107 { | |
108 z80_run(&context, 1000000); | |
109 context.current_cycle = 0; | |
110 } | |
111 return 0; | |
112 } |