「30日でできる!OS自作入門」をRustで。29日目
Posted on 2019-08-20
「30日でできる!OS自作入門 」のC言語の部分をできるだけRustですすめてみる。今回は29日目の内容。
本ではファイルの圧縮を紹介しているが、独自アルゴリズムの圧縮形式のようで、圧縮自体も必須ではなさそうなので、今回はスキップする。
ここから最後までほぼアプリケーションを作る流れになりそうだ。
非矩形ウィンドウ
透明領域を作ることができるので、以下のようにすれば一部透明のウィンドウを起動できる。
// notrec/strc/lib.rs
#[no_mangle]
#[start]
pub extern "C" fn hrmain() {
let buf: [u8; 150 * 70] = [0; 150 * 70];
let win = unsafe {
_api_openwin(.as_ptr() as usize,
buf150,
70,
14,
b"notrec".as_ptr() as usize,
)};
unsafe {
, 0, 50, 34, 69, 14);
_api_boxfilwin(win, 115, 50, 149, 69, 14);
_api_boxfilwin(win, 50, 30, 99, 49, 14);
_api_boxfilwin(win}
loop {
if (unsafe { _api_getkey(1) } == 0x0a) {
break; // Enterならbreak
}
}
;
end()}
実行結果
bball
線を使った幾何学模様を描く
// bball/src/lib.rs
#[no_mangle]
#[start]
pub extern "C" fn hrmain() {
let buf: [u8; 216 * 237] = [0; 216 * 237];
let points: [(i32, i32); 16] = [
204, 129),
(195, 90),
(172, 58),
(137, 38),
(98, 34),
(61, 46),
(31, 73),
(15, 110),
(15, 148),
(31, 185),
(61, 212),
(98, 224),
(137, 220),
(172, 200),
(195, 168),
(204, 129),
(;
]let win = unsafe {
_api_openwin(.as_ptr() as usize,
buf216,
237,
-1,
b"bball".as_ptr() as usize,
)};
unsafe {
, 8, 29, 207, 228, 0);
_api_boxfilwin(win}
for i in 0..=14 {
for j in (i + 1)..=15 {
let mut d = j - i;
if d >= 8 {
= 15 - d;
d }
if d != 0 {
unsafe {
_api_linewin(,
win.0,
points[i].1,
points[i].0,
points[j].1,
points[j]8 - d) as i8,
(;
)}
}
}
}
loop {
if unsafe { _api_getkey(1) } == 0x0a {
break; // Enterならbreak
}
}
;
end()}
このままだと描画されないところがあるので、console.rs
のバグを直す。
// console.rs
#[no_mangle]
pub extern "C" fn hrb_api(/* 省略 */) -> usize {
// 省略
} else if edx == 13 {
let mut sheet_index = ebx as usize;
let mut refresh = true;
if sheet_index >= MAX_SHEETS {
= false;
refresh -= MAX_SHEETS;
sheet_index }
let sheet = sheet_manager.sheets_data[sheet_index];
.buf_addr, sheet.width, eax, ecx, esi, edi, ebp);
draw_line(sheetif refresh {
// ここから追加
let mut eax = eax;
let mut esi = esi;
if eax > esi {
core::mem::swap(&mut eax, &mut esi);
}
let mut ecx = ecx;
let mut edi = edi;
if ecx > edi {
core::mem::swap(&mut ecx, &mut edi);
}
.refresh(sheet_index, eax, ecx, esi + 1, edi + 1);
sheet_manager}
// 省略
}
常に値の小さいほうがrefreshの引数の先になるようにした。
実行結果
インベーダーゲーム
最後に、インベーダーゲームを作る。
コードの詳細はあまり載せてもしょうがないと思うので、GitHub 参照ということで、ここには載せない。 一点、ウィンドウの端の処理がうまくいかず、こちらにあるように、ウィンドウの描画を上書きする処理を追加している。
実行結果
以下の通り、インベーダーゲームができるようになった。
最下端までインベーダーがきてしまうとGAME OVERになるが、Enterで最初から再開できる
29日目は以上となる。ここまでの内容のコードはyoshitsugu/hariboteos_in_rustのday29としてタグを打ってある。