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 \
|
CFILES = src/main.c \
|
||||||
src/bus.c \
|
src/bus.c \
|
||||||
src/cpu.c \
|
src/cpu.c \
|
||||||
|
src/disk.c \
|
||||||
src/framebuffer.c \
|
src/framebuffer.c \
|
||||||
src/mouse.c \
|
src/mouse.c \
|
||||||
src/screen.c
|
src/screen.c
|
||||||
|
|
55
src/bus.c
55
src/bus.c
|
@ -10,10 +10,12 @@
|
||||||
|
|
||||||
#include "bus.h"
|
#include "bus.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "disk.h"
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include "mouse.h"
|
#include "mouse.h"
|
||||||
|
|
||||||
extern fox32_vm_t vm;
|
extern fox32_vm_t vm;
|
||||||
|
extern disk_controller_t disk_controller;
|
||||||
extern mouse_t mouse;
|
extern mouse_t mouse;
|
||||||
|
|
||||||
int bus_io_read(void *user, uint32_t *value, uint32_t port) {
|
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;
|
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;
|
return 0;
|
||||||
|
@ -140,6 +162,39 @@ int bus_io_write(void *user, uint32_t value, uint32_t port) {
|
||||||
|
|
||||||
break;
|
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;
|
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 "bus.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "disk.h"
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include "mouse.h"
|
#include "mouse.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
@ -21,12 +22,14 @@
|
||||||
|
|
||||||
fox32_vm_t vm;
|
fox32_vm_t vm;
|
||||||
|
|
||||||
|
extern disk_controller_t disk_controller;
|
||||||
|
|
||||||
uint32_t tick_start;
|
uint32_t tick_start;
|
||||||
uint32_t tick_end;
|
uint32_t tick_end;
|
||||||
int ticks = 0;
|
int ticks = 0;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
void MainLoop(void);
|
void main_loop(void);
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||||
|
@ -42,6 +45,12 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
memcpy(vm.memory_rom, fox32rom, sizeof(fox32rom));
|
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(
|
ScreenCreate(
|
||||||
FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
|
FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
|
||||||
draw_framebuffer,
|
draw_framebuffer,
|
||||||
|
@ -59,7 +68,7 @@ int main(int argc, char *argv[]) {
|
||||||
tick_end = SDL_GetTicks();
|
tick_end = SDL_GetTicks();
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
MainLoop();
|
main_loop();
|
||||||
|
|
||||||
tick_end = SDL_GetTicks();
|
tick_end = SDL_GetTicks();
|
||||||
int delay = 1000/TPS - (tick_end - tick_start);
|
int delay = 1000/TPS - (tick_end - tick_start);
|
||||||
|
@ -73,7 +82,7 @@ int main(int argc, char *argv[]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainLoop(void) {
|
void main_loop(void) {
|
||||||
int dt = SDL_GetTicks() - tick_start;
|
int dt = SDL_GetTicks() - tick_start;
|
||||||
tick_start = SDL_GetTicks();
|
tick_start = SDL_GetTicks();
|
||||||
if (!dt)
|
if (!dt)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user