216 lines
5.6 KiB
C
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);
|
|
}
|