2014年10月13日月曜日

[OS作成]30日でできる!OS自作入門 5日目 (2)

フォントはfont.sで定義するようにした。
フォントイメージを定義したhankaku.txtからfont.sを生成するプログラムを作成した。

hankaku.txt OSASKの半角フォントを定義したファイルで、以下のような形式となっている。
char 0x61
........
........
........
........
........
.***....
....*...
.....*..
..****..
.*...*..
*....*..
*....*..
*...**..
.***.**.
........
........

font.s では、フォントの最初の文字(文字コード0x00)のアドレスをhankaku_fontとしてtinyos.cから参照できるようにする。
半角フォント1文字は16バイトからなり、256文字分定義する。

font.s

.file "font.s"

.global hankaku_font

 .data

hankaku_font:
 // char 0x00
 .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
 // char 0x01
 .byte 0x00,0x00,0x38,0x44,0x82,0xaa,0xaa,0x82,0x82,0xaa,0x92,0x44,0x38,0x00,0x00,0x00
..snip..
font.sを生成するプログラムはOCamlで作成した。

makefont.ml

open Core.Std

let file_name = "hankaku.txt"

let is_skip_line line =
  let line' = String.strip line in
  line' = "" || String.get line 0 = '#'

let is_char_line line =
  try
    String.slice line 0 4 = "char"
  with
    _ -> false

let pattern_to_int p =
  String.fold p ~init:0 ~f:(fun acc c ->
      (acc lsl 1) + (if c = '*' then 1 else 0))

type parse_state = Init | Read_header | Read_data

let () =
  let lines = In_channel.read_lines file_name in
  let state = ref Init in
  List.iter lines ~f:(fun line ->
      if not (is_skip_line line) then
        if is_char_line line then begin
          if !state = Read_data then
            print_newline ();
          state := Read_header;
          print_endline ("\t// " ^ line);
          print_string "\t.byte "
        end
        else begin
          if !state = Read_data then
            print_string ",";
          state := Read_data;
          let img = pattern_to_int line in
          print_string ("0x" ^ (Printf.sprintf "%02x" img));
        end
    );
  print_newline ()
OMakeでfont.sを作成できるようにした。
$ omake font.s

ソースコードはgithubにコミットした。
https://github.com/takeisa/tinyos/tree/master/makefont

OCamlは、このような用途のプログラムも簡単に作成できる。
OCamlでの開発では、Emacs + Tuareg + merlin を使っているが、 コード補完が効くし、REPLとしてutopが利用できるのでとても便利。

OCamlを使ってみたい人は、ここを参考に環境構築すれば良いですよ。