diff --git a/Makefile b/Makefile index e92a8de..8f45708 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ TARGET=fox32 CFILES = src/main.c \ src/bus.c \ src/cpu.c \ + src/disk.c \ src/framebuffer.c \ src/mouse.c \ src/screen.c diff --git a/src/bus.c b/src/bus.c index 3a3cac7..33f0ff3 100644 --- a/src/bus.c +++ b/src/bus.c @@ -10,10 +10,12 @@ #include "bus.h" #include "cpu.h" +#include "disk.h" #include "framebuffer.h" #include "mouse.h" extern fox32_vm_t vm; +extern disk_controller_t disk_controller; extern mouse_t mouse; int bus_io_read(void *user, uint32_t *value, uint32_t port) { @@ -71,6 +73,26 @@ int bus_io_read(void *user, uint32_t *value, uint32_t port) { break; }; + + case 0x80001000 ... 0x80002003: { // disk controller port + size_t id = port & 0xFF; + uint8_t operation = (port & 0x0000F000) >> 8; + switch (operation) { + case 0x10: { + // current insert state of specified disk id + // size will be zero if disk isn't inserted + *value = get_disk_size(id); + break; + }; + case 0x20: { + // current buffer pointer + *value = disk_controller.buffer_pointer; + break; + }; + } + + break; + }; } return 0; @@ -140,6 +162,39 @@ int bus_io_write(void *user, uint32_t value, uint32_t port) { break; }; + + case 0x80001000 ... 0x80005003: { // disk controller port + size_t id = port & 0xFF; + uint8_t operation = (port & 0x0000F000) >> 8; + switch (operation) { + case 0x10: { + // TODO: ask the user to insert a disk + break; + }; + case 0x20: { + // set the buffer pointer + disk_controller.buffer_pointer = value; + break; + }; + case 0x30: { + // read specified disk sector into memory + set_disk_sector(id, value); + read_disk_into_memory(id); + break; + }; + case 0x40: { + // TODO: write specified disk sector from memory + break; + }; + case 0x50: { + // remove specified disk + remove_disk(id); + break; + }; + } + + break; + }; } return 0; diff --git a/src/disk.c b/src/disk.c new file mode 100644 index 0000000..7df5926 --- /dev/null +++ b/src/disk.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpu.h" +#include "disk.h" + +disk_controller_t disk_controller; + +extern fox32_vm_t vm; + +void new_disk(const char *filename, size_t id) { + if (id > 3) { puts("attempting to access disk with ID > 3\n"); return; } + printf("mounting %s as disk ID %d\n", filename, (int) id); + disk_controller.disks[id].file = fopen(filename, "r+b"); + fseek(disk_controller.disks[id].file, 0, SEEK_END); + disk_controller.disks[id].size = ftell(disk_controller.disks[id].file); + rewind(disk_controller.disks[id].file); +} + +void insert_disk(disk_t disk, size_t id) { + if (id > 3) { puts("attempting to access disk with ID > 3\n"); return; } + if (disk_controller.disks[id].size > 0) remove_disk(id); + printf("mounting disk ID %d\n", (int) id); + disk_controller.disks[id] = disk; +} + +void remove_disk(size_t id) { + if (id > 3) { puts("attempting to access disk with ID > 3\n"); return; } + printf("unmounting disk ID %d\n", (int) id); + fclose(disk_controller.disks[id].file); + disk_controller.disks[id].size = 0; +} + +uint64_t get_disk_size(size_t id) { + if (id > 3) { puts("attempting to access disk with ID > 3\n"); return 0; } + return disk_controller.disks[id].size; +} + +void set_disk_sector(size_t id, uint64_t sector) { + if (id > 3) { puts("attempting to access disk with ID > 3\n"); return; } + fseek(disk_controller.disks[id].file, sector * 512, 0); +} + +size_t read_disk_into_memory(size_t id) { + if (id > 3) { puts("attempting to access disk with ID > 3\n"); return 0; } + return fread(&vm.memory_ram[disk_controller.buffer_pointer], 1, 512, disk_controller.disks[id].file); +} diff --git a/src/disk.h b/src/disk.h new file mode 100644 index 0000000..3756150 --- /dev/null +++ b/src/disk.h @@ -0,0 +1,18 @@ +#pragma once + +typedef struct { + FILE *file; + uint64_t size; +} disk_t; + +typedef struct { + disk_t disks[4]; + size_t buffer_pointer; +} disk_controller_t; + +void new_disk(const char *filename, size_t id); +void insert_disk(disk_t disk, size_t id); +void remove_disk(size_t id); +uint64_t get_disk_size(size_t id); +void set_disk_sector(size_t id, uint64_t sector); +size_t read_disk_into_memory(size_t id); diff --git a/src/main.c b/src/main.c index f223494..23b1438 100644 --- a/src/main.c +++ b/src/main.c @@ -9,6 +9,7 @@ #include "bus.h" #include "cpu.h" +#include "disk.h" #include "framebuffer.h" #include "mouse.h" #include "screen.h" @@ -21,12 +22,14 @@ fox32_vm_t vm; +extern disk_controller_t disk_controller; + uint32_t tick_start; uint32_t tick_end; int ticks = 0; bool done = false; -void MainLoop(void); +void main_loop(void); int main(int argc, char *argv[]) { if (SDL_Init(SDL_INIT_VIDEO) != 0) { @@ -42,6 +45,12 @@ int main(int argc, char *argv[]) { memcpy(vm.memory_rom, fox32rom, sizeof(fox32rom)); + if (argc > 1) { + for (int i = 0; i + 1 < argc; i++) { + new_disk(argv[i + 1], i); + } + } + ScreenCreate( FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, draw_framebuffer, @@ -59,7 +68,7 @@ int main(int argc, char *argv[]) { tick_end = SDL_GetTicks(); while (!done) { - MainLoop(); + main_loop(); tick_end = SDL_GetTicks(); int delay = 1000/TPS - (tick_end - tick_start); @@ -73,7 +82,7 @@ int main(int argc, char *argv[]) { return 0; } -void MainLoop(void) { +void main_loop(void) { int dt = SDL_GetTicks() - tick_start; tick_start = SDL_GetTicks(); if (!dt)