use disk image file
This commit is contained in:
parent
335822afc6
commit
dd2d919e2d
8
Makefile
8
Makefile
@ -45,9 +45,13 @@ KERN_OBJECTS = $(patsubst %.c,build/%.o,$(KERN_SOURCES))
|
|||||||
|
|
||||||
all: bin/vm bin/build_disk_image
|
all: bin/vm bin/build_disk_image
|
||||||
|
|
||||||
bin/vm: $(VM_OBJECTS) $(ASM_OBJECTS)
|
bin/vm: $(VM_OBJECTS) $(ASM_OBJECTS) build/image
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
$(CC) $^ -o $@ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
$(CC) $(VM_OBJECTS) $(ASM_OBJECTS) -o $@ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
||||||
|
|
||||||
|
build/image: bin/build_disk_image
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
./bin/build_disk_image
|
||||||
|
|
||||||
bin/build_disk_image: $(KERN_OBJECTS) $(ASM_OBJECTS)
|
bin/build_disk_image: $(KERN_OBJECTS) $(ASM_OBJECTS)
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
|
226
vm/main.c
226
vm/main.c
@ -10,6 +10,7 @@
|
|||||||
#include <SDL2/SDL_render.h>
|
#include <SDL2/SDL_render.h>
|
||||||
#include <SDL2/SDL_video.h>
|
#include <SDL2/SDL_video.h>
|
||||||
#include <bits/pthreadtypes.h>
|
#include <bits/pthreadtypes.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -358,6 +359,45 @@ void memdrive_drive_write(Drive* in_drive, const uint8_t* block, uint16_t i)
|
|||||||
drive->drive.block_size);
|
drive->drive.block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Drive drive;
|
||||||
|
FILE* fp;
|
||||||
|
} FileDrive;
|
||||||
|
|
||||||
|
void filedrive_construct(
|
||||||
|
FileDrive* drive, FILE* fp, uint16_t block_size, uint16_t block_amount);
|
||||||
|
void filedrive_drive_read(Drive* in_drive, uint8_t* block, uint16_t i);
|
||||||
|
void filedrive_drive_write(Drive* in_drive, const uint8_t* block, uint16_t i);
|
||||||
|
|
||||||
|
void filedrive_construct(
|
||||||
|
FileDrive* drive, FILE* fp, uint16_t block_size, uint16_t block_amount)
|
||||||
|
{
|
||||||
|
*drive = (FileDrive) {
|
||||||
|
.drive = (Drive) {
|
||||||
|
.self = drive,
|
||||||
|
.block_size = block_size,
|
||||||
|
.block_amount = block_size,
|
||||||
|
.read = filedrive_drive_read,
|
||||||
|
.write = filedrive_drive_write,
|
||||||
|
},
|
||||||
|
.fp = fp,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void filedrive_drive_read(Drive* in_drive, uint8_t* block, uint16_t i)
|
||||||
|
{
|
||||||
|
FileDrive* drive = in_drive->self;
|
||||||
|
fseek(drive->fp, drive->drive.block_size * i, SEEK_SET);
|
||||||
|
fread(block, sizeof(uint8_t), drive->drive.block_size, drive->fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void filedrive_drive_write(Drive* in_drive, const uint8_t* block, uint16_t i)
|
||||||
|
{
|
||||||
|
FileDrive* drive = in_drive->self;
|
||||||
|
fseek(drive->fp, drive->drive.block_size * i, SEEK_SET);
|
||||||
|
fwrite(block, sizeof(uint8_t), drive->drive.block_size, drive->fp);
|
||||||
|
}
|
||||||
|
|
||||||
__attribute__((unused)) static inline void dump_program(uint16_t* program)
|
__attribute__((unused)) static inline void dump_program(uint16_t* program)
|
||||||
{
|
{
|
||||||
for (size_t rip = 20; rip < 60; ++rip) {
|
for (size_t rip = 20; rip < 60; ++rip) {
|
||||||
@ -379,189 +419,25 @@ int main(void)
|
|||||||
|
|
||||||
int label_ids = 0;
|
int label_ids = 0;
|
||||||
|
|
||||||
int main_loop = label_ids++;
|
|
||||||
int interrupt_table = label_ids++;
|
|
||||||
int keyboard_interrupt = label_ids++;
|
|
||||||
int keyboard_interrupt_0 = label_ids++;
|
|
||||||
int keyboard_interrupt_1 = label_ids++;
|
|
||||||
int keyboard_interrupt_2 = label_ids++;
|
|
||||||
int keyboard_interrupt_3 = label_ids++;
|
|
||||||
int keyboard_interrupt_4 = label_ids++;
|
|
||||||
int put_char = label_ids++;
|
|
||||||
int put_char_0 = label_ids++;
|
|
||||||
int put_char_1 = label_ids++;
|
|
||||||
int screen_x = label_ids++;
|
|
||||||
int screen_y = label_ids++;
|
|
||||||
|
|
||||||
#define L(LABEL) s_label(LABEL)
|
|
||||||
|
|
||||||
Line program_asm[] = {
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
// rsp points *at* the top element
|
|
||||||
s_mov16_r_i(Rbp, 2048),
|
|
||||||
s_mov16_r_i(Rsp, 2048 - 2),
|
|
||||||
|
|
||||||
s_lit_l(interrupt_table),
|
|
||||||
s_or_i(Rfl, Rfl, 1 << Fl_Int),
|
|
||||||
|
|
||||||
s_or_i(Rfl, Rfl, 1 << Fl_Vcd),
|
|
||||||
|
|
||||||
s_mov16_r_i(R0, 512),
|
|
||||||
s_mov16_r_i(R1, 1),
|
|
||||||
s_int(Int_DiskRead),
|
|
||||||
|
|
||||||
L(main_loop),
|
|
||||||
s_hlt(),
|
|
||||||
s_jmp_l(main_loop),
|
|
||||||
|
|
||||||
L(interrupt_table),
|
|
||||||
// size
|
|
||||||
s_data_i(1),
|
|
||||||
s_data_l(keyboard_interrupt),
|
|
||||||
s_nop(),
|
|
||||||
|
|
||||||
L(keyboard_interrupt),
|
|
||||||
s_and_i(Rfl, Rfl, (uint16_t)~(1 << Fl_Int)),
|
|
||||||
s_push_r(Rbp),
|
|
||||||
s_mov16_r_r(Rbp, Rsp),
|
|
||||||
s_push_r(R0),
|
|
||||||
s_push_r(R1),
|
|
||||||
s_push_r(R2),
|
|
||||||
s_push_r(R3),
|
|
||||||
|
|
||||||
s_in_i(R0, Device_Keyboard),
|
|
||||||
|
|
||||||
s_cmp_i(R0, 44),
|
|
||||||
s_mov16_r_r(R1, Rfl),
|
|
||||||
s_and_i(R1, R1, 1 << Fl_Eq),
|
|
||||||
s_jnz_l(R1, keyboard_interrupt_0),
|
|
||||||
|
|
||||||
s_cmp_i(R0, 42),
|
|
||||||
s_mov16_r_r(R1, Rfl),
|
|
||||||
s_and_i(R1, R1, 1 << Fl_Eq),
|
|
||||||
s_jnz_l(R1, keyboard_interrupt_1),
|
|
||||||
|
|
||||||
s_cmp_i(R0, 40),
|
|
||||||
s_mov16_r_r(R1, Rfl),
|
|
||||||
s_and_i(R1, R1, 1 << Fl_Eq),
|
|
||||||
s_jnz_l(R1, keyboard_interrupt_2),
|
|
||||||
|
|
||||||
s_jmp_l(keyboard_interrupt_3),
|
|
||||||
|
|
||||||
L(keyboard_interrupt_0),
|
|
||||||
s_mov16_r_i(R0, ' '),
|
|
||||||
s_call_l(put_char),
|
|
||||||
s_jmp_l(keyboard_interrupt_4),
|
|
||||||
|
|
||||||
L(keyboard_interrupt_1),
|
|
||||||
s_mov16_r_ml(R1, screen_x),
|
|
||||||
s_cmp_i(R1, 0),
|
|
||||||
s_mov16_r_r(R2, Rfl),
|
|
||||||
s_and_i(R2, R2, 1 << Fl_Eq),
|
|
||||||
s_jnz_l(R2, keyboard_interrupt_4),
|
|
||||||
s_sub_i(R1, R1, 1),
|
|
||||||
s_mov16_ml_r(screen_x, R1),
|
|
||||||
s_mov16_r_i(R0, ' '),
|
|
||||||
s_call_l(put_char),
|
|
||||||
s_mov16_r_ml(R1, screen_x),
|
|
||||||
s_sub_i(R1, R1, 1),
|
|
||||||
s_mov16_ml_r(screen_x, R1),
|
|
||||||
s_jmp_l(keyboard_interrupt_4),
|
|
||||||
|
|
||||||
L(keyboard_interrupt_2),
|
|
||||||
s_mov16_r_ml(R1, screen_y),
|
|
||||||
s_add_i(R1, R1, 1),
|
|
||||||
s_mov16_ml_r(screen_y, R1),
|
|
||||||
s_mov16_r_i(R1, 0),
|
|
||||||
s_mov16_ml_r(screen_x, R1),
|
|
||||||
s_jmp_l(keyboard_interrupt_4),
|
|
||||||
|
|
||||||
L(keyboard_interrupt_3),
|
|
||||||
s_add_i(R0, R0, 'A' - 4),
|
|
||||||
s_call_l(put_char),
|
|
||||||
s_jmp_l(keyboard_interrupt_4),
|
|
||||||
|
|
||||||
L(keyboard_interrupt_4),
|
|
||||||
|
|
||||||
s_pop_r(R3),
|
|
||||||
s_pop_r(R2),
|
|
||||||
s_pop_r(R1),
|
|
||||||
s_pop_r(R0),
|
|
||||||
s_mov16_r_r(Rsp, Rbp),
|
|
||||||
s_pop_r(Rbp),
|
|
||||||
s_or_i(Rfl, Rfl, 1 << Fl_Int),
|
|
||||||
s_iret(),
|
|
||||||
|
|
||||||
L(put_char),
|
|
||||||
s_push_r(Rbp),
|
|
||||||
s_mov16_r_r(Rbp, Rsp),
|
|
||||||
s_push_r(R1),
|
|
||||||
s_push_r(R2),
|
|
||||||
|
|
||||||
s_mov16_r_ml(R2, screen_y),
|
|
||||||
s_mul_i(R2, R2, vcd_width_in_ch),
|
|
||||||
s_mov16_r_ml(R1, screen_x),
|
|
||||||
s_add_i(R1, R1, 0x0c00),
|
|
||||||
s_add_r(R1, R1, R2),
|
|
||||||
s_mov8_mr_r(R1, R0),
|
|
||||||
|
|
||||||
s_mov16_r_ml(R1, screen_x),
|
|
||||||
s_add_i(R1, R1, 1),
|
|
||||||
s_mov16_ml_r(screen_x, R1),
|
|
||||||
|
|
||||||
s_cmp_i(R1, vcd_width_in_ch),
|
|
||||||
s_mov16_r_r(R2, Rfl),
|
|
||||||
s_and_i(R2, R2, 1 << Fl_Eq),
|
|
||||||
s_jnz_l(R2, put_char_0),
|
|
||||||
s_jmp_l(put_char_1),
|
|
||||||
|
|
||||||
L(put_char_0),
|
|
||||||
s_mov16_r_ml(R1, screen_y),
|
|
||||||
s_add_i(R1, R1, 1),
|
|
||||||
s_mov16_ml_r(screen_y, R1),
|
|
||||||
s_mov16_r_i(R1, 0),
|
|
||||||
s_mov16_ml_r(screen_x, R1),
|
|
||||||
|
|
||||||
L(put_char_1),
|
|
||||||
|
|
||||||
s_pop_r(R1),
|
|
||||||
s_pop_r(R2),
|
|
||||||
s_mov16_r_r(Rsp, Rbp),
|
|
||||||
s_pop_r(Rbp),
|
|
||||||
s_ret(),
|
|
||||||
|
|
||||||
L(screen_x),
|
|
||||||
s_data_i(0),
|
|
||||||
L(screen_y),
|
|
||||||
s_data_i(0),
|
|
||||||
|
|
||||||
// clang-format on
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t program_asm_size = sizeof(program_asm) / sizeof(program_asm[0]);
|
|
||||||
|
|
||||||
uint16_t* program = calloc(512 * 2, sizeof(uint16_t));
|
|
||||||
uint16_t program_size
|
|
||||||
= assemble_to_binary(program, program_asm, program_asm_size);
|
|
||||||
printf("program size = %d\n", program_size);
|
|
||||||
|
|
||||||
// dump_program(program);
|
|
||||||
|
|
||||||
// return 0;
|
|
||||||
|
|
||||||
MemDrive drive;
|
|
||||||
memdrive_construct(&drive, (uint64_t*)program, 512);
|
|
||||||
|
|
||||||
SdlDevice io_device;
|
SdlDevice io_device;
|
||||||
res = sdldevice_construct(&io_device);
|
res = sdldevice_construct(&io_device);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE* fp = fopen("build/image", "rb");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(
|
||||||
|
stderr, "error: could not open build/image: %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileDrive drive;
|
||||||
|
filedrive_construct(&drive, fp, 512, 32);
|
||||||
|
|
||||||
vm_start(&drive.drive, &io_device.io_device);
|
vm_start(&drive.drive, &io_device.io_device);
|
||||||
|
|
||||||
free(program);
|
fclose(fp);
|
||||||
sdldevice_destroy(&io_device);
|
sdldevice_destroy(&io_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user