tmytのらくがき

個人の日記レベルです

SWIMMER OSINT CTF 2026 Write up

SWIMMER OSINT CTF 2026 にちょっぴり参加してました。Write upを書くといいらしいので書きます。

総合成績

4位でした。すごいね!ただオムライス(後述)はもうちょっといけたんじゃないかっていう説と、そもそも早くても3位には追い付けてなかったという説があります。

解けた問題

cx

2025年春、かつて香港に存在していた空港の100周年を記念して、特別なフライトが実施されたようです。 このフライトの便名を解答してください。 例えば、便名が JL2026 のとき、Flag は SWIMMER{JL2026} となります。

かつて香港に存在していた空港の100周年を記念して、特別なフライト をキーワードにGoogle検索をすると、香港経済新聞 がヒットすします。 記事を読むと

キャセイパシフィック航空の特別機CX8100が香港上空を低空飛行

とあるので、SWIMMER{CX8100} を回答してCorrect。CXと言われればキャセイパシフィックですね。

pilot

cx の問題で示されたフライト中、添付画像の席に座っていた人物の名前を英語で解答してください。 (なお、添付画像は座席を示すためのものであり、当該フライトの実際の写真ではありません) 例えば、人物の名前が John Doe のとき、Flag は SWIMMER{John Doe} となります。

問題に添付されている画像は、航空機の右側の席を示しています。右側の席はCo-pilotの座席で、先ほどのCX8100便の副操縦士は…というと cx8100 pilotGoogle検索すると Catherine Zhu さんのLinkedInの投稿が見つかります。このなかに

Cathay Pacific Captain Adrian Scott co-piloting CX8100

とあります。 SWIMMER{Adrian Scott} と回答してCorrectです。

obsolete

2025年11月、「台湾有事」を巡って日中関係が悪化しました。 その中で、在日本中国大使館のSNSアカウントは国連憲章の「敵国条項」について言及する投稿を行いました。 これに対し、日本の外務省は「その条項は 1995年の国連決議 によって死文化(obsolete)している」と反論したことが報じられています。

さて、この決議において、投票を 棄権 した国がいくつかあります。それはどこの国か、解答してください。 決議に関する公式記録に記載されている国名をアンダーバー (_) で区切ったもの(順不同)をFlagとします。

たとえば、UNITED STATES(アメリカ合衆国)とRUSSIAN FEDERATION(ロシア連邦)と記載されていた場合、Flagは SWIMMER{UNITED STATES_RUSSIAN FEDERATION} となります。

めっちゃ時事~~~~とか思いました。そもそも棄権した国はどこかということについては 敵国条項 1995 とかでGoogle検索するとWikipediaが出てくるのでみると

賛成155、棄権3(北朝鮮朝鮮民主主義人民共和国)、キューバリビア

とあるので棄権したのはこの3国。英語表記なんだっけ…とおもったんですが、そもそも問題を読むと「公式記録に記載されている国名」とあるので公式記録の文書を探す必要がありました。 これは、「国際連合総会決議50/52」というもので決議されたそうなので、だいたいこんなもんPDFあるやろ。と思い、何で検索したのか忘れたんですが9115 UN Yearbook というのにたどり着き、SWIMMER{Cuba_Democratic People's Republic of Korea_Libyan Arab Jamahiriya} でCorrectでした。

paint

添付画像に写っている航空機は、ある映画にちなんだ特別塗装機です。 この特別塗装機は、2017年3月21日に就航開始しましたが、2025年に引退が発表され、去る2026年1月9日、この塗装での最後の運航を終了しました。

さて、2017年にこの特別塗装が行われた建物はどこでしょうか。座標を地図上で示してください。

この問題に添付されている写真はANAスターウォーズ、特にC-3POペイントです。軽度の飛行機オタクなので開いた瞬間これはANAってなりました。 さてこの塗装がどこでされたのかということなのですが、ANAスターウォーズ塗装機はボーイングなのでまぁエバレットか羽田あたりちゃうんか知らんけど。とか思いながら、ANA スターウォーズ 塗装 工場 と検索するとどうやらC-3POは伊丹で塗装されたそうです。ならまぁあとは伊丹の格納庫の場所を調べるだけの話になり、ピンを刺してCorrectでした。

debris

2025年12月8日、日本のあるテレビ番組で、高速道路のパトロール隊への密着取材の様子が放映されました。 パトロール隊の108号車は、路上に落下していたトン袋の回収を命じられました。トン袋が最初に落下していた地点はどこでしょうか? マップ上で示して解答してください。

content warning : 交通事故の映像が含まれる映像を視聴する必要があります(人が巻き込まれるシーンはありません)。

2025年12月8日 高速道路のパトロール隊への密着取材 で検索すると、YouTubeが出てきます。それを見ていると「首都高池袋線 音羽 4.02kp」付近のカメラ映像でトン袋が落下していることが分かります。 首都高 キロポストで検索すると首都高全線をキロポスト付きで走行してくれている素晴らしい動画が見つかります。5号池袋線下り4kp付近を見ながら、Google ストリートビューであたりをつけてピンを刺してCorrectでした。

rain_04_source2

rain が2番目に作成した偽記事には、「rainが未公開の情報を見つけた」ということが書かれているようです。しかし、これは虚偽だと思われます。 この人物の嘘を暴くには、正確な出典を探す必要があります。

この画像の出典となる古い書籍は電子化されており、詳細が参照できるはずです。 その資料のデジタルオブジェクト識別子(DOI)を解答してください。 例えば、答えが 12.34567/890123 の場合、Flagは SWIMMER{12.34567/890123} となります。

この問題の前にrain という人物のブログのURLが分かっています。このURLにアクセスしそれっぽい画像を見るとこれがあります。

この画像で画像検索するとみての通り国会議事堂です。国会議事堂の設計デザインが掲載された資料を探せばいいようです。 なんやかんやありまして、洪洋社編『議院建築意匠設計競技図集』, 洪洋社, 大正9【422-13】 で検索するとだいたいよさそうな気がしてきます。

出てきたページでDOIを探すと 10.11501/967480 となっているので、 SWIMMER{10.11501/967480} でCorrectです。

rain_05_date

rain は2025年12月25日 (JST)、ある場所に来たことをX上で投稿しています。 しかし、この画像は2025年の別の日に撮影された写真のようで、事実とは異なるようです。 この写真が本当に撮影された日を YYYY/MM/DD の形式で解答してください。 ただし、撮影日は日本時間(JST)を基準とします。 例えば、答えが2025年6月8日の場合、Flagは SWIMMER{2025/06/08} となります。

指定されているXの画像は大阪城公園の写真です。ただ、12/25は平日なのに入場口なんて看板が出ていて若干不自然です。まぁ平日でもイベントやってることはありますが… 画像中央付近に、「ご招待・報道受付」とあってその上にイベントのロゴがあります。これを画像検索したところうまく見つからなかったんですが、大阪であることはわかっているので大阪をキーワードにしたところ、サントリー1万人の第九であることがわかりました。 あとはこの開催日を回答すればよいので、 SWIMMER{2025/12/07} でCorrectでした。

debeyohiru_01_social

調査対象の人物はソフトウェアエンジニアで、2026年以降には debeyohiru というIDでの活動が確認されています。 この人物がこのIDでの活動を開始したのは2026年1月のようです。この人物がこれ以前に使用していたIDを特定できないでしょうか?

2026年1月時点で、noteというサービスに古いIDのアカウントが残存しているようです。 このアカウントのIDを解答してください。

例えば、digital_jpn_gc が対象のアカウントの場合、 Flag は SWIMMER{digital_jpn_gc} となります。

Googledebeyohiru で検索するとBluesky のアカウントがヒットします1。この中にnote のスクショがあり、スクショのURLをみると furaigo5 であることが分かります。 SWIMMER{furaigo5} でCorrectです。

debeyohiru_02_profile

debeyohiru は2026年1月時点で求職中で、プロフィールページをウェブ上に公開していたようです。 このページを探り出し、そのURLを解答してください。

例えば、 https://example.com/foobar が対象のページの場合、 Flagは SWIMMER{https://example.com/foobar} となります。

まぁたぶんGitHubあるでしょ。ってことで https://github.com/furaigo5 をたどるとプロフィールページが出てきて、そこからGitHub PagesでホストされたWebページが見つかります。

SWIMMER{https://furaigo5.github.io/profile/} を回答してCorrectです。

debeyohiru_03_email

debeyohiru が2026年現在、普段使っているメールアドレスが知りたいです。 この人物が現在使用中とおぼしきメールアドレスを探り出し、解答してください。

例えば、メールアドレスがfoobar@example.comの場合、Flagは SWIMMER{foobar@example.com} となります。 警告: このアドレスに対してメールを送信してはなりません。解答に際して、メールを送る必要は一切ありません。

先ほどのGitHubページの中にメールアドレスがあるのでそのまま回答すればOKです。SWIMMER{furaigo5.onionsoup(アットマーク)gmail.com} でCorrectです。

debeyohiru_05_hidden1

debeyohiru の本名が知りたいです。 この人物の実名と考えられるものを解答してください。 ローマ字(アルファベット)表記で入力してください。漢字の表記を考慮する必要はありません。

例えば、Sanae Takaichiが実名の場合、Flagは SWIMMER{Sanae Takaichi} となります。

本名なぁ~ん~とおもってF12押してSourceを眺めていたらJavaScriptのヘッダに @author 書いとるやんけ!!!!となりました。 SWIMMER{Tsubasa Gotanno} と回答してCorrectでした。

番外編

lilica_03_virtual_world

チームメンバーから「VRChatのワールド特定しないといけないんですけど、ナギサ?ってかいてるんです。」といわれ、NAGiSAのURLを共有しました。 「なんでナギサがここなんです?」って聞かれたんですが、

私「VRChatでナギサっていえばおそらく間違いなくここです、そういうもんなんです。」

VRChatやってないとGoogleレンズで検索したりするらしいです。

debeyohiru_04_meal

最難関オムライス。ターゲットが食べたオムライスを答えないといけないんだけど、全然わからん。 Googleのクチコミに投稿されている画像のオムライスを回答すると正解だったんですが、まじでわかんなかったやつでした。

あまりにもわからなさすぎて、ずっとオムライスとにらめっこしてた結果終わった後ポムの樹食べました。

まとめ

たのしかったです!

OSINT CTFあんまり得意じゃないんですがとても楽しかったです!! 今回はチームで参加したんですが、DiscordでVCつなぎながら、各自担当している問題の状況をシェアしたり、スレッド立てて状況メモしたりしながらやってました。 楽しかったのでまたやりたいですね!!!次はDIVER...?


  1. 運悪くアダルティな検索結果が混ざってくるのでびっくりします

CsPscのフォローアップ記事です

久しぶりにアドベントカレンダーというものを書いたのですが、その時にC#をRoslynで解析し、ASTをPostScriptに落としてC#のようなプログラムをプリンタで実行できて楽しいね!!というジョークコンパイラを実装しました。

CSharp-PostScript Comiler 縮めてcspsc は、RoslynでASTをなめて、ツリーをPostScriptに変換するだけのもはやコンパイラか?といわれると怪しいやつです。かっこよく言うと、「C#向けのPostScriptバックエンド」です。かっこつけすぎました。 これは1200行ほどの1ファイルで実装されています。

github.com

アドベントカレンダーではプリンタでプログラムが実行できて楽しいね!!Roslyn便利だね!!ぐらいのところまでにとどめておいたのですが、そこそこちゃんと作ってあるコンパイラで、紹介していない機能がたくさんあったのでせっかくなのでフォローアップという形でこっちに放流します。

文中のコードはコンパイルが通ることを確認しているのでPostScriptにコンパイルしてあほだな~って眺めるのがいいかも1

組み込み属性

PostScriptをC#から生成するにあたって、PostScriptの全命令をC#マッピングするのがめちゃくちゃだるかったので属性でさぼったりしました。そのため、変な属性が2個だけ定義されています。

DllImportAttribute

DllImportAttribute自体は普通のC#にも存在しているんですが、このコンパイラはDllImportAttributeの解釈を大幅にさぼっているので本物より実装が雑です。具体的には、引数を全く解釈していません。

さらに、この属性はRoslynをごまかしてDiagnosisを正しく通過したうえでコンパイル時に関数名をPostScriptの命令に置換するためのマーカーでしかなく、関数名は常に ToLowerCase されます。

// たとえば
[DllImport("何を書いてもいい")]
extern static void ShowPage();

// 空はRoslynがエラーにするのでなんか書いてね
// [DllImport("")]
// extern static void sub();

[DllImport("🔢")]
extern static double Sqrt(double x);

[DllImport("関数名の大文字小文字がめちゃくちゃでもいい")]
extern static void MoVeTo(double x, double y);

PSFontAttribute

せっかくなのでフォントを設定したいと思います。ただ、こんなジョークコンパイラにおいてフォントなんて最初の1回だけ設定できれば十分すぎます。そのため、Assembly属性として設定することでなんかC#っぽい見た目になるな!ということで、Assembly属性を通してページのフォントを設定できます。

// PostScriptフォント名、フォントサイズで渡す
[assembly:PSFont("Courier", 12)]

組み込み関数

組み込み関数がいくつかあります。紹介するまでもないものとしてConsole.WriteLine, Console.Write のシノニムをイメージした WriteLine, Write がありますが本物と違いFormatを受け付けないかつ、string しか受け付けないので比較的さぼった実装になっています。

これらは WriteLine, Write のシノニムです。実はシノニムですらなくて、コンパイル時には __print, __println という関数呼び出しに置換されます。Cのコンパイラだとよくある関数だと思ってたら実はマクロで、libcに置き換わってた!みたいなそういうタイプの呼び出しです。

// これが
println("Hello, World");
// こう
// (Hello, World) __println

__sym

フォントを設定するにはPSFontAttributeを使うと書いてあるのですが、やっぱりPostScriptの全機能をフル活用したいかなあと思いまして、C#からPostScriptで言うところのNameを生成する関数です。PostScriptのNameに該当する機能がC#にはないのですが、RubyJavaScriptでは言えばSymbolが近い概念です。

こんなのいつ使うんだといわれるとかなり微妙なんですが、findfontをDllImportしたときとかに使えます。

[DllImport("x")]
extern static object FindFont(PsSym sym);

FindFont(__sym("Courier"));

__asm

これはもはやC#なのかわからなくなってきましたが、任意の位置に任意のPostScript命令を直接Emitできます。 いわば、PostScript界のインラインアセンブラです。

/*
// 普通に関数定義もできる
int Fib(int n){
  if(n < 2) return n;
  return Fib(n - 1) + Fib(n - 2);
}
*/
// けどインラインアセンブラで書いたほうがオーバーヘッドが少なくて高速
[DllImport("x")]
extern static int Fib(int n);
__asm("/fib { dup 1 gt { dup 1 sub fib exch 2 sub fib add } if } def");

println(Fib(10)); // 55

参考例にもあるように、__asm で関数定義した場合C#側にはシンボル情報がやってこないのでマッピングのためにDllImportを書きます。この時順番はなんでもいいです。

ref/in/out引数、Tuple引数、Tuple戻り値

アドカレではそんなに言及してないんですが、真面目にコンパイラが実装されているのでref/in/out 引数に無駄に対応しています。 さらに、Tuple構造体がない代わりに、Tuple記法に対応しているのでNamedTupleの定義、分解ができます。

ref/in/out

ref/in/out は引数を渡すときに辞書に包んで関数を呼び、関数は引数がref/in/outの時に辞書から取り出してローカル変数を定義し、関数から抜けるとき辞書に書き戻す。そして呼び出し元は辞書から取り出してローカル変数に書き戻す。という手順を踏んでいます。

つまりこれ、Boxing/Unboxingですね!PostScriptの辞書を使ってref/in/out 指定された変数をBoxing/Unboxingすることで参照渡しをなんだかうまいこと実現できているのです。

% void X(out int n) { n = 10; }
% X(out var k);
/X {
  2 dict begin
    /n_ref exch def
    /n n_ref /value get def
    mark {
      /n 10  dup 3 1 roll store
      pop
    } stopped { pop } if
    cleartomark n_ref /value n put
    end
  }
def
/k 0 def
/k_ref << /value k >> def
k_ref X /k k_ref /value get store

この参照渡し駆使すると地獄のようだけどValidな構文が出来上がって地獄だった。例えば

int n(ref int a, out int b, int c){
  return (b = a += c) * 2;
}
int x = 1;
x = n(ref x, out var y, 3); // 8 

refのaにcを足したものをoutのbに代入したものを2倍したものがnの戻り値でそれをもとのxに代入するというレビューで見たら発狂しそうな実装なんですが、なんかこれたまたま動きます。びっくりですね。

さらにここにTupleを融合させます。

(int a, int b) m(ref int k, out (int y, int z) t){
    t = (k += 2, k *= 3);
    return (t.y, t.z * k);
}

int x = 10;
var t1 = m(ref x, out var t2);
println($"{x}, {t1.a}, {t1.b}, {t2.y}, {t2.z}"); // 36, 12 1296, 12, 36

書いてて何かいてんのかわからないぐらい狂気なので詳細は避けますが、検算したところおそらく出力は正しく、C#の評価順序とも一致した正しい挙動になっていそうです。正直ここまでちゃんと動くとは思ってなかった。

Roslynのごまかしかた

Roslynもこんな使い方をされるとは思ってなかった気がします。ただPostScriptを出力するためにいい感じにASTを吐いてほしいし、なんならC#の構文としておかしいものは事前に全部エラーにしてほしい、ただそうすると組み込み関数とかもエラーにされると困る。ので適当なクラスをでっちあげてRoslynをごまかします。

using System.Runtime.InteropServices;

namespace CsPsc.Preamble
{
    public static class Intrinsics
    {
        [DllImport("cspsc_intrinsics", EntryPoint = "println")]
        public static extern void println(string s);

        [DllImport("cspsc_intrinsics", EntryPoint = "print")]
        public static extern void print(string s);

        [DllImport("cspsc_intrinsics", EntryPoint = "__asm")]
        public static extern void __asm(string s);

        [DllImport("cspsc_intrinsics", EntryPoint = "__sym")]
        public static extern PsSym __sym(string name);
    }

    [System.AttributeUsage(System.AttributeTargets.Assembly)]
    public class PSFontAttribute : System.Attribute
    {
        public string FontFace { get; }
        public int FontSize { get; }

        public PSFontAttribute(string fontFace, int fontSize)
        {
            FontFace = fontFace;
            FontSize = fontSize;
        }
    }

    public class PsSym { }
}

この名前空間をツリーのパース時にだけusing static Preamble.Intrinsics するようにしてあります。その結果Roslynは正当なC#の呼び出しだと思っているのにその先ではILを1文字もEmitせずに、全部PostScriptしか吐かない。というジョークコンパイラとして成り立つ仕組みになっていました。

正直まさかここまでうまくPostScriptにコンパイルできるとも思ってなかったのにRoslynすごいなーPostScriptすごいなーとかおもって適当に作ってたらそこそこにC#が動く、可動式ジョークとしていいポイントに収まったんじゃないかなと思っています。

Roslynで嘘コンパイラ作るの楽しいからみんなもやってみるといいよ

github.com


  1. 実行はWebエディタを用意してあるのでそこで試してみるのが手っ取り早いです。CsPsc Playground

VRChatアバターのモーションを非破壊に差し替えるやつを作りました

VRChat楽しんでますか?僕はぼっちなのでBoothで衣装を買って、Unityで着せ替えを楽しんで、時々散歩に出かけるのと、ラジオ体操をするぐらいです。

2年ぶりの投稿がこれでいいのか一瞬悩まなかったわけでもないんですが、気にしたら負けな気がするので気にしないことにしました。

tl;dr

  • アバターのPlayable Layerに設定されているAnimatorに含まれるMotionを差し替えるNDMFプラグインを作ったよ
  • VCCから導入できるよ、URLはここ https://tmyt.github.io/vpm/
  • GameObjectを置いて、Avatar Motion Changer というComponentを設定してつかってね

前置き

さて、アバターのモーション*1を差し替えたいことが時たまあります。 具体的には、AFKを別なものに変えたり、ジャンプモーションを変えたり、ハンドサインに割当たっているモーションを変えたりでしょうか。

これらの変更をするにはアバターに付属しているAnimatorを複製して編集してアバターに設定という手順を踏まないといけないです*2。 ただ、Animatorを複製して編集みたいなのはできればやりたくないのでNDMFの力でPlayable LayerのAnimatorに設定されているMotionを差し替えるやつを作ってみました。

導入方法と使い方

VCCから簡単導入できるようにしてみました、手元のVCCと友人にやってもらった限りインストールできているので多分あってると思います。 次のページからAdd to VCC してVCCから、Avatar Motion Changer というのをインストールしてください。Non-Destructive Modular Framework が必要ですが、Modula Avatarがインストール済みであればすでに入っています。

tmyt.github.io

VCCからパッケージがインストールできたら、実際にアバターに組み込んでいきます。 今回は、ぽんでろさんのしなのちゃんに、フカさんのしなのちゃんの手でしょりしょりするやつを設定してみます。 アバターなどのUnity Packageはすでにインポートされている状態とします。

booth.pm

booth.pm

まずGameObjectをアバターの配下に追加し、そのGameObjectにAvatar Motion Changerというコンポーネントを追加します。*3

List is Empty と出ている近くの+ボタンを2回押します。すると項目が2個増えるので、ドロップダウンからいい感じに設定します。Animationのところは、設定したいMotion、ここではFUKA_Fist_Triggerをドロップします。

あとはプレイボタンを押すとか、アバターをアップロードするときなどのビルド時に自動でモーションが差し変わります。 もとのAnimatorも変更されないのでアバターのプレハブが更新されたときも基本的に気にしなくていいはず…です。

制約事項

  • Playable Layerに対するAnimatorが未設定の状態のものはこのコンポーネントから設定することはできません。将来的にできるようになるかもしれないですが、そもそも使うことがなさそうなので対応は未定です。
  • StateのMotion以外のパラメータの設定には現時点では対応していません。どうしても必要になったら対応するかもしれないですがこちらも使わなさそうなので対応は未定です。

その他

  • ひとつのGameObjectに複数つけても正しく動くように作っているはずですがテストしてないので本当に動くかはわかりません。
  • オリジナルのデータが変更されていないこと・Play時の一時ファイルでのみ変更されていること・アップロードしたアバターでは変更が反映されていることは十分に確認していますが、100%オリジナルデータが安全という保障はできないので各自バックアップは撮ってください。

おわりに

モーション入れ替えがとても簡単になるのでみんな使ってみてね!*4

それと、こういうの設定できたよ!これが設定うまくできないよ!みたいなのがあったらこそっと教えてください

*1:ここで指すモーションは、Playable Layerに設定されているAnimatorのStateMachine内に設定されているAnimation Clipを指します

*2:たぶんそう。本当にそうなのかはわからないけどみんなAnimator編集するって書いてるからたぶんそう

*3:アバター配下のどこかにComponentが設定されていれば動くので追加しなくても大丈夫ですが、後から見た時にわかりやすいのでとりあえず追加します

*4:そもそもこれを使うシーンが多分ほとんどない

Keychron Q65が届いた

Keychron Q65というキーボードがDHLで届いたのです。

5月ごろにGroupBuyやっていてそれがついに届いたという感じです。ちなみに昨日までは売り切れ表示だったんですが、今(2022年11月23日)みたところ在庫あり表示になっているので今すぐ買えますね!!!!

Keychron Q65 QMK Custom Mechanical Keyboardwww.keychron.com

組み立てるのも楽しいんですがキーキャップ選び出すと沼にはまるのでFully Assembled Knobにしました。

第一印象はめっちゃ重い(物理)なんか2.4kgあるらしいです。2リットルペットボトルより重たい…安定感抜群ですね…

そんでもってめっちゃ光る。USBケーブル接続した瞬間めっちゃ光る。虹色に波打っててゲーミングみたいでした。

このキーボードの気に入っているポイントは左側にノブとM2~M5キーがあることです。Knob Versionっていうぐらいなんだからそりゃそうかという感じですがノブがあります。

しかも、VIAでカスタムできるのも楽しいポイントでした。VIAってすごいんですね、リアルタイムで反映されるし自動で永続化されるし…

VIAで1個だけわからなかったのが、Altを押してESCを押したときはESCじゃなくてGrave*1を出力するようにしたいけどこれをどうしていいかわからなかった。

QMKにはGrave Escapeという機能があってこれを使うと似たようなことができる…けどこれはShiftかGUI*2とESCを押したときにESCじゃなくてGraveになる機能…らしい…*3

このためにレイヤ1枚使うのももったいないしなぁ…とおもってしばらく使ってたらふとQMK改造すればいい!!オープンソース最高!!となってGrave Escapeの機能を改造することにしました。

Grave Escape改造

Grave EscapeがShift or GUIでGraveになるESCから、AltでGraveになるESCに改造したメモ。

DockerでDebianを起動してやります。

# 環境設定
docker run -it --rm debian
apt update
apt install -y sudo zlibg1-dev libjpeg-dev git python3-pip vim
python3 -m pip install qmk
qmk setup Keychron/qmk_firmware

お好きなエディタでここを編集する

diff --git a/quantum/process_keycode/process_grave_esc.c b/quantum/process_keycode/process_grave_esc.c
index ddf02739..17c12a1a 100644
--- a/quantum/process_keycode/process_grave_esc.c
+++ b/quantum/process_keycode/process_grave_esc.c
@@ -23,7 +23,7 @@ static bool grave_esc_was_shifted = false;
 bool process_grave_esc(uint16_t keycode, keyrecord_t *record) {
     if (keycode == QK_GRAVE_ESCAPE) {
         const uint8_t mods    = get_mods();
-        uint8_t       shifted = mods & MOD_MASK_SG;
+        uint8_t       shifted = mods & MOD_MASK_ALT;
 
 #ifdef GRAVE_ESC_ALT_OVERRIDE
         // if ALT is pressed, ESC is always sent
# いい感じにビルドする
make keychron/q65/q65_ansi_stm32l432_ec11:via

ここまでやって、出来上がったbinを焼いたらOKでした。

焼き方はスペースバーを外すとスイッチの左側にDFUに入るスイッチがあるので、それをUSBケーブルを指すとDFUモードになってQMK Toolboxでファームが焼けるようになります。

焼き終わった後、Fn+J+Zを4秒くらい押してEEPROMをファクトリリセットしておくといいそうです。

*1:つまりバッククオート

*2:WindowsでいうところのWindowsキーMacでいうところのCommandキー

*3:ドキュメントを読むともちろんそう書いてある

Windows 開発キット 2023っていうの買いました

Windows 開発キット 2023 っていうやつを買いました。DevKit 2023のほうが呼びやすくていいですね。

BUILDでProject Volterraとして発表されたやつがようやく販売開始した感じなんですが、日本も対象でびっくりしました。*1 販売開始当初、Microsoft Storeで99万とか99円とかで一瞬話題になりましたね。

www.microsoft.com

10月26日に在庫が復活したので注文したところ、価格設定ミスってたこともあって発送がぐちゃぐちゃになっていたらしく配達予定は28日でしたが実際届いたのは11月1日でした。

スペックを引用しておくとこんな感じだそうです。

- 32GB LPDDR4x RAM and 512GB fast NVMe storage
- Snapdragon® 8cx Gen 3 compute platform
- Ports: 3x USB-A, 2x USB-C, Mini-Display (HBR2 support), Ethernet (RJ45)

あとから知ったんですが、実装RAMが32GBなことにびっくりしました。

感想

Arm64で動くWindowsなだけでなんも変わらないですね…  Snapdragon 8c以降はCPUが仮想化対応になったのでHyper-Vも動きます。Hyper-Vが動けばWSL2も動きます。

ソフトウェア面では、最近はVSCodeもArm64で動くし、Visual StudioもまだPreviewですがArm64で動作します。 2019年頃はまだx86エミュレーションで実行されていたOfficeやOneDriveも今ではArm64で動くようになりました。3年前よりArm64でコンパイルされたバイナリもかなり増えてきた印象です。

SlackやDiscordのようなサードパーティーのアプリケーションはArm64版Windowsバイナリを提供してくれないことが多くエミュレーションで実行されます。ただ、Arm64上のバイナリエミュレーションはそれなりにはがんばるので心配するほどは遅くないです。*2とはいえ、エミュレーションのChromiumとv8で動作するElectronよりはブラウザでアクセスしたほうが速いかもしれません…*3

x86エミュレーションでADBも使えるのでAndroidデバッグできます。*4

Seeeduino Xiaoを接続したところ、ちゃんとシリアルデバイスとして認識され、Arduino IDEコンパイルから書込みまで成功しました。

最近はデバイスドライバ周りもUniversal対応になっているものが増えてきたので、C630を買ったころよりはるかに環境が整備されました。

おもしろポイント1

おもしろポイント1は、Arm64でWindows動作しているのでWSAももちろんArm64で動作します。

[ro.product.cpu.abi]: [arm64-v8a]
[ro.product.cpu.abilist]: [arm64-v8a,armeabi-v7a,armeabi]
[ro.product.cpu.abilist32]: [armeabi-v7a,armeabi]
[ro.product.cpu.abilist64]: [arm64-v8a]

Arm64でWSAが動くメリットは、Unityのil2cppでコンパイルされたバイナリがx86_64版のWindowsより安定して動いている感がありました。あと心なしか動作が早い気もする、ただ計ったわけではないです。

ただ考えてみるとArm64で動いてるWSAって、それHyper-Vで仮想化されてるただのAndroidやん……という話なのでそりゃはやいじゃんという話ではあります。

おもしろポイント2

おもしろポイント2は、中身はほとんどSurfaceだそうです。たぶんSQ3のSurface Proから画面とモデムと電池をとっぱらった結果なんじゃないでしょうか。

UEFISurfaceのものが動いているようなのですが、USB-Cで接続するとUEFI画面が表示されないのでどんなのが出ているのでしょうか… miniDP to HDMIなアダプタが手に入ったら確認してみます。

そのほか

セットアップはさすがにリモートではできない…のだけど余っているディスプレイはないので数年前に流行ったHDMIをUVCで接続できる2000円ぐらいのアレ*5で画面をみてたんですがやっぱしまぁまぁ便利ですね。1個持っとくといい。

キーボードとかの接続もめんどくさかったのですが、LenovoThinkPad トラックポイント キーボード IIが2.4GHz無線とBluetoothのデュアルスタックなのでこういう時に1枚持っていると便利でした。*6

OOBEはネットワークが必須になったバージョンでした。ローカルアカウントを1回作りたい派なので、Shift+F10で OOBE\BYPASSNRO してI get kotonakiです。

このあとMSAログインに切り替えたのですが、その時にパスワードログインが無効になってしまうので有効にしたあと一度パスワードでログインしてあげないとリモートからログインできませんでした。地味にはまりポイントです。

あと結構謎な動きをしたのが、Final Fantasy XIV 暁月のフィナーレベンチマーク(x64バイナリ)を実行したところ、ベンチマークシーンの開始5秒付近でなぜかマシンがリセットしてしまいます。イベントログを見ると、予期しないシャットダウンでした。ということなので予期しないシャットダウンらしいのですがなんのこっちゃわかりません。エミュレーションの過程で変な命令とか叩いてうっかり死んでしまったのでしょうか。そもそも動作対象外の環境なのでこれ以上は詳しく調べることはしませんでした。

このPCはここまでの設定をしたのちに、電源ケーブルだけ接続された状態で部屋の隅に押し込まれたのでした…

*1:前のSnapdragon DevKitって言ってたやつは北米だけだったはず

*2:Ryzen 9 4950XみたいなハイエンドCPUと比較するともちろん遅いです。

*3:ちなみに、2022年11月現在ChromeもArm64版が提供されていません。EdgeはArm64ネイティブなのでChromeを使うよりはEdgeを使ったほうが速いですね

*4:もちろん、WSAで動作している自分自身にもadb接続できます。

*5:https://www.amazon.co.jp/dp/B0936Q2G5G/

*6:今思えば何も考えずに接続したけど普通に使えてました。ドライバ大丈夫かな…とか何も考えてなかった

スマホ同期 あらため、電話リンク

WindowsAndroidを接続して通知とかが見られるようになる、スマホ同期(英語だとYour Phone)がWindows 11になってもうちょっと便利になったよ。というのは見ていたけど一回も使ったことなかったので使ってみたら結構おもしろいし便利だったし、実装も面白い感じだったのでまとめておきます。

そもそも何

WindowsからAndroidに接続して通知がみれる、SMSの送受信ができる。一部の機種では画面の転送とか電話の発着信もできる。

一部の機種というのは、ここに書いてあって、 Surface Duoシリーズと、Galaxyシリーズだけ。GalaxyなのはSamsungとがんばって作ってますよ、ということだから。

さらに、最新の機能を使うにはGalaxyの最近の機種か、Surface Duo 2じゃないとだめ。そうSurface Duo 2を買ったから試そうと思ったのでした。

画面転送

画面転送がアプリ単位でできます。これがわりと便利でおもしろい。

例えば、Panasonicのシーリングを操作してみたり f:id:tmyt:20220406221535p:plain

プリコネグランドマスターズをプレイしたり f:id:tmyt:20220406221723p:plain

ToDoを書き込んでおいたり

f:id:tmyt:20220406221801p:plain

というのが、Windows上から同時に起動できます

f:id:tmyt:20220406222127p:plain

Google Chat入れてないなってPlayストアからインストール中の図 f:id:tmyt:20220406222344p:plain

アプリはWindows側から起動できて、電話リンクにアプリ一覧が出てきます。

f:id:tmyt:20220406222722p:plain

ここから選ぶと、アプリが立ち上がって専用のウィンドウとして表示される。さらにこのアプリはスタートメニューとタスクバーに登録ができる(!!)

f:id:tmyt:20220406222824p:plain

タスクバーにもちゃんとAndroid側のアイコンで表示される(!!)めっちゃすごい…すごいがんばって実装されている…

f:id:tmyt:20220406222851p:plain

使ってみた感想

たくさん開くとだめらしいです。Surface Duo 2では7個?が上限らしい。

f:id:tmyt:20220406223400p:plain

ゲームが快適に遊べるほどのフレームレートでは転送されてこないです。プリグラぐらいなら遊べた。

気になるのがどうやって実装されているのかな。というところ。わかる範囲で挙動をみてみたところ、アプリごとのセカンダリディスプレイが起動しているようです。

display?.displayId?.toString() // とかすると、20以上の値がGetできる

なので、サポートされてる機種じゃないとアプリ単位での転送ができないってことらしいです。

アプリごとのディスプレイを作ってるので、Windows側から比較的柔軟に制御できるのかーかしこいなー、なんて。

メールがみれたりしてちょっと便利なのと、Androidでしか動かないアプリを起動できてちょっと便利なぐらいでたいていはWindowsでもできるので劇的にこれが便利!!!ってことはないかもしれない。ただ知っておくとたぶんすごく便利。

あと、接続中はすごい速度で電池が減っていくのでいらないときは通知パネルからOffにしておくとなおよし。

f:id:tmyt:20220406232551p:plain

スマホ同期 あらため、電話リンク

WindowsAndroidを接続して通知とかが見られるようになる、スマホ同期(英語だとYour Phone)がWindows 11になってもうちょっと便利になったよ。というのは見ていたけど一回も使ったことなかったので使ってみたら結構おもしろいし便利だったし、実装も面白い感じだったのでまとめておきます。

そもそも何

WindowsからAndroidに接続して通知がみれる、SMSの送受信ができる。一部の機種では画面の転送とか電話の発着信もできる。

一部の機種というのは、ここに書いてあって、 Surface Duoシリーズと、Galaxyシリーズだけ。GalaxyなのはSamsungとがんばって作ってますよ、ということだから。

さらに、最新の機能を使うにはGalaxyの最近の機種か、Surface Duo 2じゃないとだめ。そうSurface Duo 2を買ったから試そうと思ったのでした。

画面転送

画面転送がアプリ単位でできます。これがわりと便利でおもしろい。

例えば、Panasonicのシーリングを操作してみたり f:id:tmyt:20220406221535p:plain

プリコネグランドマスターズをプレイしたり f:id:tmyt:20220406221723p:plain

ToDoを書き込んでおいたり

f:id:tmyt:20220406221801p:plain

というのが、Windows上から同時に起動できます

f:id:tmyt:20220406222127p:plain

Google Chat入れてないなってPlayストアからインストール中の図 f:id:tmyt:20220406222344p:plain

アプリはWindows側から起動できて、電話リンクにアプリ一覧が出てきます。

f:id:tmyt:20220406222722p:plain

ここから選ぶと、アプリが立ち上がって専用のウィンドウとして表示される。さらにこのアプリはスタートメニューとタスクバーに登録ができる(!!)

f:id:tmyt:20220406222824p:plain

タスクバーにもちゃんとAndroid側のアイコンで表示される(!!)めっちゃすごい…すごいがんばって実装されている…

f:id:tmyt:20220406222851p:plain

使ってみた感想

たくさん開くとだめらしいです。Surface Duo 2では7個?が上限らしい。

f:id:tmyt:20220406223400p:plain

ゲームが快適に遊べるほどのフレームレートでは転送されてこないです。プリグラぐらいなら遊べた。

気になるのがどうやって実装されているのかな。というところ。わかる範囲で挙動をみてみたところ、アプリごとのセカンダリディスプレイが起動しているようです。

display?.displayId?.toString() // とかすると、20以上の値がGetできる

なので、サポートされてる機種じゃないとアプリ単位での転送ができないってことらしいです。

アプリごとのディスプレイを作ってるので、Windows側から比較的柔軟に制御できるのかーかしこいなー、なんて。