use disk image file

This commit is contained in:
sfja 2025-03-31 19:59:13 +02:00
parent 335822afc6
commit dd2d919e2d
2 changed files with 57 additions and 177 deletions

View File

@ -45,9 +45,13 @@ KERN_OBJECTS = $(patsubst %.c,build/%.o,$(KERN_SOURCES))
all: bin/vm bin/build_disk_image
bin/vm: $(VM_OBJECTS) $(ASM_OBJECTS)
bin/vm: $(VM_OBJECTS) $(ASM_OBJECTS) build/image
@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)
@mkdir -p $(dir $@)

226
vm/main.c
View File

@ -10,6 +10,7 @@
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_video.h>
#include <bits/pthreadtypes.h>
#include <errno.h>
#include <pthread.h>
#include <stdatomic.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);
}
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)
{
for (size_t rip = 20; rip < 60; ++rip) {
@ -379,189 +419,25 @@ int main(void)
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;
res = sdldevice_construct(&io_device);
if (res != 0) {
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);
free(program);
fclose(fp);
sdldevice_destroy(&io_device);
}