#include "asm/asm.h" #include "common/video_character_display.h" #include #include #include #include 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, 0, 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_lines_with_labels(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); }