From cd3da4faab294529fb1fe3b9b25e165af2a86086 Mon Sep 17 00:00:00 2001 From: Ain <41307858+nero@users.noreply.github.com> Date: Sun, 22 Dec 2019 12:57:53 +0100 Subject: [PATCH] WIP on superzazu-based emulator --- .gitignore | 12 +---- HOST/em8080.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 81 ++-------------------------- 3 files changed, 154 insertions(+), 86 deletions(-) create mode 100644 HOST/em8080.c diff --git a/.gitignore b/.gitignore index 3470f5f..17077a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,2 @@ -*.bin -*.bs -*.img -*.com -*.rom -*.lst -*.exe -*.log -*.sys -/utils +*.COM +*.BIN diff --git a/HOST/em8080.c b/HOST/em8080.c new file mode 100644 index 0000000..15cff6f --- /dev/null +++ b/HOST/em8080.c @@ -0,0 +1,147 @@ +// 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; +} diff --git a/Makefile b/Makefile index ac76e1a..f6c2923 100644 --- a/Makefile +++ b/Makefile @@ -1,88 +1,17 @@ -FLOPPY = 360 - -BDOS = 0xF000 -BDOSIMG = bdos/8086.bin - -BIOS = 0xF800 -BIOSIMG = bios/8086.bin - -PROGRAMS = $(patsubst %.asm,%.com,$(wildcard com/*.asm)) DISTFILES = $(PROGRAMS) -ROMS = - -QEMU_ARCH = $(shell uname -m) -QEMU = qemu-system-$(QEMU_ARCH) -QEMU_ARGS = $(addprefix --option-rom ,$(ROMS)) - -NASM = nasm -NASM_ARGS = -s -Ilib -Plib/nasmcomp.asm -w-macro-params -NASM_ARGS += -DBDOS=$(BDOS) -DBIOS=$(BIOS) - -EMUL = utils/emul - -ifdef KVM -QEMU_ARGS += --enable-kvm -endif - -ifdef DEBUG -ROMS += rom/debug.rom -NASM_ARGS += -l $(basename $@).lst -endif - -ifndef DISPLAY -QEMU_ARGS += --display curses -endif .PHONY: default bootstrap clean qemu-rom qemu-floppy default: fdimage.img -bootstrap: +MAC.COM: wget -N http://www.cpm.z80.de/download/mac-b.zip unzip mac-b.zip -# Host utils -utils/%: src/utils/%.c - mkdir -p utils - $(CC) -o $@ $< +CP437.BIN: CP437.BMP HOST/bmp2font + HOST/bmp2font $< $@ -CP437.BIN: src/cp437.bmp utils/bmp2font - utils/bmp2font $< $@ - -# Boot sectors -boot/%.bs: boot/%.asm - $(NASM) $(NASM_ARGS) -DFLOPPY=$(FLOPPY) -o $@ $< - -# BIOS option roms -rom/%.rom: rom/%.asm utils/fix-rom - $(NASM) $(NASM_ARGS) -o $@ $< && utils/fix-rom $@ - -# Regular COM programs -com/%.com: com/%.asm - $(NASM) $(NASM_ARGS) -o $@ $< - -bdos/%.bin: bdos/%.asm lib/*.asm - $(NASM) $(NASM_ARGS) -o $@ $< - -bios/%.bin: bios/%.asm - $(NASM) $(NASM_ARGS) -o $@ $< - -fdimage.img: boot/fat.bs $(BDOSIMG) $(BIOSIMG) $(DISTFILES) - mformat -R 9 -C -i $@ -f $(FLOPPY) -B boot/fat.bs :: - dd if=$(BDOSIMG) bs=512 seek=1 count=4 conv=notrunc of=$@ - dd if=$(BIOSIMG) bs=512 seek=5 count=4 conv=notrunc of=$@ - mcopy -i $@ $(DISTFILES) :: - -hdimage.img: boot/mbr.bs fdimage.img - cat boot/mbr.bs fdimage.img >$@ +HOST/em8080: HOST/8080/i8080.o HOST/em8080.o clean: - find -name '*.lst' -delete - rm -f $$(cat .gitignore) boot/*.bs com/*.com rom/*.rom utils/* - rmdir utils - -qemu-floppy: fdimage.img $(ROMS) - $(QEMU) $(QEMU_ARGS) -boot a -fda fdimage.img - -qemu-hdd: hdimage.img $(ROMS) - $(QEMU) $(QEMU_ARGS) -boot c -hda hdimage.img + rm -f *.COM *.BIN HOST/bmp2font HOST/em8080 HOST/*.o