tomoyuki-nakabayashi / Rustemu86

Apache License 2.0
5 stars 0 forks source link

VGA出力する方法を調査する #20

Closed tomoyuki-nakabayashi closed 6 years ago

tomoyuki-nakabayashi commented 6 years ago

http://onagat.hatenablog.com/entry/2017/03/25/011308

このあたりでいける?

tomoyuki-nakabayashi commented 6 years ago

https://docs.rs/vga-framebuffer/0.4.0/vga_framebuffer/

tomoyuki-nakabayashi commented 6 years ago

https://en.wikipedia.org/wiki/VGA-compatible_text_mode

tomoyuki-nakabayashi commented 6 years ago

https://qiita.com/koji_mats/items/62e85a87cc580e225796

GTK使うか。悪くない気がする。

tomoyuki-nakabayashi commented 6 years ago

libgtkをインストールする。

sudo apt install libgtk-3-dev
tomoyuki-nakabayashi commented 6 years ago

めっちゃお手軽やな。

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");
    }
  };
}
tomoyuki-nakabayashi commented 6 years ago

https://github.com/rust-qt

qtという選択肢も一応あるのか。

tomoyuki-nakabayashi commented 6 years ago

gtk-rs

tomoyuki-nakabayashi commented 6 years ago

http://gtk-rs.org/docs/gtk/struct.Label.html

GTK labelで文字列表示できるらしい。 GTK textviewだと、テキストエディタになっちゃう。それはいらん。

tomoyuki-nakabayashi commented 6 years ago
      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();
      });

これで出力はされるね。

tomoyuki-nakabayashi commented 6 years ago

https://stackoverflow.com/questions/11489607/how-to-display-text-and-button-in-gtk-in-single-window

widgetを垂直に並べてテキスト表示しないとだめっぽい?

tomoyuki-nakabayashi commented 6 years ago

逆に25×80の1文字表示widgetを作って並べてしまえばいいのか。

tomoyuki-nakabayashi commented 6 years ago
      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つのウィジェットに複数のラベルをつけることはできないらしい。

tomoyuki-nakabayashi commented 6 years ago

https://gtk-rs.org/docs/gtk/trait.LabelExt.html

LabelExt traitを使えばよさそう。

tomoyuki-nakabayashi commented 6 years ago
        let label = gtk::Label::new("Hello");
        win.add(&label);
        label.set_text("Hi!");

うん、これで更新できるぞ。

tomoyuki-nakabayashi commented 6 years ago

https://developer.gnome.org/pygtk/stable/pango-markup-language.html

Pango Markup... また良く分からんものが出てきたぞ…。

tomoyuki-nakabayashi commented 6 years ago
      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();
      });

これで青文字が出る。

tomoyuki-nakabayashi commented 6 years ago
        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と出力されるが、激しく面倒臭いぞ…。

tomoyuki-nakabayashi commented 6 years ago

んー?Label自体もWidgetなのか。

tomoyuki-nakabayashi commented 6 years ago
        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);

なるほど。これでいいのか。

tomoyuki-nakabayashi commented 6 years ago
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になっているっぽい。

tomoyuki-nakabayashi commented 6 years ago

https://github.com/PistonDevelopers/conrod

conrodに浮気するかぁ。

tomoyuki-nakabayashi commented 6 years ago

けっこう複雑だな。

tomoyuki-nakabayashi commented 6 years ago
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の問題かな。

tomoyuki-nakabayashi commented 6 years ago

https://github.com/PistonDevelopers/conrod/issues/1018

issueになっているが、コメントアウトしろ、みたいなことしか書かれていないので、そうする。

tomoyuki-nakabayashi commented 6 years ago

うーん、使いにくい! Rust-qtの人柱やってみるか…。

tomoyuki-nakabayashi commented 6 years ago

https://github.com/rust-qt/cpp_to_rust

tomoyuki-nakabayashi commented 6 years ago
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
tomoyuki-nakabayashi commented 6 years ago

結局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
}
tomoyuki-nakabayashi commented 6 years ago

次は更新処理。

tomoyuki-nakabayashi commented 6 years ago
        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>");

つらたん。

tomoyuki-nakabayashi commented 6 years ago

だいぶできてきた。16bit即値をストアする命令を追加しよう。

00000000  66C7042500800B00  mov word [0xb8000],0xe48
         -480E
tomoyuki-nakabayashi commented 6 years ago
00000000  C7042500800B0048  mov dword [0xb8000],0xe48
         -0E0000

なるほど。c7オペランドは、0x66が先頭にあったら16bit即値で、なければ32bit即値、と。 えぐい。

tomoyuki-nakabayashi commented 6 years ago

とりあえず動くものはできた。 が、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)]
}
tomoyuki-nakabayashi commented 6 years ago

light redをエミュレーションできていないけど、一旦閉じ。