2025年4月26日土曜日

SG-1000II コンポジット化

RF→HDMI変換器をしまい込んで出てこなかったので、先人の知恵を借りてSG-1000IIのコンポジット化をしたので簡単なメモ。

参考にした先人のページはこちら……なんだけど、goo blogサ終のアナウンスが出ていて、最終更新から数年経ってるし、近々消えてしまうのかなぁ……とりあえず今回参考にしたページについてはarchive.orgに拾ってもらえました。

で、同じ旧型だし、これを参考にやれば良いんだな……ってバラしてみたら、このページで扱ってる基板は「171-5141 ©SEGA 1984」の刻印、一方で手元の基板は「171-5168 ©SEGA 1984」で同じ年でもレイアウトがだいぶ違う。ただ、幸いな事に改造に影響する[C16][R41][R42]の部品番号は同じに見えたので、基本的には同じ修正を適用する事でコンポジット化できました。

元記事の説明に出てくる端子がどこに相当するか写真で残しときます。

音声についてはRFスイッチを外しても、すぐ横にICが並んでいてあまりスペース取れそうになかったので元記事みたいなミニジャックを綺麗に取り付けるのは諦めて、RFスイッチの位置にRCAを外にせり出す形で無理やり取り付け。そのままだと蓋が閉まらないので少し削りました。こちらは端子周辺のレイアウト・配線はほぼ同じでわかりやすい。追記にあったノイズ対策はやってません。フィルタはまだしも直流カットはやったほうが良いかもしれないけど。



2025年3月9日日曜日

PC-G850とg800とApple Silicon

ポケコンPC-G850を手に入れたついでに、そのエミュレータであるg800をApple Siliconなmacでコンパイルしたので、そのメモ。

基本的にはbrew環境のSDL2を使ってコンパイルしただけで、手直しはほんのちょっとです。brewだけインストール済みって人はbrew install sdl2だけしてもらえたらって感じ。

コードで直さなきゃいけないのは以下の点だけ。基本的には古のUNIXの修正で良くやるやつで、stri*系とmemi*系をstrcase*系に直す、MAX_PATHをPATH_MAXに直す(今どきそれで良いのか?ってのは別の話)、足りてないincludeと標準関数名との衝突を避けるリネームをするだけ。

あとはmakeで警告などは出るものの、最後まで通りました。

diff --git a/basic.c b/basic.c

index 9764b01..0860a6e 100644

--- a/basic.c

+++ b/basic.c

@@ -671,7 +671,7 @@ static int encodeNumDms(uint8 *num, const uint8 *str, int dms)

        } else

                sign = 0x00;

 

-       if(strnicmp((const char *)p, "&H", 2) == 0) { /* 16<90>i<95>\<8B>L */

+       if(strncasecmp((const char *)p, "&H", 2) == 0) { /* 16<90>i<95>\<8B>L */^M

                int i;

                uint32 x = 0;

                uint8 dec[8 + 1], *q;

@@ -3213,7 +3213,7 @@ uint8 *skipBlank(const uint8 **p)

 */

 int peekSymbol(const uint8 **p, const uint8 *symbol)

 {

-       return memicmp(*p, symbol, strlen(symbol)) == 0;

+       return strncasecmp(*p, symbol, strlen(symbol)) == 0;^M

 }

 #define peekSymbol(p, symbol)  peekSymbol(p, (const uint8 *)(symbol))

 

@@ -5468,7 +5468,7 @@ static int staErase(struct Basic *bas, const uint8 **p)

 */

 static int staFiles(struct Basic *bas, const uint8 **p)

 {

-       char path[MAX_PATH] = "";

+       char path[PATH_MAX] = "";^M

        uint8 ch;

 

        if(!isTerm(p))

@@ -5614,7 +5614,7 @@ static int staGoto(struct Basic *bas, const uint8 **p)

 

 /*

 */

-static void pause(struct Basic *bas)

+static void pause800(struct Basic *bas)^M

 {

        if(*pauseWhenPrint & 0x04)

                while(getKeycode() != GKEY_RETURN)

@@ -5688,7 +5688,7 @@ static int staGprint(struct Basic *bas, const uint8 **p)

                        return ERR_10;

        }

 

-       pause(bas);

+       pause800(bas);^M

        return ERR_OK_NEXT;

 }

 

@@ -6552,7 +6552,7 @@ static int staOpen(struct Basic *bas, const uint8 **p)

 {

        int err, fileno = 1, mode = 0;

        uint8 *filename;

-       char path[MAX_PATH];

+       char path[PATH_MAX];^M

 

        if((err = fetchStr(bas, &filename, p)) < 0)

                return err;

@@ -6967,7 +6967,7 @@ static int staPrint(struct Basic *bas, const uint8 **p)

 

        if(isTerm(p)) {

                *noWrap = 0x00;

-               pause(bas);

+               pause800(bas);^M

                return ERR_OK_NEXT;

        }

 

@@ -7050,7 +7050,7 @@ static int staPrint(struct Basic *bas, const uint8 **p)

                        return ERR_10;

        }

 

-       pause(bas);

+       pause800(bas);^M

        return ERR_OK_NEXT;

 }

 

@@ -8028,7 +8028,7 @@ static int getKeywordFromName(int *code, const uint8 *name)

                        }

 

        /* RESERVED<82><A9>? */

-       if(strnicmp((const char *)name, "RESERVED", 8) != 0)

+       if(strncasecmp((const char *)name, "RESERVED", 8) != 0)^M

                return ERR_OK;

        for(p = name + 8; *p == ' '; p++)

                ;

diff --git a/iocs.c b/iocs.c

index 3cb47d1..6e1ed54 100644

--- a/iocs.c

+++ b/iocs.c

@@ -1516,13 +1516,13 @@ uint8 getChrcode(int cursor)

 

                        /* <83><8D><81>[<83>}<8E><9A><81>E<83>J<83>i<95>ϊ<B7><83>e<81>[<83>u<83><8B><82><A9><82>猟<8D>????<EA><92>v<82><B7><82><EA><82>΃L<83><85><81>[<82>ɓ<FC><82><EA><82><E9> */

                        for(r = table; r->roman != NULL; r++)

-                               if(memicmp(roman, r->roman, strlen(roman)) == 0) {

+                               if(strncasecmp(roman, r->roman, strlen(roman)) == 0) {^M

                                        if(strlen(roman) == strlen(r->roman)) {

                                                strcpy(queue, r->kana);

 

                                                if(memory[0x7901] & 0x08) {

                                                        for(d = dai_sho; d->dai != NULL; d++)

-                                                               if(stricmp(queue, d->dai) == 0)

+                                                               if(strcasecmp(queue, d->dai) == 0)^M

                                                                        strcpy(queue, d->sho);

                                                        memory[0x7901] &= ~0x08;

                                                }

diff --git a/menu.c b/menu.c

index 9f84189..1dc1642 100644

--- a/menu.c

+++ b/menu.c

@@ -14,6 +14,7 @@

 #      include <unistd.h>

 #      include <sys/types.h>

 #      include <sys/stat.h>

+#      include <dirent.h>^M

 #endif

 #include "g800.h"


2025年2月15日土曜日

X68000 Zのキーボードまとめ

X68000 ZのEAKのキーボード、色々と曰く付きだったんだけど、Z2祭りにより気持ちが高まったので、少し調べてみたのでまとめ。

調べたキーボードは

  • Hackers Edition
  • Early Access Kit
  • Product Edition
基板に書かれたバージョンは全部同じで「V1 20220823」でした。ただ、Hackers Editionだけは2つ基板に違いがあります。
  1. X68000 Zのシルク印刷がない
  2. 制御マイコン付近のR0(153)が存在しない
R0はVCC-GND間に15kΩを刺してるようです。これ、Hackers Editionでなんらかの問題に気づいて、電源ノイズが問題だと思って入れた対策かな……

そして、Early Access KitとProduct Editionの違いは、電解コンデンサの容量。Hackers EditionとEarly Access Kitは220uF、Product Editionではこれが10uFに差し替えられてる。220はUSBにはでかすぎ。刺した瞬間にコンデンサにチャージするための突入電流が大きくて、ネゴシエーション前に許された電流上限を越えて切断されてるんでしょう。実際、自分はHackers Editionをいろんな環境で使ってきてるけど、Product Edition以外でもわりと挙動は怪しくなりがちでした。

今までコミュニティでは2つの対処方法があったようで、1つはGOROmanさんのコンデンサを10uFに交換する方法、もう1つはVbusに10Ωを直列に挿す方法。後者は電圧降下0.2V程度なので許容範囲との報告だったんですが、自分が以前計測した感じだと全てのLEDが点灯すると40mAくらいまで電流値が上がるので、その時はおそらく0.4Vくらいの電圧降下となり少し不安ありです。GOROmanさんの方は大正解なんですが、もしかしたら立場上あまりハッキリ言えなかったりするかもしれないので、変わってここで大暴露。10uFに交換するのが、Product Edition化改造としては正しい方法です。おそらく公式の修理も同じ対応かと思います。

まとめると

EditionX68000 ZシルクR0電解コンデンサ
Hackers Editionなしなし220uF
Early Access Kitありあり220uF
Product Editionありあり10uF

となります。

さて、実際の作業方法です。

まず裏面の下側の3つのゴムを剥がして、隠しネジを見つけます。この3つの隠しネジと上段の穴の中にある3つのネジ。この計6個のネジを外すことでキーボードが御開帳となります。ゴムはピンセットで引っ掛けてはずせば、そんなにダメージ与えず元に戻せる形ではずせます。中央がちょっと各ネジっぽくなってるけど、ここはシール剥がさなくて大丈夫。罠です。

ネジが外れたら開いていくのですが、爪で止められているのでスマホを開く道具とか使って開きましょう。手前側からが開けやすいです。ぶっちゃけこのキーボードに限っては爪折れても問題ないのでバシッと。ただ、無理に力加えるとカバー全体がバキッといくかもしれないので、全体が歪まないよう気をつけつつ。

蓋を外したら次はこれ。写真の通りキーキャップを外してください。下にネジがあるのがこの5つのキーキャップです。見えるネジを全て外す事で基板が下面ケースから外れます。

キーキャップ外す時は道具揃えた方が安心です。自分は過去にキャップ外そうとして貴重なレトロマシンの軸をへし折ったことが何度も……こういうやつ↓買っときましょう。ほんと便利なんで。

そして最後に電解コンデンサの交換。

中央付近に電解コンデンサ、そのすぐ下にC5、R0と見えるかと思います。コンデンサはたぶんスルーホールじゃないと思うので、片足ずつハンダ小手で温めて引っ張れば簡単に外れます。それかペンチでバッサリ切り落とすのも全然あり。(2/15訂正:綺麗にハンダを剥がして確認した方の情報によるとスルーホールのようです。外しにくい時は足が抜けるよう上方に垂直に引っ張ってみて下さい。)

という感じで、作業としてはわりと簡単だけど、キーボード分解する時にケース傷つけたりとか、それなりの事は起きうるので、自分で作業する場合は自己責任で。慣れてない人は条件(前回のクラファンでEAK、今回のクラファンでZ2購入)を満たしてれば無償で直してくれるみたいなので、無理せず頼んじゃった方が良いと思います。一日たりとも手放せない or 魔改造大好きって人はこの方法でやっとけば、とりあえず電気的にはオマ環にはなりにくいのでないかと。

2024年12月28日土曜日

mac mini 2024とintel資産運用

前ふり

mac miniのARM移行については、DAW系ソフトとかも含め心配事が多いので踏ん切りがつかなかったのですが、mac mini 2024の超小型化に心動かされ、頑張って移行する事にしました。

一般ソフトの移行

最近のやつなら、ほぼUniversalでパッケージされていて、ARMで起動すればARM版が動いてくれます。万が一古いIntelバイナリだったとしても、Rosetta 2経由で快適に動きます。例えばVLCのビデオエンコードとかはIntelバイナリを変換して動かした方が速いくらいだし、Unreal Engineみたいな重たい開発環境でも、新しい版ならUniversal、古い版ならIntel版が快適に動いてます。

少し気にしないと行けないのがPlug-in系。例えば配信ソフトのOBSはVLCがインストールされてるとVLCを入力ソースとして選び、映像ストリーミングを受信したりできますが、お互いインストールされてるバイナリタイプが一致していないと拡張として認識されません。例えばOBSだけ最新版でUniversal、VLCはIntelって場合は、ARMに移行した時にOBSだけARMで動くようになり、VLCの拡張が利用できなくなります。このような場合、VLCをUniversalかARMに更新すれば連携できるようになります。もし両者をARMで揃えられない場合は、UniversalアプリをRosetta経由で強制的にIntelバイナリで起動するという方法もあります。

DAWやVST/AUの対応事情

DAWやDJソフトなんかはわりと早期にARM対応してたみたいで、今なら特に困ることなく移行できます。が、VST/AU周りは少しハマりポイントも。

VST/AUは基本的には先述のPlug-in問題と同じで、基本的にはアーキテクチャが一致してる事が望まれます。が、調べた範囲だとAUに関してはOSレベルでクロスアーキテクチャをサポートしてるので透過的に使えるらしく、全てのDAWでサポートされてると思って良さそう。VSTに関してもDAWごとに内部的にブリッジ用意して使えるように努力してくれてます。

FL Studio ... この辺で説明されてるけど、ARM版で起動してもIntel VSTをブリッジしてくれます。Intel AUは少しはまりポイントがあったので後述。

Cubase ... VST3はARM版しかサポートせず。VST2に関してはIntel版もブリッジしてくれます。古くて移行してくれてないやつはだいたいVST2なので納得感ある、かつ公式らしい対応。

Studio One ... 2でも3でもIntel VSTをブリッジしてくれる。

AUに関しては落とし穴があって、読み込み時にシステムダイアログで警告を受けます。

ここでうっかりゴミ箱に入れないようにしましょう。「このまま開く」から許可する手順に入ります。すでに具体的な事はわすれてしまったけど、もしかしたら左のダイアログが先に出て、人まずは完了でパスして、この後にシステム設定に設定項目が現れて、そこから許可をすると右のダイアログで許可できるようになったかも。システム拡張とかパーミッションの設定と近いプロセス。

で、落とし穴は、このダイアログがでない環境があるって事。自分のケースではFL StudioではSynth1は黙殺されてましたが、Studio Oneでこのダイアログが表示され、そこから承認プロセスを通したらFL Studioでも使えるようになりました。

あと、マシン移行時にライセンスの再認証が必要なPlug-insが多いと思うので注意しましょう。自分の場合、iZotopeの再認証をしてなかったため、Studio Oneで定期的に音切れが発生する、という現象に悩まされてました。

新規仮想マシンの運用

もし一般的なWindowsアプリが動かしたい場合は、Parallelsか無償になったVMware Fusion経由でARM版Windowsを動かすのがおすすめ。ARM版Windows自体がIntelバイナリを実行する機能を持っているため、大半のソフトは問題なく動きます。問題が起きるとすれば、特殊なドライバを必要とする開発系ツールなど。あとはゲームでアンチチートに弾かれる事はあります。最近の需要で言えばVRChatが該当します。かつては問題なく動いていましたがEAC導入後は弾かれてます。VCRChatに関しては公式から非公式情報が出ており、エミュレーションするハードウェアの固有値をうまく設定する事で回避できるようですが、ARM版Windowsのバイナリ変換ではこの辺の固有値は設定できないので対応不可と思われます。

Linuxに関しても、今はARM版LinuxからRosetta 2経由でIntel版アプリを動かす事もできるようになってます。という事で、いずれの場合の新規OSインストールが許容できるなら、ARMベースで動かしてアプリレベルで必要に応じてIntelバイナリを変換、というのがパフォーマンス的にもベスト。

Intel仮想マシンの移行

すでに運用してたIntel版Windowsをそのまま持ち越したい、という需要が大きいとは思うんですが、ビジネスでそれをサポートしてくれてるとこは残念ながらありません。今のところ、そこそこうまく言っているのは、UTMでqemuのバックエンドを使い、Intelシステムエミュレーションの上で変換したVMイメージを使う方法くらいです。以下、注意点をいくつか。

事前にParallels関係のVM補助ツールは全部アンインストールしましょう。残っていると他のVMに持っていった際に関連ドライバ(prl_strg.sys)が起動中にクラッシュします。

Parallelsのディスクイメージは、snapshotとったりサイズ可変の設定になってたりすると変換がうまくいきません(サイレントに壊れて、起動失敗したところで深く悩みます)。元のマシンでこれらの設定をはずしてから、 /Applications/Parallels Desktop.app/Contents/MacOSts/MacOS/prl_convert などを使ってplainなフォーマットに変更しましょう。そこまで変換しておけば、UTMでファイルを選択した際にqcow2形式に自動変換した上でVMのフォルダ内にコピーを作ってくれます。

UTMに持ってきたら、CPUのマルチコア設定に注意。qemuはマルチコアエミュレーションをする際、コアごとに別スレッドでエミュレーションをするので物理スレッド数くらいまでエミュレーションするCPUを増やせばスケールするはず!と思うと失敗します。ARM上でIntelをエミュレーションするのは、strong-on-weakと呼ばれるケースに該当します。要はマルチコアにおけるメモリ一貫性保証の制約がARMの方がパフォーマンスを出しやすいweak memory orderを採用している。その上でより制約の厳しいstrong memory orderをエミュレーションするのは難しい/オーバーヘッドがでかいです。そのため、デフォルトでは正確性を優先してマルチスレッド対応は切られてる。そこで、システム設定にある「マルチコアを強制」にチェックを入れると、memory consistencyのサポートは諦めてマルチスレッドで動くようになります。この設定を受け入れないと実用的な速度では動きません。qemuの方でも一応バランスを見てバリアを埋めてくれてはいるようで、実用上は問題にはならない気はします。実際、ARM版Windowsのバイナリ変換でも標準設定でははmemory consistencyは壊れてます。実行ファイルのプロパティにある互換性設定でバイナリごとにエミュレーション精度を指定できるようになっており「標準設定でうまく動かなかったら、ここを変えてね」という扱い。一方Rosetta 2に関してはApple Silicon側にstrong memory orderをサポートする仕掛けがあり、正確かつ高速なエミュレーションができている、と言われてます。ほんと夢がある石なんだよ……。

Windows 10のイメージを持ってくるのに使ってる設定は以下の通り(いじったとこだけ)。

アーキテクチャ: x86_64
システム: Standard PC (Q35 + ICH9, 2009) (alias of pc-q35-9.1) (q35), 8192MiB
CPU: デフォルト, 4コア, マルチコアを強制
QEMU: 「ベースクロックにローカル時間を使用」のみチェック(非UEFI環境)
ディスプレイ: virtio-vga-gl (GPU Supported)

Linux系を持ってくる場合もParallels用のドライバは削除した方が良いみたい。GPU Supportedなディスプレイカード設定を入れると画面が落ちるのは古いせいかと思ってたら、どうもParallels用のドライバが悪かった。/Applications/Parallels\ Desktop.app/Contents/Resources/Tools/prl-tools-lin.isoあたりをマウントしてinstallerを実行すれば、uninstallが選べます。これでUbuntu22でvirtio-gpu-gl-pci (GPU Supported)が動くようになった。それまではvmware-svgaしか動いてなかった。virtio-ramfb-gl (GPU Supported)がいけるという話もあるけど、自分は動かなかった(けど、Parallelsの掃除してからは試してない)。

既存のVMイメージの流用だけじゃなく、どうしてもIntel版Windowsが必要って場合もUTMで同様の設定で新規インストールするのが唯一の解だと思います。新規の場合はギャラリーにあるイメージが最適設定の参考になるかと。VRChatのハードウェア設定もUTMで設定いれればワンチャン動くかもしれません(未確認)。

Wine

そうそう、Wineryとかwine系ラッパーで作ってあったパッケージはそのまま快適に動いてます。たぶんRosetta 2経由で起動してる。

その他

何から何まで移行・動作確認できてるわけじゃないので、他にも色々とあるかも。

例えばbrewとかはARMだとインストールする場所が変わるので、intel版残したままARM版も入れて様子見てる。

VS Codeの拡張とかもintel依存多いので怪しい。たぶんログアウトして同期を切ってからアプリとデータを削除、再インストールするのが正しい……けど、やってない。同期したままファイル消したりすると伝播するので危険……というのは以前経験した。

VRChat動かしたい人は、ARM版LinuxでRosetta for Linuxを使ってSteamを動かせば、Proton経由で動く可能性がありますね。少なくともSteamDeckではProtonでEAC突破できてるので。

追記(2024/12/31):Rosetta for Linuxはx86_64しかサポートしてない模様。Steam Launcherが32bitアプリなので一工夫必要。i386だけbinfmtにqemuを登録するとか?と思って試してみたけど、最終的にはlibGLの中で落ちた。

試したい人向けにやった事のメモをしとくと、UTMでGalleryにあるDebian 12 (Rosetta)をインストール、その中で以下の作業を敢行。

sudo apt install qemu-user-static
sudo update-binfmts --install qemu-i386 /usr/bin/qemu-i386-static --magic '\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00' --mask '\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
sudo dpkg --add-architecture i386
sudo apt update
# https://store.steampowered.com/about/ から steam_latest.deb をダウンロード
sudo apt install ~/Download/steam_latest.deb
steam

Xに垂れ流してた作業ログを簡単にまとめただけなので、もし詳細を教えて欲しい!ってとこがあれば、Xで声かけてください。分かる範囲でなら答えたり追記したりします。