2024年4月28日日曜日

懸念していたことが現実になった

冠山峠道路のトンネルが開通したとのことで,林道の方に登るついでにトンネル見に行くか,と徳山ダムに向かって出発.で,現地に着いたら,

おいおいおいー,林道封鎖されとるやんけ(;´д⊂)

トンネルが開通したら林道の方は廃道にされるかも,と懸念していたが,それが現実のものになってしまった.一時的なものかもしれないけど,積極的に林道を修復する理由もなくなったので,走れるチャンスは確実に減ったはず.封鎖を確認したのは岐阜側で,もしかしたら福井側から登れるのかもしれんけど,景色がいいのは岐阜側の道なので,福井側から登っても意味がない.自分の行動範囲ではピカイチで景色が良かっただけに,ここが走れなくなるのは非常に悲しいなぁ.
あと,冠山峠道路のトンネル開通前はここを走りに来るのはドライブ目的の車しかなかったので交通量は少なかったが,今回は結構交通量多かった気がする.

つうわけで本来は通る予定がなかった冠山峠道路のトンネルを通って,能楽の里牧場なる場所に向かった.

実はあんまり期待してなかったんだけど,山頂は,木が一本もない素晴らしい眺め.しかも,360度全周にわたって視界を遮るものが無い絶景.
冠山峠道の林道が走れなくなった代わりに,いい場所見つけたヽ(´ー`)ノ

2024年3月30日土曜日

天神風の道公園で春の訪れを感じながらバイクツーリング


最近,技術的な話題はともかく,日記的な話題の blog を上げるのがだるくなってきて,めっきり更新頻度が減っている当 blog.
ここで,AI に blog 記事書かせてみたらいいんじゃね? と思ってやってみた.

入力した文章はこれ↓
====================================
次の文章を元にblogの記事を書いてください.

冬は寒かったので全然バイクに乗っていない.
今日は暖かかったので,本年初のバイクのり.
多くのライダーが集まる湖畔の里つきがせはスルーして天神風の道公園に行った.
ここは見晴らしが良く人も少ないのでお気に入り.
桜はあまり咲いてなかった.梅らしきものは咲きかけ.
====================================

出力された記事
===== ここから =================================

天神風の道公園で春の訪れを感じながらバイクツーリング

冬の間は寒くてバイクに乗る機会が減っていましたが、今日は暖かかったので今年初のバイクツーリングに行ってきました。多くのライダーが集まる湖畔の里つきがせはスルーして、見晴らしが良く人も少ない天神風の道公園を目指しました。

公園に到着すると、眼下に広がる景色に感動しました。遠くの山々まで見渡せる絶景は、まさに春の訪れを感じさせてくれます。桜はまだあまり咲いていませんでしたが、梅の花が咲き始めており、春の訪れを告げていました。

公園内を散策していると、気持ち良い風を受けてリフレッシュできました。人も少なく、静かな環境で自然を満喫することができました。

今年のツーリングシーズンは、天神風の道公園からスタートすることができて、とても良い思い出になりました。これから暖かくなるにつれて、色々な場所に出かけたいと思います。

公園情報

  • 天神風の道公園
  • 奈良県奈良市月ヶ瀬梅林
  • 駐車場あり
  • 無料

おすすめポイント

  • 見晴らしが良く、遠くの山々まで見渡せる
  • 人が少なく、静かな環境
  • 春は桜や梅の花が楽しめる

まとめ

天神風の道公園は、見晴らしが良く、静かな環境で自然を満喫できる公園です。春は桜や梅の花が楽しめるので、ツーリングの目的地におすすめです。

===== ここまで =================================

すげえよwww 「春の訪れ」とか自分では絶対書かないしそんな文才無いwww
しかも自己満足な記事ではではなく,公園情報や見どころまでまとめられて,ちゃんと他の人にとって役に立つ記事になっている.しょうもない記事を書くライターは廃業だなこれ.
これ見たら,ソースコード書くだけの人もそのうち淘汰されるだろうなぁ,というのも実感が湧いてくるね.

2024年3月24日日曜日

C++ で構造化アセンブリプログラミング

動機

原始的なアセンプラしか無い原始的な CPU のプログラミングをすることになった.
でアセンブリプログラミングの一番の萎えポイントとして,例えば C 言語だと
if(a == b){
  c = d;
}else{
  e = f;
}
みたいに書けるところが,構造化記述できないアセンブラだと
  cmp a, b
  jnz label0
  mov c, d
  jmp label1
label0:
  mov e, f
label1:
とラベルやら分岐命令やら,自分で生成しないといけないのでめんどくさいし,if がネストすると可読性も悪い.真面目にやるなら bison/flex とかでまともな構造化アセンブリ言語を設計するところだけど,そこまでやるのはなぁ... と思ったところで,C++ のクラス / 演算子オーバーロードをうまいこと使えば,構造化アセンブリプログラミングもどきが出来るのでは? と思った.
例えば,C++ で "r0 = r1;" と書いてコンパイル・実行すれば,"mov r0, r1" というテキストが得られる,みたいなイメージ.

まずは代入演算

//////////////////////////////////////////////////////////////////////////////
// Register

class RegisterObject {
public:
  RegisterObject(const char* szName) : m_szName(szName){}
  const char *Name(void) const {return m_szName;}
  
private:
  const char* m_szName;
};

class GpReg : public RegisterObject {
public:
  GpReg(const char* szName) : RegisterObject(szName){}
  
  GpReg& operator=(const GpReg& src){
    printf("\tmov\t%s, %s\n", Name(), src.Name());
    return *this;
  }
};

//////////////////////////////////////////////////////////////////////////////
// Register インスタンス

GpReg r0("r0");
GpReg r1("r1");
GpReg r2("r2");
GpReg r3("r3");

//////////////////////////////////////////////////////////////////////////////
// アセンブリプログラム

int main(int argc, char **argv){
  r0 = r1 = r2;
  return 0;
}
GpReg class は汎用レジスタをイメージしていて,特殊なレジスタがあれば RegisterObject か GpReg を継承する感じ.C++ ソースコード上の変数名 (r0 とか) は実行時には失われてしまうので,m_szName に変数名をセットしておく.
代入演算のキモは言うまでもなく "operator=" で,= が呼ばれたら mov 命令のテキストを出力する.
で実行結果:
        mov     r1, r2
        mov     r0, r1
おお,いい感じ.アセンブラだと r0 = r2 が直接代入できないので一旦 r1 を経由する,みたいなケースが多々あるが,それが 1行で書けるのはありがたい.

比較演算

次に,if-else-endif の構造化をやる前に比較演算子を定義する.
対象 CPU は,== なら cmpeq みたいに比較演算子毎に比較命令があり,その結果をフラグレジスタ f0 にセットする.条件分岐命令は f0 の値をみて分岐するかどうか決める.
class FlagReg : public RegisterObject {
public:
  FlagReg(const char* szName) : RegisterObject(szName){}
};

//////////////////////////////////////////////////////////////////////////////
// Register インスタンス

FlagReg f0("f0");

//////////////////////////////////////////////////////////////////////////////
// global な operator

FlagReg& operator==(const GpReg& a, const GpReg& b){
  printf("\tcmpeq\t%s, %s, f0\n", a.Name(), b.Name());
  return f0;
}

//////////////////////////////////////////////////////////////////////////////
// アセンブリプログラム

int main(int argc, char **argv){
  r0 == r1;
  return 0;
}
RegisterObject を継承して FlagReg を定義する. operater== で,== が呼ばれたら cmpeq 命令を出力して,== の返り値として f0 を返す.
で実行結果:
        cmpeq   r0, r1, f0
これはなんの問題もない.

if-else-endif

そしてこの取り組みの一番の目的である,if-else-endif の構造化をやってみる.
//////////////////////////////////////////////////////////////////////////////
// 構造化構文

int g_LabelCnt = 0;
std::vector<int> g_Label;

void _if(FlagReg& f){
  printf("\tjnset\t%s, _L%d\n", f.Name(), g_LabelCnt);
  g_Label.push_back(g_LabelCnt);
  ++g_LabelCnt;
}

void _else(void){
  printf("\tjmp\t_L%d\n", g_LabelCnt);
  printf("_L%d:\n", g_Label[g_Label.size() - 1]);
  
  g_Label.pop_back();
  g_Label.push_back(g_LabelCnt);
  ++g_LabelCnt;
}

void _endif(void){
  printf("_L%d:\n", g_Label[g_Label.size() - 1]);
  g_Label.pop_back();
}

//////////////////////////////////////////////////////////////////////////////
// アセンブリプログラム

int main(int argc, char **argv){
  _if(r0 == r1);
    r0 = r2;
  _else();
    r1 = r3;
  _endif();
  return 0;
}
_if ではフラグレジスタを受取り,必要な分岐命令を生成する.また if-else-endif はネストするので,分岐先ラベルの情報はスタックに push / pop する必要がある.
で実行結果:
        cmpeq   r0, r1, f0
        jnset   f0, _L0
        mov     r0, r2
        jmp     _L1
_L0:
        mov     r1, r3
_L1:
おおぉ,これこれ! これがやりたかったんだよ.この時点でこのやり方はかなりうまくいく感触を得ていたが,念の為 if がネストするケースをテストしてみたら,
コード:
//////////////////////////////////////////////////////////////////////////////
// アセンブリプログラム

int main(int argc, char **argv){
  _if(r0 == r1);
    _if(r1 == r2);
      r2 = r0;
    _else();
      r3 = r1;
    _endif();
  _else();
    r1 = r3;
  _endif();
  return 0;
}
実行結果:
        cmpeq   r0, r1, f0
        jnset   f0, _L0
        cmpeq   r1, r2, f0
        jnset   f0, _L1
        mov     r2, r0
        jmp     _L2 ←※ここ
_L1:
        mov     r3, r1
_L2:
        jmp     _L3
_L0:
        mov     r1, r3
_L3:
んー,間違いではないんだけど,jmp _L2 の飛び先は jmp _L3 しか無いので,最適化の観点では「ここ」で jmp _L3 にすべき.
この最適化をやるためには,直接アセンブリテキストを出力するのではなく,一旦中間言語とかでメモリ上に溜めておき,最後に最適化フェーズを流す,等しないといけないということがわかった.
それを解決して,あとはメモリアクセスとかラベルへのサブルーチンコールとかを実装すれば,普通に使えそう.

2024年2月12日月曜日

DualShock3 アナログ修理

DualShock3 (PS3 コントローラ,以下 DS3) のアナログ入力が変 (入力してなくても,入力がプルプルぶれる) になってきたので,ジョイスティックセンサを交換することにした.
事前情報ではジョイスティックセンサは基板にハンダ付けなので,めんどくせぇと思って分解したら,


フィルム基板をゴムでジョイスティックセンサの端子に押し付けてあって,端子部分のハンダ付けは無し.固定はセンサの一部を爪のように折り曲げて固定.これは修理容易だしこの方式が流行って欲しいと思ったが DS4 では基板ハンダ付けにのようなので,残念ながら流行らなかったらしい.
ちなみに DS3 でも基板ハンダ付けバージョンもあるらしい.自分の DS3 の型番は CECHZC2J-A2.

で,交換自体はサクッと終わって,試しに使用してみたらほぼ問題なく使えるものの,センサの入力特性に違和感が.具体的には,標準のセンサに比べて,スティックの倒し量が半分くらいで入力 100% になってしまって,要は微妙な入力が非常にやりにくくなった.

これは,センサに使われている可変ボリューム? ポテンショメーター? の特性によると思うけど,買い直すにしても販売ページにそんな事書いてないし,標準部品の特性に近いセンサの選定は難しそう.

で我慢してこのまま使い続けるかしばらく悩んだが,ダメ元で元のおかしくなったセンサの可変ボリュームを分解清掃してみることにした.更に接点が接する部分に注油して,組み直して動かしてみたところ…

ビンゴヽ(´ー`)ノ 無事無入力時のブレも治った.
結局アリエクのジョイスティックセンサいらんかった.買ったのはこれで,少なくともこれを買うのはおすすめしない.

2024年2月10日土曜日

6年越しの夢が叶う

遡ること 6年前,Ace Combat 7 (以下AC7) が PSVR 対応するということで,「コックピットに乗って空中戦,の疑似体験」ができると思って,PSVR を買った.感想としては思ったとおり「乗り物に乗ってる感」がすごくて,それまでのゲーム体験とは一線を画すものだった.
ただし,ゲーム本編は VR 非対応で,おまけみたいな VR 専用ステージ 3面が遊べるだけ,という大変残念な仕様.本編が VR 対応してれば神ゲーだったのに.しかも PSVR 自体が失敗気味で,その後遊びたいと思えるゲームが全く発売されず,大爆死(;´д⊂)
# 今から思えば,PS4 では性能が足らなくて普通のクォリティで VR ゲーム作れなかったんじゃないかと思う

そして時は流れて現在,PC 版の AC7 と UEVR というフリーソフトで,強制的に VR 化できるという情報を得たので,PICO4 を \41,640 で get.

6年間これを待ってたんだよ(゜ーÅ)ほろり
実際に遊んだ感じでは PSVR での VR 専用ステージとほぼ変わらず,ゲームとして普通に成立している.PSVR では遊べなかった本編を VR で遊べて,なおかつ PSVR よりも高解像度ということで,非常に満足度が高い.

これは大抵の非 VR ゲームに言えることだけど,特に「乗り物に乗る系」は,画面の描画範囲が現実に比べとても狭い.例えば敵機がジグザグに逃げているのを追っているとき,敵機は画面外で切り返しても自分はそれが見えず,追うのに失敗することが頻繁に起こってストレスが溜まる.
VR だと,首が動く範囲である限り敵機を視線で追い続けることができるので,敵機の切り返しにも対応できてドッグファイトが非常にやりやすい.

あと,車運転するときを思い出してもらえればわかると思うけど,現実世界で左右に曲がりたいとき,視線は真正面を見続けているのではなく,曲がる先を見ている.非 VR だとこれも描画範囲外だが,VR は首をそっち方向に向けて曲がるという自然な動作が可能で,こういうところの「実際に乗っている感」が非常に高い.

ただし,元々 VR ゲームでないもの無理やり VR 化している事から,問題点もいくつかある.
・ターゲットマーカー以外のHUD表示がされないのが最大の問題.
 ・レーダーが表示されない(PAUSEすれば見れる)
 ・残弾が表示されない
 ・機銃レティクルが表示されないので機銃当てるのは至難レベル
 ・機体姿勢・速度・高度が表示されない
・コックピット視点が使えない
 ・首の動きにコックピット描画が張り付いているので,コックピット視点は使えないので,「乗り物に乗ってる感」は大分そがれる.

そこは割り切りが必要だけど,上記を改善する MOD も開発されているっぽいので,今後に期待.


2024年1月21日日曜日

JOG 3KJ エンスト修理

 足車の JOG 3KJ が走行中にエンストするようになった.症状としては
・ガス欠の症状に非常によく似ていて,走行中に突然アクセルを抜いたかのようにエンジン回転が下がり,アクセルを開けるとわずかに回転が上がろうとするが,そのままエンストする.
・停車後しばらくセルを回すと,エンジンがかかり普通に走れる.

先人の症例を調べてみると,考えられる原因としては
(1) 燃料タンクに水が混入した
(2) 燃料系統 (キャブとか) が汚れで詰まっている
(3) 点火系が壊れた

あたり.(3) だとすると再現性が低く,プラグの火花見てもわからんだろうな,と思ったので,まずは (1) から順番に可能性を潰そうと思った.

まずは燃料タンクからガソリンを抜いて,抜いたガソリンを観察してみたが,見た感じ水は入ってなさそう.

次にキャブ掃除すっか,とキャブを外したところ,負圧燃料コックに負圧を伝えるホースが割れていることを発見.この時点で勝利を確信したwww

念のためキャブ・負圧コックを分解してみたけど,特に詰まり等はなかった.

ということで負圧燃料コックのホースを交換して完了.
今回はわかりやすい故障で良かった.

2023年9月14日木曜日

グラボ + GPU 内蔵 CPU で省電力化する

ここ最近はグラボが買い時だそうで,現に Radeon RX6600 XT の最安値が ¥54,800→¥31,800 に値下げしてたのでぽちっとな,してゲーミング PC (光るとは言っていない) 爆誕.多分 PlayStation4.8 くらいの性能はあるはず.

で,Ryzen5 5600G の内蔵 GPU (IGPU) が無駄になったなぁ,と思ったところで,
・グラボと IGPU を同時に有効化できる (IGPU Multi-Monitor)
・IGPU 側の DP 端子から,グラボ側の映像も出力できる.これは,アプリごとにどちらの GPU を使うかを選択可能.

つまり,3D ゲーム以外では IGPU を使うことによって消費電力を下げられるのでは? と思って実験してみた.設定は,
・BIOS で IGPU Multi-Monitor を有効化
・Win11 上で,デフォルトを IGPU にして 3D ゲームだけグラボに設定→参考

この状態と,IGPU を無効化してグラボだけを生かした状態,のそれぞれで,YouTube を再生したときの消費電力をワットチェッカーで観測してみる.その結果は,

●グラボのみ: 70W
●IGPU + グラボ: 51W

グラボにも省電力機能はあるだろうから,あんま変わらんだろうと思っていたが,意外にも大差がついた.当然のことながら 3D ゲームでも性能ペナルティ的なものはなく,IGPU が問題なく活かせるヽ(´ー`)ノ

2023年8月15日火曜日

さらば PlayStation

自分 PlayStation は初代~PS4 まで買ってて,そのうち PS5 も買うつもりだったけど,
・今どきはプレステ専用タイトルは殆ど無い.改めて自分が持ってる PS4 のソフトで PS4 専用タイトルを調べてみたら 11本中 1本だけ.
・プレステはそのうち修理受付が終了するので,遊べなくなるリスクがある.実際 PS2/PS3 が立て続けに壊れて困った.
・11本しかソフト持ってないのに数万円のゲーム機はコスパ悪い.
と色々デメリットが多いことに気づいて,PS5 は買わないことに決定.多分,PS5 の資金でグラボ買ったほうがいい.

で,初めて PC ゲームプラットフォームであるところの Steam 試してみたけど,大昔の PC ゲーム事情から進化していて想像以上に良い!
・偶に Steam 上でセールやってる.自分は中古のプレステソフトしか買わないけど,Steam のセールは中古プレステソフトより安いことも多い.
・PC ゲームはキーボード & マウスでしか遊べないと思い込んでいたら,最近の PC ゲームはちゃんとゲームパッドに対応している.ゲームパッド派の自分もニッコリ.

で PORTAL2 がセールでなんと¥120 で売ってたのでぽちっとな.PORTAL2 は PS3 版も持ってるんだけど,PC 版はユーザが作って公開してるステージをタダで遊べるので,無限に遊べる.こういう拡張性が高いところも PC 版の利点.
ついでに DsHidMini で PS3 コントローラを Bluetooth 接続できて,快適ヽ(´ー`)ノ

2023年7月30日日曜日

OpenWrt 22.03.5 OpenVPN の tun を NAT で接続する

ELECOM WRC-1167GST2 に OpenVPN を入れて,Andoid で外出先から自宅 LAN に接続しできるようにしてみた.
OpenWRT への OpenVPN のインストール・設定自体はここを参考に割と簡単にできるのだが,ここの説明にもある通り,Android がクライアントの場合,ブリッジモード (TAP) が使えず,トンネルモード (TUN) しか使えない.つまりそのままでは,自宅 LAN 配下の機器と通信できない.
で昔 PPTP サーバ立ち上げたときのように iptables の設定で NAT 設定すりゃいいや,と思ったら,OpenWrt 22.03.5 では FireWall の設定が iptables から nftables に変わったみたいで,そのせいでマニュアルでルールを追加する手段がなさげ?
なので,GUI で設定する方法を探してみた.

# 以下,tun0 は人によって違うので適当に読み替えて

(1) OpenVPN 設定時に tun0 を追加するときに,Firewall Setting で tun0 の zone を lan に設定する.

(2) Firewall - NAT Rules で Add して,General Setting の
- Name: てきとう
- Soure address: tun0 のサブネット
- Action: MASQUERADE

Advanced Settings の
- Outbound device: br-lan

で,無事 Android から LAN 配下の資源にアクセスできた.

ちなみに,OpenVPN クライアントとして OpenVPN for Android を使用する場合,DNS の設定を,自宅 LAN の DNS で override すると,自宅 LAN のマシン名とかで名前引きできるので便利.

2023年7月28日金曜日

4台目 OpenWRT

自分,ルータは OpenWRT 化必須で対応ルータは限られているんだけど,ELECOM WRC-1167GST2 がセール \2,838 と安くなってて,念のため OpenWRT サポートリスト確認したら対応してたので,衝動買いしたw
今のは 11年前に買った WZR-HP-AG300H で WiFi も 11n/a と古いので,そろそろアップグレードしたいと思ってたところなのでちょうどよかった.
と思ったら USB ポートないじゃん(;´д⊂)ちょっと早まったかも.

まぁ後悔しても仕方ないので,旧ルータの設定を新ルータに移して乗り換え,と思ったら,WZR-HP-AG300H 用にコンパイルした stone が WRC-1167GST2 で動かなかった.
仕方がないので OpenWRT の mipsel 環境を構築しようと過去の blog 見たら,肝心なところがリンク切れてて意味ねぇ.自分の blog のゴミっぷりを改めて反省した.

なので改めて手順を記載しておく.(基本的な手順はこれ,以下 Fedora での手順)

(1) 環境ビルドに必要なパッケージをインストールする.コマンドラインも載ってるので,コピペするだけ.
sudo dnf --setopt install_weak_deps=False --skip-broken install \
bash-completion bzip2 gcc gcc-c++ git make ncurses-devel patch \
rsync tar unzip wget which diffutils python2 python3 perl-base \
perl-Data-Dumper perl-File-Compare perl-File-Copy perl-FindBin \
perl-IPC-Cmd perl-Thread-Queue

(2) OpenWRT のソースを取得
git clone https://git.openwrt.org/openwrt/openwrt.git

(3) make menuconfig を実行して,ターゲットデバイスを設定する.
Target System --> MediaTek Ralink MIPS
Subtarget --> MT7621 based boards
Target Profile --> ELECOM WRC-1167GST2

(4) make したら,WRC-1167GST2 用のコンパイル環境が生成される.

で,問題なく stone コンパイルできて WRC-1167GST2 で動いたヽ(´ー`)ノ

で,ルータ変えた感想としては,
・ハード的には 11ac が使えるようになったが USB ストレージが使えなくなった.それ以外の差は無いと言って良い
・自分,使うのは基本有線で,WiFi で帯域が足りないシーンは無い
ので,正直変えなくても良かった気がする.