投稿日:

さて、私は神戸(三宮→石屋川→春日野道)に住み、次の4月で19年になる。元々は進学でやってきた神戸だが、住みやすさが気に入って住み続けている。

ところで大阪と言えば何が思い浮かぶだろう?

私は通天閣、たこ焼き、お好み焼き、吉本、日本橋、梅田の高層ビル群くらいのすごーくステレオタイプの印象しかなかった。勿論茶屋町とかオシャレな場所があるのは知ってるし、新今宮のスラム具合も知っている。

しかし今まで特に行ったことがないエリアがあった。私はナードなオタクなので光り輝くようなところが苦手なので、心斎橋に行ったことがなかったのだ。

今回縁あって心斎橋に行ったところ、大阪の新しい顔や、Windows 95にあったようなピンボールに触れることができたので、ちょっと書いてみる。

なぜ心斎橋に行ったか?

まずその前に、なんでそんなところに行ったか?だが、単純な話、映画を見に行ったのだ。

行ったのはキノシネマ心斎橋で、Wikipedia上では未だに2024年12月13日開業予定と書かれてる映画館である。既に営業されており映画を見ることができる。

この日はゾンビランドサガ ゆめぎんがパラダイスのドリパス門真上映を鑑賞するために大阪入りしていたので、そのついでに寄ることにした。勿論、キノシネマ心斎橋で鑑賞したのもゾンビランドサガ ゆめぎんがパラダイスである。なんと13回目の鑑賞となり、歴代最多を記録したが、まぁそこはどうでもいい。

おしゃれというかファンキーでポップでレトロだった心斎橋

何が言いたいのかサッパリわからないがそれが所感である。

心斎橋に入り一番に出迎えてくれた奇抜なのはこの壁画である。何かはわからないが、中々芸術的な奴だ。治安がよさそうな気はしない。

余談だが私は一瞬だけ赤羽に住んでいたことがあるので、治安についてはあまり気にしないほうである。

そして映画館の前あたりに来た。中々にぎわっている空間で、ファンキーで若い感じの空気が流れていた。おじさんも多くいたが、全体的には大学生くらいが多かったように思う。

そしてこれが映画館の入る心斎橋ビッグステップなるビルだ。OSシネマズの上映前のau割の宣伝にいる鳥みたいなやつがいるし、全体的にポップな感じかと思えば、緑が豊かで、カッコいい感じのゴンドラむき出しエレベーターが三基も並んで動いていた。

人生で初めて曲がるエスカレーターにも乗った。

THE SILVER BALL PLANETと初めてのピンボール台でのプレイ

そして映画館に行く途中で見つけたのが、THE SILVER BALL PLANETだ。

この店は日本最大ともされるピンボールの専門店らしく、Windows 95で3Dピンボールに親しんだ身としては非常に興味深かった。

この店を知ったのは私に同じくadiary利用者である.iso/plant氏のブログ記事、様々な報告書 2026夏編にあった『THE SILVER BALL PLANETの小噺』によるところが大きい。

中には様々なピンボール台が設置されており、新台まであった。

ピンボールと言えばWindows 95の頃に電子化されたゲームだから、さぞ古いものだろうと思っていたのだがトイ・ストーリー4の台があって驚いた。トイ・ストーリー4は2019年6月21日公開なので、1995年には電子化され物理台がないと考えている状態から見ると、かなり新しいものということになるが、恐らく今でも作られ続けているのだろう。英語版のメーカーページを見ると、この台は2022年に製造されたものだそうだ。

ニュースサイトのToy Story 4 pinball announced by Jersey Jack Pinball companyの記事によると、コレクターズエディションは1,000台、限定版は5,000台のみ製造され、限定盤は青フレームで12,000USD、コレクターズエディションは赤フレームで15,000USDということのようだ。

これは青フレームなので限定版のようだが、すると本日の為替レートでは約186万円するようだ。運送費や関税なども考えると200万以上する代物だろう。すごい。

サウスパークの台でも遊んだが、こんな下品なものがアメリカという国に存在してていいのかと笑ってしまった。

ピンボールはたった100円でプレイでき、それも結構遊べるので、非常に面白かった。

ボールがフラッパーの間をすり抜けたり、横の溝から落ちたりするのが悔しかったので、調べたところ、ピンボールは台を揺らして玉の軌道を変えることがルールにあるとあり、驚いた。そういや3Dピンボールも揺らせた気がする。

今回は500円玉と万札しかなく、十分に遊べなかったが、次来るときは百円玉と千円札を持ってこようと思った。

店内には千円札の両替機もあり、千円札があれば両替して遊べるようになっている。また懐かしい感じのコーラ瓶の自販機もあり、雰囲気が良かった。

ビッグステップにあった面白いもの

スケスケの中をエスカレーターが動いているのが見え、動輪の動きなどを眺められるのは面白かった。

他にもレトロな感じのアナログ対戦ゲームもあり、中にはATARIのPONGもあったが、残念ながらこのPONGは2017年に作られたもので#ATARI_TABLE_PONG)、日本ではタイトーが販売しているようだ。

キャラクターグッズ自販機も遊び心のあるデザインで、中々面白かった。

全体的に面白いビルだった。

心斎橋を歩く

来るときは御堂筋線の心斎橋駅から来たが、帰るときは阪神なんば線から帰ろうということで、心斎橋を南下するように歩いていた。

まず目に入ったのが、このストリート的にステッカーがベタベタ貼られた電柱類である。しかも単なる電柱かと思ったらマーブル模様のロボットの姿をしていて無駄にアート。関節まで丁寧に作られているほどだ。

その先にはフォントからして変なホテルがあったり。

ちんちん卍にしか見えない、ちんちろりん卍という店があった。~~卍という表現があるのは知っていたが、店の名前になっているのは初めてみた気がする。

これがあるなら株式会社マジ卍とかあっても驚かないぞ。

この辺りは一応商店街なのか、それっぽい看板も生えていた。久左衛門。

道頓堀へ抜け、闊歩する

道頓堀と言えばグリコが思い浮かぶが、出てきた通りが変な場所だったので、知らない道頓堀が見えた。

写真を拡大すると「シャッターは文化や!」という文字が見え、謎に大阪弁だが、文化シヤッターそのものは東京発祥の東京の企業らしい。

ゆったり漂う水上バスや周りの明かり、道頓堀と書かれた壁など、全体的に雰囲気がとても良かった。

そして少し歩くとそこには道頓堀と書かれたいい感じのネオンサインが出ていた。サカナクションの新宝島みたいな感じだ。

奥には大勢の人が見え、なんかすごかった。

見た感じネオン管に見えるので、LED化などはされてなさそうだった。渋い。

ちなみにネオンサインは今でも作られていて、例えば神戸市灘区の二号線沿いにあるカンサイネオン電気という会社はビルに季節ごとのネオンサインを出しており、見ていて楽しい。

道頓堀の文字をくぐった先には大勢の人がいて、古風な料亭のようなものも見え、大阪にこんなところが…と、この日何度目かわからない驚きを味わっていた。

そして日本橋のほうに目をやるとnamba HIPSというHEP FIVEの親戚みたいな名前のビルがあり、何やら禍々しい感じの見た目のところに、ご神体の様なものを抱えていてなんかすごかった。シャングリ・ラのアニメに出てきそうな見た目だ。

あとがき

そもそも神戸引きこもりで大阪にあまり来ないのもあるが、こういった雰囲気の場所に来ることが人生において皆無なので、すごく新鮮だった。

心斎橋は想像以上にいいところだったし、夜の道頓堀の雰囲気も良かった。

今回は映画を見るために来たわけだが、こういうところにふらっと出てこれるのも三宮住みのいいところだな~と思うのであった。

次回ピンボールをするときは腰を屈めて台に対して低めの目線を持ち、揺らすプレイにチャレンジしてみたいところだ。

更新日:
投稿日:

今使っているチェアがだいぶヘタってきて、そろそろダメそうなので買い換えたいがディスコンになっていて困ってしまった…。

椅子に求めるもの

個人的に椅子に求めるものは次のようなものだ。

  • 汚れに強く、清掃性が高い
  • 加水分解しない
  • 座面に程よいクッション性があり、硬さやツッパリ感がない
  • 上で胡坐をかける
  • 一番高い状態のまま机の下に入れられる

ファブリック vs メッシュ vs レザー

で、これを求めると選択肢としてはこの辺りだろう。

まずファブリック素材は汚れに弱く、清掃性も終わってる。家具屋の座面や、会社の椅子などは悲しいほど汚れているし、悪臭を放っていることさえある。あんなのは耐えられない。

次にメッシュチェアだが、こちらは突っ張っていて苦手だ。それと椅子の端っこ、太ももが乗る部分が硬くて痛い。アーロンチェアだろうがオカムラだろうが痛いものは痛い。

すると残るのは革張りになってくる。革張りの椅子は汚れが染み込まず、表面の汚れも落としやすい。また、座り心地はファブリック並みによく、親水性がないためクッションの中に湿気が溜まることがないのもメリットだ。

今の椅子

三年ほど使っていて、食べこぼしや飲みこぼし、血などの付着があったりもしたが、軽微なものはトイレクイックル、油汚れであっても食器洗い洗剤で擦れば綺麗になくなるので、汚した内容に対する状態はいい。

構造的には左右にパイプが張っていて、その間に革をハンモックのように張っている面白い構造だ。クッションと呼べるものはないが、革の伸縮によるクッション性がある。

しかし三年も使っていると革が伸びてダメになってくる。これは三代目なのだが、四代目はどうにも手に入りそうにない。

素材はニトリのNレザーで、そのためか加水分解など一切せず、非常に表面の状態はいいのが特徴だ。

更に肘置きがなく、机の下にそのまま入るのも便利だ。

ただ本来は肘置きで背もたれを固定する構造のため、肘置きがないと背もたれが前に折れてくるのが難点だ。この椅子は運搬の都合、背もたれを半分に折って小さくできるようになっているのだ。

これも初期のころは何もせずとも立っていたのだが、ついここ半年ほどで具合が悪くなってきている。

そこでガムテープで固定しているのだが、ガムテープだと緩んで機能しなくなることもあり、なんとも言えない。

背もたれが倒れているのは非常に腰によくないので、限界を感じる。

因みにこの椅子は製品としてはニトリのNシールドカルカというものだ。

次の椅子探しの旅

類似品を探して発見するリプロダクトというジャンル

ニトリ製品はOEMも多く、ニトリでディスコンになった後もホムセンなどで見かけることがあるので調べていたが、残念ながら同じものは見つからなかった。

ただ類似品はECサイト上に多くあり、調べていくうちにイームズ社の開発したアルミナムチェアのリプロダクトであることが分かった。リプロダクトというのは要は設計の権利が切れたもののコピー品のことである。

「イームズ アルミナムチェア リプロダクト」とかでググると山のように出てくる。ローバックならニトリビジネスにもオフィスチェア(EX338 GTS129 BK)として存在した。

オフィスチェア(EX338 GTS129 BK)を実際に買ってみたが、座面実測が44cmで今の椅子が50cmなので、6cmも低く、更に座面が後ろに倒れており、作業椅子としては使えそうになかった。いわゆるエグゼクティブチェアの類に近いと思うが、グランフロント大阪にあるニトリビジネスの展示などを見る限り、会議室での使用を想定してそうだった。

しかし、イームズ アルミナムチェア リプロダクトが、これほど人気のジャンルならニトリさんにもイームズ アルミナムチェア リプロダクトとしてもう一度出しなおしてほしいものである。

まぁないものは仕方がないので諦めるしかない。

家具屋巡礼

実際に座ってみないことには何とも言い難いので、実物を展示している店舗を探すことにした。

まずそんじょそこらの家具屋にはオフィスチェアがそもそも置いてない。これを置いている家具屋を探すだけで一苦労である。

ググって出てくるオシャレな家具屋には確実にない。置いてあるのはニトリ、IKEA、東京インテリア家具、大塚家具くらいだ。

ニトリに期待できる品がない以上、他をあたるしかないだろうと思って、まず訪問したのが新神戸のプラスカーサだったが、こちらにはハーマンミラーのアーロンチェアやセイルチェアしかなかった。

次に向かったポートアイランドのIKEAには革張りのオフィスチェアで求めるものがなく、ファブリックが多かったと思う。向かいの東京インテリア家具には何の期待もせずに向かったがハーマンミラーとオカムラのチェアはあったものの、そもそもハーマンミラーとオカムラに求める品がない私には意味がなかった。

最後に向かったのは大阪南港にある大塚家具のショールーム、IDC大塚家具大阪南港だ。

ここは非常に品ぞろえが多かったが、リプロダクト品の扱いはなかった。予約なしで訪問したが、ここでは店員からアドバイスを受けることができた。

一番近いのはオカムラのコンテッサセコンダの総革張りとのことだった。しかし本革で価格は70万円、コンテッサの売りは肘置きということで、「肘置きが不要ならそれだけの価値はなく、更に本革はガシガシ汚す用途では不向きという。価格的に無理なのもあり、撤退することにした。

ここまでの旅で分かったこととしては、革張りの椅子にはエグゼクティブチェア、要するに社長椅子が多く作業に不向きなものが多いということだった。そして作業椅子は代替ファブリックかメッシュである。

結局次の椅子をどうするか

ひとまず世の中の椅子はファブリックかメッシュが多く、革張りがあっても社長椅子では話にならないし、作業椅子でも価格が70万では話にならない。

そこで着眼したのがゲーミングチェアだ。ゲーミングチェアは革張りが多く、ゲームをしながら使うものなので飲み食いが想定されている。肘置きは高さ調整が効いたり、外せそうな見た目のものも多く見えるので、ここにならチャンスがないかということを思ったので、次はゲーミングチェアを見ていこうと思う。

Value-DomainのダイナミックDNSエンドポイントは60秒以内に叩くとエラーが返ってくるので、これを回避するためのDDNSの仕組みを作った話。

やったこと

まず、Value-DomainのDNS APIに対し、既存のaレコードをバルクで差し替えるためのツールとしてvd-ddns_v4.plを作った。

そしてhotplug.dにPPPoEインターフェースのIPが変わったときに、このスクリプトを蹴る処理を書いた。

この記事の前提構成

OpenWrtにIPv4用のPPPoEインターフェースがある。

やったこと

  1. 今回利用するのに必要なPerl周りをセットアップする。ストレージの空きが3.2MBほど必要
  2. value-domain-dns-util/root配下とか適当な場所に放り込む
    • opkg install openssh-sftp-serverでSFTPを導入しておくとファイル移動に便利
  3. vi /etc/hotplug.d/iface/40-pppoeとかして、OpenWrtのインターフェースが変化したときのHookを作る

     #!/bin/sh
     # デバイスが存在しなければ終了
     [ -n "$DEVICE" ] || exit 0
     # リンクアップでなければ終了
     [ "$ACTION" = ifup ] || exit 0
     # インターフェース名がPPPoEのものでなければ終了
     [ "$INTERFACE" = wanppp ] || exit 0
     # pppoe-wanpppのIPv4アドレスを取得
     pppoeaddr=$(ip -4 addr show pppoe-wanppp | head -2 | tail -1 | awk '{print $2}')
     # ログに吐く
     logger -t "DDNS - PPPoE IP" $pppoeaddr
     # DDNSもどきを叩く
     /root/vd-dns-util/vd-ddns_v4.pl 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' example.com $pppoeaddr hoge fuga piyo
     # 結果をログに吐きたいが何故か動いていない
     if [ $? -eq 0 ]; then
     logger -t "DDNS - UPDATE SUCCEED"
     else
     logger -t "DDNS - UPDATE FAIL"
     fi
    
  4. PPPoEインターフェスをRestart

  5. Value-Domainのコンパネで指定したドメインのaレコードが更新されていることを確認

備考

一般的にDNSレコードの浸透時間は更新前に浸透していたTTLに依存し、Value DomainのAPI経由で普段から操作している場合は120秒以下にならないため、最大120秒のダウンタイムが発生するが、理論上は公式のDDNS機能と大差ないはずと思われる。

aレコードのみの対応にしているのは私の環境だとIPv6は変動しないが、v4はそれなりの頻度で変わるためだ。

運用しているMastodonのv4が変わったのに気づかないまま疎通できないインスタンスが出てくることがしばしばあり、手動で対応するのが手間なのと、毎回一日くらい気づくのに遅れるので今回自動化に踏み切った。前々からやり勝ったのだが、中々腰が重く進んでいなかった。

そもそもこの手のものは監視システムで検知できて然るべきなので、おいおい監視システムの構築もしていきたいところだ。

更新日:
投稿日:

確認環境

OpenWrt 24.10.0

やり方

opkg install perl
opkg install perlbase-essential
opkg install perlbase-json-pp
opkg install perlbase-scalar
opkg install perlbase-xsloader
opkg install perlbase-dynaloader
opkg install perlbase-list
opkg install perlbase-bytes
opkg install perlbase-findbin
opkg install perlbase-http-tiny

# OpenWrtにはPerlのSSLモジュールがないので親切な人が作ってくれてるものを使わせていただく
# https://jw2013.github.io/openwrt-packages/
opkg install libustream-mbedtls
wget https://jw2013.github.io/openwrt-packages/public.key
opkg-key add public.key
echo 'src/gz pkgs-by-jw2013 https://jw2013.github.io/openwrt-packages/24.10/x86_64' >> /etc/opkg/customfeeds.conf
opkg update
opkg install perl-net-ssleay
opkg install perl-io-socket-ssl
rm public.key

増加する容量

キビバイトやメビバイトのバイト変換やトータルビバイトはLLMに換算させた欠化を書いているので誤りが混ざっている可能性がある。大まかには合っていると思うが…。

pkg size byte
perl 1.27 MiB 1,331,692
perl-io-socket-ssl 124.00 KiB 126,976
perl-net-ssleay 153.61 KiB 157,297
perlbase-autoloader 3.04 KiB 3,113
perlbase-b 106.07 KiB 108,616
perlbase-base 4.27 KiB 4,372
perlbase-bytes 1.23 KiB 1,260
perlbase-class 3.02 KiB 3,092
perlbase-config 18.55 KiB 18,995
perlbase-cwd 11.31 KiB 11,581
perlbase-dynaloader 4.50 KiB 4,608
perlbase-errno 3.22 KiB 3,297
perlbase-essential 23.79 KiB 24,361
perlbase-fcntl 7.36 KiB 7,537
perlbase-feature 2.68 KiB 2,744
perlbase-file 72.30 KiB 74,035
perlbase-filehandle 1.81 KiB 1,853
perlbase-findbin 1.98 KiB 2,028
perlbase-http-tiny 12.98 KiB 13,292
perlbase-i18n 21.21 KiB 21,719
perlbase-integer 1.12 KiB 1,147
perlbase-io 67.71 KiB 69,335
perlbase-json-pp 11.96 KiB 12,247
perlbase-list 23.14 KiB 23,695
perlbase-locale 10.98 KiB 11,244
perlbase-mime 6.50 KiB 6,656
perlbase-params 4.02 KiB 4,116
perlbase-posix 40.45 KiB 41,421
perlbase-re 285.55 KiB 292,403
perlbase-scalar 1.60 KiB 1,638
perlbase-selectsaver 1.27 KiB 1,300
perlbase-socket 19.49 KiB 19,958
perlbase-symbol 1.94 KiB 1,987
perlbase-tie 18.40 KiB 18,842
perlbase-unicore 779.16 KiB 797,860
perlbase-utf8 1.24 KiB 1,270
perlbase-xsloader 2.54 KiB 2,601
total 3.08 MiB 3,230,188
投稿日:

カスタムキャスト側でCOM3D2のプリセットを再現しようとすると、色周りの設定が数値指定できない関係で難しすぎたので、何とかしようとして見つけた方法。

一撃で同じキャラを持ってこれるのでだいぶ楽。

必要なもの

  • スマホとPCを繋ぐためのUSBケーブル
  • バイナリエディタ
  • COM3D2
  • カスタムキャスト

確認環境

Env Ver
Android 16
COM3D2 2.29.4
カスタムキャスト 1.04.01

やり方

  1. スマホをUSBケーブルでPCに繋ぐ
  2. スマホ側の接続形態を充電からファイル転送モードにする
  3. カスタムキャストを開いて適当に服・体プリセットをセーブする
  4. 内部共有ストレージ/Android/data/jp.customcast.cc2/files/Presetを開き、保存したプリセットを取り出す
  5. COM3D2を開き、カスタムキャストで使いたいキャラのエディット画面を開き、服・体プリセットを保存する
  6. バイナリエディタでCOM3D2のプリセットファイルを開き、454E44AE426082を検索し、そこより先にあるバイナリコードをすべてコピーする
  7. カスタムキャストのプリセットを開き、454E44AE426082を検索し、そこより先にあるバイナリコードを、先ほどコピーしたCOM3D2のバイナリコードですべて上書きし、保存する
  8. 保存したカスタムキャストのプリセットファイルを内部共有ストレージ/Android/data/jp.customcast.cc2/files/Presetに戻す
  9. カスタムキャストを開き、キャラエディットからプリセットをロードする

備考

恐らくファイルヘッダ以外ほぼ互換だと思われるが、ヘッダのリプレースが面倒なのでボディを書き換えることで達成した。

当たり前だがMODとかは反映されない。

おまけ

データを個別に取得して弄れるようにしようとツールを書こうとしていたが、パラメーターが多いのと、フォーマットが異なるものがあり、解析に飽きたので調べた残骸として残しておく。

using System.Diagnostics;
using System.Text;

class Program {
    static void Main(string[] args) {
        string filePath = @"C:\path\to\pre_Dummymaid_20260222134142.preset";

        if (!File.Exists(filePath)) {
            Debug.WriteLine($"ファイルが見つかりません: {filePath}");
            return;
        }

        byte[] fileData = File.ReadAllBytes(filePath);
        Debug.WriteLine($"ファイル読み込み完了: {fileData.Length} bytes");

        var obj = new ParamFinder(fileData);

        var MuneL = obj.FindBodyValue("MuneL");
        var MuneS = obj.FindBodyValue("MuneS");
        var MuneTare = obj.FindBodyValue("MuneTare");
        var RegFat = obj.FindBodyValue("RegFat");
        var Hara = obj.FindBodyValue("Hara");
        var RegMeet = obj.FindBodyValue("RegMeet");
        var KubiScl = obj.FindBodyValue("KubiScl");
        var UdeScl = obj.FindBodyValue("UdeScl");
        var EyeSclX = obj.FindBodyValue("EyeSclX");
        var EyeSclY = obj.FindBodyValue("EyeSclY");
        var EyePosX = obj.FindBodyValue("EyePosX");
        var EyePosY = obj.FindBodyValue("EyePosY");
        var EyeClose = obj.FindBodyValue("EyeClose");
        var EyeBallPosX = obj.FindBodyValue("EyeBallPosX");
        var EyeBallPosY = obj.FindBodyValue("EyeBallPosY");
        var EyeBallSclX = obj.FindBodyValue("EyeBallSclX");
        var EyeBallSclY = obj.FindBodyValue("EyeBallSclY");
        var FaceShape = obj.FindBodyValue("FaceShape");
        var MayuY = obj.FindBodyValue("MayuY");
        var HeadX = obj.FindBodyValue("HeadX");
        var HeadY = obj.FindBodyValue("HeadY");
        var DouPer = obj.FindBodyValue("DouPer");
        var Sintyou = obj.FindBodyValue("sintyou");
        var Koshi = obj.FindBodyValue("koshi");
        var Kata = obj.FindBodyValue("kata");
        var West = obj.FindBodyValue("west");
        var MuneUpDown = obj.FindBodyValue("MuneUpDown");
        var MuneYori = obj.FindBodyValue("MuneYori");
        Debug.WriteLine($"MuneL: {MuneL}, MuneS: {MuneS}, MuneTare: {MuneTare}, RegFat: {RegFat}, Hara: {Hara}, RegMeet: {RegMeet}, KubiScl: {KubiScl}, UdeScl: {UdeScl}, EyeSclX: {EyeSclX}, EyeSclY: {EyeSclY}, EyePosX: {EyePosX}, EyePosY: {EyePosY}, EyeClose: {EyeClose}, EyeBallPosX: {EyeBallPosX}, EyeBallPosY: {EyeBallPosY}, EyeBallSclX: {EyeBallSclX}, EyeBallSclY: {EyeBallSclY}, FaceShape: {FaceShape}, MayuY: {MayuY}, HeadX: {HeadX}, HeadY: {HeadY}, DouPer: {DouPer}, Sintyou: {Sintyou}, Koshi: {Koshi}, Kata: {Kata}, West: {West}, MuneUpDown: {MuneUpDown}, MuneYori: {MuneYori}");
    }
}

class ParamFinder {
    private Byte[] FileData;

    static byte[] CreateBinaryStringBytes(string text) {
        using var ms = new MemoryStream();
        using var writer = new BinaryWriter(ms, Encoding.UTF8);
        writer.Write(text);
        writer.Flush();
        return ms.ToArray();
    }

    /// <summary>
    /// バイト配列内から指定パターンの最初の出現位置を返す (見つからなければ -1)
    /// </summary>
    static int FindPattern(byte[] data, byte[] pattern) {
        int limit = data.Length - pattern.Length;
        for (int i = 0; i <= limit; i++) {
            bool match = true;
            for (int j = 0; j < pattern.Length; j++) {
                if (data[i + j] != pattern[j]) {
                    match = false;
                    break;
                }
            }
            if (match)
                return i;
        }
        return -1;
    }

    public ParamFinder(Byte[] fileData) {
        this.FileData = fileData;
    }

    public int FindBodyValue(string subject) {
        byte[] signature = CreateBinaryStringBytes(subject);

        int sigOffset = FindPattern(this.FileData, signature);
        if (sigOffset < 0) {
            throw new Exception($"エラー: データセクションのシグネチャ '${subject}' が見つかりませんでした。");
        }

        using var ms = new MemoryStream(this.FileData, sigOffset, this.FileData.Length - sigOffset);
        using var reader = new BinaryReader(ms, Encoding.UTF8);
        reader.ReadString();
        reader.ReadString();
        reader.ReadInt32();
        reader.ReadInt32();
        reader.ReadString();
        reader.ReadInt32();
        reader.ReadInt32();
        return reader.ReadInt32();
    }

}