vc3/kern/main.c
2025-03-31 19:49:36 +02:00

216 lines
5.6 KiB
C

#include "asm/asm.h"
#include "common/video_character_display.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const size_t block_size = 512;
const size_t block_amount = 32;
void write_program(FILE* fp);
int main(void)
{
FILE* fp = fopen("build/image", "wb");
if (!fp) {
fprintf(
stderr, "error: could not open build/image: %s\n", strerror(errno));
return -1;
}
printf("clearing disk...\n");
uint8_t* data = calloc(block_size, 1);
for (size_t i = 0; i < block_amount; ++i) {
fwrite(data, 1, block_size, fp);
}
free(data);
fseek(fp, 0, SEEK_SET);
printf("done!\n");
write_program(fp);
fclose(fp);
}
void write_program(FILE* fp)
{
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));
printf("assembling program...\n");
uint16_t program_size
= assemble_to_binary(program, program_asm, program_asm_size);
printf("done!\n");
printf("program size = %d\n", program_size);
printf("writing program to disk...\n");
fwrite(program, sizeof(uint16_t), program_size, fp);
printf("done!\n");
free(program);
}