エミュレータについて

遊びで作っているエミュレータについていろいろまとめておこうかなというだけの投稿。 実験で作った CPU のエミュレータです。 最初は実機でデバッグするのが辛いだろうということでアセンブラに簡易的な実行機能を つけようといった程度のモチベーションで始めたんですが、デバッガの実装が意外に面白かったので だんだん機能が増えてきているという感じです。 機能 今の所こんな感じです。 アセンブリで書いたプログラムを実行する 分岐命令の飛び先のアドレスをラベルで指定できる メモリの初期化ファイルに書かれた内容で内部のメモリを初期化 命令のアドレスにブレークポイントを置く 実行した命令をもとに戻す (Undo) 未定義動作を踏みそうになったら例外を飛ばして威嚇する ワード単位でのイミディエイトをサポートする疑似命令 実際にメモリの内容を読んで実行する (自己書き換えみたいなプログラムも動く) で今後無駄に実装しようと思っているのが

C/C++の単項演算子 + について

C++ で char を std::cout とかで出したいとき、 char hoge = 'a'; std::cout << +hoge; みたいに書くと a じゃなくて 97 が出る。これはなぜなのか。 C11 ではこのように述べられている。 The result of the unary + operator is the value of its (promoted) operand. The integer promotions are performed on the operand, and the result has the promoted type. C++17 ではこのように述べられている。 The operand of the unary + operator shall …(略) Integral promotion is performed on integral or enumeration operands. The type of the result is the type of the promoted operand. というわけで C、C++ 両方で単項演算子 + の結果は汎整数拡張がなされた結果になる。 hoge は char で +hoge は int の型を持つということになり、 operator<< の int オーバーロードが呼ばれ、97 が出力された。 参考にした資料 手元にあった C11 と C++17 の最終ドラフトで確認した。 より新しい規格では仕様が変わっている可能性もある。

EmscriptenでJSとCで相互にデータをやり取りする

Emscripten で JavaScript の世界と C の世界でデータをやり取りする方法をメモ (with ccall/cwrap)。 C や C++ 側で必要なこと Emscripten でコンパイルすると、main から到達できないコードは dead code elimination でサクサク消されちゃうので 関数に EMSCRIPTEN_KEEPALIVE を付けて消されないようにしておく必要がある (EMSCRIPTEN_KEEPALIVE 自体は __attribute__((used)) に展開されるっぽい。環境によるとは思うけど)。 コンパイルは emcc -s WASM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS="['ccall']" -o index.html main.cc とかで。NO_EXIT_RUNTIME にしておくことで、 main を実行したあとランタイムを止めるというデフォルトの挙動を変更できる。 ExPORTED_RUNTIME_METHODS に cwrap とかを入れておくと cwrap から使えるようになる。 ccall や cwrap で関数を呼び出すときの基本的な方法 Module.cwrap('hoge', 'string', 'number')(5); みたいな感じで C の関数を呼び出せるが、問題は引数と戻り値のところに何を入れるかということになる。

Emacs内のターミナルでのEmacsの実行をいい感じにした

ちょっと前ですが、「Emacs 内のターミナルで Emacs を開こうとしたら既に開いている Emacs でそのファイルを開く」やつを作りました。 しくみ ざっくり説明すると、DBus を使って Emacs とシェル (で立ち上がるプロセス) が通信して、 Emacs を開く代わりに現在のセッションで開いているように見せるという感じになります。 通信できるなら別に DBus じゃなくてソケットでもいいんですが、DBus だと Emacs Lisp の インターフェースでサーバを作るのが楽なので DBus になりました。 さて、この機能の実現には Emacs 側とシェル側 (厳密には emacs コマンドで立ち上げるプロセス) に細工が必要です。これ以降でそれらをもう少し詳しく説明します。 Emacs 側の細工 DBus インターフェースで待ち受けておく必要があります。

WebAssemblyを触ってみた

めっちゃお久しぶりです。 WebAssembly でハロワ的なサムシングを C++ でやったらすんなり動きすぎて感動したというポストです。 動機としては C++ で書いた SMF (Standard MIDI File) のパーサをブラウザ上で使いたかった ということです。別に速度を求めていたとかそういうわけではないのですが、バイナリを扱うのはやっぱり JavaScript よりも C++ とかの方がぱぱっと書けるかな、という。 で、使ったコードはリンク先に置いてあります。 https://github.com/kofuk/haystack/blob/df5d58caadf1ca640fef80484ac138faa6090c14/smf.cc 一応ビッグエンディアンをリトルエンディアンに変換している部分が wasm での挙動が予想できないため 不安な要素だったんですが、リトルエンディアンと考えていいみたいでした。 (これってコンパイルされた wasm をビッグエンディアンのマシンに持っていったら動かないみたいなことはあるんだろうか)。

VTE で Sixel が使えるようになった

久しぶりに vte のリポジトリを見に行ったら HEAD で Sixel が使えるようになっていたので、 その導入方法を……。 適当に調べた感じだと GNOME 端末 3.37 とかでもサポートされてるっぽいです。 sover 見た感じだと ABI 互換性が崩れたことはなさそうなのでどのバージョンでも問題は起きないかと思います。 バージョン Arch Linux 上で確認をしています。 また、実際に使ったコミットのハッシュは以下です。 c17e6d12da00a94c3768be6671182a6a039ec0c0 方法 まだリリースされていないので HEAD を取ってくる必要があります。 なんかサーバ遅い気がするので --depth 1 をつけて履歴を取ってこないようにした方がいいかもしれません。 $ git clone https://gitlab.gnome.org/GNOME/vte.git ソースのディレクトリに入り、Meson で Ninja などなどを生成 & ビルドします。 sixel はデフォルトだと無効なのでここで有効化してやります (-D は Make とか CMake にあるような、ビルドのオプションを変えるというオプション)。 $ meson . _build -Dsixel=true && cd _build && ninja ビルドに成功したらインストールします。ld.so.conf とかで /usr/local/lib を使う設定に していれば、そのまま ninja install とかでインストールすればいいと思います。 僕はめんどくさいので乱暴に _build/src/libvte.so.0.6500.0 を /usr/lib にコピーして soname のリンク (/usr/lib/libvte.so.0 などの古いライブラリに張ってある symlink) を張り替えるというやり方にしました (おそらくログがローカライズされないくらいで実害はないと思います)。

GObjectについて

この記事では C++ とか Java とかを触ってる人が、 それと同等のコードを GObject 上に構築するにはどうしたらいいのかという視点で解説していきたいと思います。 ただし、一部にそれらの内部実装に関する知識を要する部分があるので、 使ったことがあるというだけでは理解が難しい部分があるかもしれません。 GObject 使おうとしても意外と Web 上に情報がなく…… (これは単に調べるのが下手という説もある)。 GObject とは GObject は C で書かれたユーティリティライブラリである GLib の一部で、 主に GTK の構築に使われているオブジェクトシステム (オブジェクト指向ぽくコード書くフレームワーク) です。 オブジェクト関連の言語機能がない C で簡単に OOP できます。 ……ということになってる (のか知らないけど) けど、C++ から便利機能とか オブジェクト関連の構文を取り除いた感じで、割と自分で管理しないといけない部分が多い。 実際のところ感覚的には他言語のバインディングを触ってる感覚に近いです。

LuaLaTeXをとりあえず使ってみる

なんでも pLaTeX が本格的にやばいかも らしい。pLaTeXやばいやばい話はこれまで何度も聞いた気がする。 ちょっと前に SATySFi 使ったりしたけど、あれはちゃんと SATySFi 書けないとあんまり満足度高くないので まあのんびり習得していけたらいいやと。 そういうわけで、とりあえず LuaLaTeX を使えるようにしておく。 LuaLaTeX について TeX を再実装した LuaTeX というやつに LaTeX のパッケージを乗っけたもの………だと思う。 あんまり正確なことは把握してないので気になった方はマサカリ投げてください…………。 まあ見た目は Lua が使える LaTeX という感じ。僕は Lua は日常会話レベル (ほんとか?) だけど TeX は海外旅行に行ったときに身振り手振りでなんとか意思疎通するレベルなので Lua が使えるのはけっこう嬉しい…気がする。

Firefoxでマイク使用中のポップアップを表示しない方法

Firefox でマイクとか画面共有とかを使ったときに出てくるこいつを消す1方法。 一応これは安全のために出ているので、専用のプロファイルを作って使用することをおすすめする。 (使用自体おすすめできないのでは?) about:config で toolkit.legacyUserProfileCustomizations.stylesheets を true にする (いつの間にか消えてそうな名前だなぁ)。 /.mozilla/firefox/<プロファイル> の中に chrome というディレクトリを作る。 その中に userChrome.css を作り、以下の内容を書く。 #webrtcIndicator { display: none; } もしくはマウスカーソル合わせたときだけ隠すとか。 ところで Firefox ってときどき Chrome という名前が内部的に使われてる2けど 何なんですかね。 参考 Is it possible to disable this overlaying microphone icon? : firefox どうでもいいこと リンク貼るためにタイトルをコピーしようと思って Reddit でブラウザのコンソール開いたら何やら視線を感じた。 ちなみに仕事中 Reddit 見てないです。

OBS StudioのPipeWireキャプチャが古いリリースでも動くようにしてみた

今リリースされているバージョンの OBS Studio では Wayland 上で画面キャプチャができない。 OBS の master ブランチには PipeWire を使用した画面キャプチャが入っているので、 それを今のリリースされているバージョンに読ませて画面キャプチャできるようにしてみた。 これを /usr/lib/obs-plugins に置けば使えるはず。 (そのままビルドしただけでは動かないので適当に下みたいなパッチを当てた。) ビルドした linux-capture.so (消えてるかも) sha256: 693caf89788be465dfb813fd2c4662280fa2fbe218900dad3ad6111eec2926a6 適当に新しいやつのソース取ってきてビルドすればいいやんという話ではある。