Closed tomoyuki-nakabayashi closed 6 years ago
https://qiita.com/koji_mats/items/62e85a87cc580e225796
GTK使うか。悪くない気がする。
libgtkをインストールする。
sudo apt install libgtk-3-dev
めっちゃお手軽やな。
extern crate gtk;
extern crate gio;
use gtk::{ WidgetExt, WindowExt };
use gio::{ ApplicationExt };
fn main() {
match gtk::Application::new("com.github.tomoyuki-nakabayashi.Rustemu86", gio::APPLICATION_HANDLES_OPEN) {
Ok(app) => {
app.connect_activate(|app| {
let win = gtk::ApplicationWindow::new(&app);
win.set_title("Rustemu86");
win.show_all();
});
app.run(&[""]);
},
Err(_) => {
println!("Application start up error");
}
};
}
qtという選択肢も一応あるのか。
http://gtk-rs.org/docs/gtk/struct.Label.html
GTK labelで文字列表示できるらしい。 GTK textviewだと、テキストエディタになっちゃう。それはいらん。
app.connect_activate(|app| {
let win = gtk::ApplicationWindow::new(&app);
win.set_title("Rustemu86");
let label = gtk::Label::new("Hello");
win.add(&label);
win.show_all();
start_rustemu86();
});
これで出力はされるね。
https://stackoverflow.com/questions/11489607/how-to-display-text-and-button-in-gtk-in-single-window
widgetを垂直に並べてテキスト表示しないとだめっぽい?
逆に25×80の1文字表示widgetを作って並べてしまえばいいのか。
app.connect_activate(|app| {
let win = gtk::ApplicationWindow::new(&app);
win.set_title("Rustemu86");
let label1 = gtk::Label::new("Hello");
let label2 = gtk::Label::new("Helloo");
win.add(&label1);
win.add(&label2);
win.show_all();
start_rustemu86();
});
1つのウィジェットに複数のラベルをつけることはできないらしい。
https://gtk-rs.org/docs/gtk/trait.LabelExt.html
LabelExt traitを使えばよさそう。
let label = gtk::Label::new("Hello");
win.add(&label);
label.set_text("Hi!");
うん、これで更新できるぞ。
https://developer.gnome.org/pygtk/stable/pango-markup-language.html
Pango Markup... また良く分からんものが出てきたぞ…。
app.connect_activate(|app| {
let win = gtk::ApplicationWindow::new(&app);
win.set_title("Rustemu86");
let label = gtk::Label::new(None);
win.add(&label);
label.set_markup("<span foreground=\"blue\">Blue text</span>");
win.show_all();
start_rustemu86();
});
これで青文字が出る。
let grid = gtk::Grid::new();
win.add(&grid);
let frame1 = gtk::Frame::new("a");
let frame2 = gtk::Frame::new("b");
grid.attach(&frame1, 10, 10, 10, 10);
grid.attach(&frame2, 20, 10, 10, 10);
win.show_all();
これで、a b
と出力されるが、激しく面倒臭いぞ…。
んー?Label自体もWidgetなのか。
let grid = gtk::Grid::new();
win.add(&grid);
let label1 = gtk::Label::new("a");
let label2 = gtk::Frame::new("b");
grid.attach(&label1, 10, 10, 10, 10);
grid.attach(&label2, 20, 10, 10, 10);
なるほど。これでいいのか。
fn create_text_grid() -> Grid {
let grid = gtk::Grid::new();
let mut row: Vec<gtk::Label> = Vec::new();
for i in 0..80 {
let label = gtk::Label::new(None);
let mut c = String::new();
write!(c, "<span size=\"13000\">{}</span>", i%10).unwrap();
label.set_markup(&c);
row.push(label);
}
for (col, label) in row.iter().by_ref().enumerate() {
grid.attach(label, 9*(col as i32), 16, 9, 16);
}
row[3].set_markup("<span foreground=\"blue\" size=\"13000\">3</span>");
grid
}
1列はこれで良いっぽい。
sizeがpoint/1000で指定なんだよなぁ。どうやら13だと9dotになっているっぽい。
https://github.com/PistonDevelopers/conrod
conrodに浮気するかぁ。
けっこう複雑だな。
use conrod::{self, widget, Colorable, Positionable, Widget};
use conrod::backend::glium::glium::{self, Surface};
pub fn init_display(activate_cb: fn()) {
const WIDTH: u32 = 720;
const HEIGHT: u32 = 400;
let mut events_loop = glium::glutin::EventsLoop::new();
let window = glium::glutin::WindowBuilder::new()
.with_title("Hello Conrod!")
.with_dimensions((WIDTH, HEIGHT).into());
let context = glium::glutin::ContextBuilder::new()
.with_vsync(true);
let display = glium::Display::new(window, context, &events_loop).unwrap();
activate_cb();
}
これで画面が出る。
with_multisampling()を入れるとダメだな。OpenGLの問題かな。
https://github.com/PistonDevelopers/conrod/issues/1018
issueになっているが、コメントアウトしろ、みたいなことしか書かれていないので、そうする。
うーん、使いにくい! Rust-qtの人柱やってみるか…。
tomoyuki@tomoyuki-VirtualBox:~/work/02.x86/Rustemu86/rustemu86$ cargo run -- tests/bins/hello-x86_64.bin
Compiling qt_core v0.2.3
Compiling qt_gui v0.2.3
error: failed to run custom build command for `qt_core v0.2.3`
process didn't exit successfully: `/home/tomoyuki/work/02.x86/Rustemu86/rustemu86/target/debug/build/qt_core-f0048664e1aa23cd/build-script-build` (exit code: 101)
--- stderr
Executing command: "qmake" "-query" "QT_VERSION"
Stdout:
Stderr:
qmake: could not exec '/usr/lib/x86_64-linux-gnu/qt4/bin/qmake': No such file or directory
Error:
0: command failed with exit code: 1: "qmake" "-query" "QT_VERSION"
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error(Msg("command failed with exit code: 1: \"qmake\" \"-query\" \"QT_VERSION\""), (None, None))', libcore/result.rs:945:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.
warning: build failed, waiting for other jobs to finish...
error: failed to run custom build command for `qt_gui v0.2.3`
process didn't exit successfully: `/home/tomoyuki/work/02.x86/Rustemu86/rustemu86/target/debug/build/qt_gui-2d27e82dca87c4d6/build-script-build` (exit code: 101)
--- stderr
Executing command: "qmake" "-query" "QT_VERSION"
Stdout:
Stderr:
qmake: could not exec '/usr/lib/x86_64-linux-gnu/qt4/bin/qmake': No such file or directory
Error:
0: command failed with exit code: 1: "qmake" "-query" "QT_VERSION"
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error(Msg("command failed with exit code: 1: \"qmake\" \"-query\" \"QT_VERSION\""), (None, None))', libcore/result.rs:945:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.
Qtのパスを指定しないといけない。 正しいPATHの与え方がよくわからないので、PATHに追加しておく。
PATH=~/Qt5.9.2/5.9.2/gcc_64/bin/:$PATH cargo run -- tests/bins/hello-x86_64.bin
結局GTKに戻ってきた。
fn create_text_grid() -> Grid {
let grid = gtk::Grid::new();
let mut text: Vec<Vec<gtk::Label>> = Vec::new();
for row in 0..25 {
text.push(Vec::new());
for col in 0..80 {
text[row].push(gtk::Label::new(None));
text[row][col].set_markup("<span font_family=\"monospace\" size=\"13000\" background=\"black\"> </span>");
grid.attach(&text[row][col], col as i32, row as i32, 1, 1);
}
}
grid
}
次は更新処理。
let child = screen.get_child_at(0, 0).unwrap().downcast::<gtk::Label>().ok().unwrap();
child.set_markup("<span font_family=\"monospace\" size=\"13000\" background=\"black\">a</span>");
つらたん。
だいぶできてきた。16bit即値をストアする命令を追加しよう。
00000000 66C7042500800B00 mov word [0xb8000],0xe48
-480E
00000000 C7042500800B0048 mov dword [0xb8000],0xe48
-0E0000
なるほど。c7
オペランドは、0x66が先頭にあったら16bit即値で、なければ32bit即値、と。
えぐい。
とりあえず動くものはできた。 が、Mov命令のデコードが今のままではダメですな。ぐちゃぐちゃ。
fn decode_mov_rm_imm(rf: &RegisterFile, inst: &FetchedInst) -> Vec<ExecuteInstType> {
use cpu::isa::modrm;
if inst.mod_rm.unwrap().mode != modrm::ModRmModeField::Direct {
return decode_store(&rf, &inst)
}
let dest = inst.mod_rm.unwrap().rm;
let imm = inst.immediate;
let uop1 = ExecuteInst { opcode: ExOpcode::Mov, dest: Some(dest), rip: None,
op1: Some(imm), op2: None, op3: None, op4: None };
vec![ExecuteInstType::ArithLogic(uop1)]
}
light redをエミュレーションできていないけど、一旦閉じ。
http://onagat.hatenablog.com/entry/2017/03/25/011308
このあたりでいける?