Mercurial > repos > blastem
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/blastcpm.c Wed Jul 29 00:05:21 2015 -0700 @@ -0,0 +1,112 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <sys/select.h> + +#include "z80_to_x86.h" +#include "util.h" + +uint8_t ram[64 * 1024]; + +#define START_OFF 0x100 +#define OS_START 0xE400 +#define OS_RESET 0xE403 +int headless = 1; + +void z80_next_int_pulse(z80_context * context) +{ + context->int_pulse_start = context->int_pulse_end = CYCLE_NEVER; +} + +void render_errorbox(char *title, char *message) +{ +} + +void render_infobox(char *title, char *message) +{ +} + +void *console_write(uint32_t address, void *context, uint8_t value) +{ + putchar(value); + return context; +} + +uint8_t console_read(uint32_t address, void *context) +{ + return getchar(); +} + +void *console_flush_write(uint32_t address, void *context, uint8_t value) +{ + fflush(stdout); + return context; +} + +uint8_t console_status_read(uint32_t address, void *context) +{ + fd_set read_fds; + FD_ZERO(&read_fds); + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_SET(fileno(stdin), &read_fds); + return select(fileno(stdin)+1, &read_fds, NULL, NULL, &timeout) > 0; +} + +void *exit_write(uint32_t address, void *context, uint8_t value) +{ + exit(0); + return context; +} + +const memmap_chunk z80_map[] = { + { 0x0000, 0x10000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, NULL, NULL, NULL, NULL}, +}; + +const memmap_chunk io_map[] = { + { 0x0, 0x1, 0xFFFF, 0, 0, NULL, NULL, NULL, console_read, console_write}, + { 0x1, 0x2, 0xFFFF, 0, 0, NULL, NULL, NULL, console_status_read, console_flush_write}, + { 0x2, 0x3, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, exit_write}, +}; + +int main(int argc, char **argv) +{ + FILE *f = fopen("fake_cpm.bin", "rb"); + long fsize = file_size(f); + if (fsize > sizeof(ram) - OS_START) { + fsize = sizeof(ram) - OS_START; + } + if (fread(ram + OS_START, 1, fsize, f) != fsize) { + fprintf(stderr, "Error reading from fake_cpm.bin\n"); + exit(1); + } + f = fopen(argv[1], "rb"); + fsize = file_size(f); + if (fsize > OS_START - START_OFF) { + fsize = OS_START - START_OFF; + } + if (fread(ram + START_OFF, 1, fsize, f) != fsize) { + fprintf(stderr, "Error reading from file %s\n", argv[1]); + exit(1); + } + fclose(f); + ram[0] = 0xC3; + ram[1] = OS_RESET & 0xFF; + ram[2] = OS_RESET >> 8; + ram[5] = 0xC3; + ram[6] = OS_START & 0xFF; + ram[7] = OS_START >> 8; + + z80_options opts; + z80_context context; + init_z80_opts(&opts, z80_map, 1, io_map, 3, 1); + init_z80_context(&context, &opts); + for(;;) + { + z80_run(&context, 1000000); + context.current_cycle = 0; + } + return 0; +} \ No newline at end of file