Implement disk controller
This commit is contained in:
parent
5bfe275b29
commit
7004b61606
1
Makefile
1
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
|
||||
|
|
55
src/bus.c
55
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;
|
||||
|
|
54
src/disk.c
Normal file
54
src/disk.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include <SDL2/SDL.h>
|
||||
#include <getopt.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
18
src/disk.h
Normal file
18
src/disk.h
Normal file
|
@ -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);
|
15
src/main.c
15
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)
|
||||
|
|
Loading…
Reference in New Issue
Block a user