2018-11-25

Vimconf 2018のスタッフをしてきた

VimconfとはテキストエディターVimに関する発表をするカンファレンスだ。国際カンファレンスを意識し、発表の多くは英語で行われている。今年は他ならぬVimの作者であるBram Moolenaar本人を招待している。

去年のVimconf 2017には、雇用主のドワンゴがスポンサーをしていたので、スポンサーチケットで参加をした。

今年のVimconf 2018もドワンゴはスポンサーをしていたが、去年は私がスポンサーチケットを使ったので遠慮をして今年は別の同僚に譲った。自腹で行こうかと思ったが、チケット販売サイトはクレジットカードからの入金しか受け付けなかったので、購入を断念した。

残念、今年は参加できないか、と思っていたところ、運営スタッフから人手不足で当日のスタッフが足りないので来てくれと言われ、急遽スタッフとして受付のチケットもぎりをすることになったので、結果的に今年も参加することになった。他の運営スタッフとは違い、当日の、それも開場後前後の1,2時間程度しかスタッフらしいことはしなかったのだが、立派なスタッフ面をいて開場直後以外の発表はバックヤードから聞いていた。

Vimconfは国際カンファレンスを意識して基本的に英語で司会、発表が行われるのだが、無線イヤホン経由の英語と日本語の通訳がついている。去年のVimconf 2017ではプロの通訳ではない運営スタッフの一人が通訳を担当した。プロではないので、通訳内容はだいぶアレでソレであったと聞いている。

今回はなんとプロの通訳を手配したという。私は英語のリスニングができるので通訳の品質を確かめてくれと言われてイヤホンを聞いてみたのだが、さすがはプロだ。流暢な英語が流れてくる。英語は自然で発表内容とあっているように思われるが、本当に発表者の発言と一致しているかという検証は難しかった。というのも発表者の日本語と通訳の英語を同時に聞くのは困難だからだ。驚異的なことに、発表者の発話する日本語に対応して流れる英語の遅延が少ない。あらかじめ発表内容の台本を渡されてそれを翻訳して読み上げているのだろうかと思うぐらい遅延が少ない。さすがはプロの通訳だ。

発表はmattnさんから始まった。VimからTCP/IPのlistenできるようにするという機能の実装で、VimがNUL文字を扱えるようにBLOB型を追加するという内容だった。

いよいよBram Moolenaar本人が発表する番になった。Bram Moolenaarはあまり表に出てこない人だ。Vimconf 2018以前にBram Moolenaarに直接対面したことのある日本人は数えるほどしかいないはずだ。インターネット上でBram Moolenaarを検索すると決まって出てくる、あの有名な酒瓶を掲げたBram画像は11年前の2007年のもので、現在の本人は11年分の齢を重ねた姿になっていた。

Bram Moolenaarの発表はVimの歴史を軽く紹介したほかは、Vimが現在取り組んでいる新機能の現状についての説明があった。Vimscriptが遅いのでパース済みの中間表現を保持することで高速化するアイディアや、Vimscriptのスレッドによる並列読み込みといったアイディアが説明された。そしてプラグインの話になった。最初のプラグイン機構は単一のディレクトリにvimscriptを放り込むものであったが、最近はプラグインごとに独立したディレクトリを持つことができるようになり、だいぶ楽になった。プラグインの例として、なんとあのShougoさんのプラグインが言及され、開場からは驚きの声が上がっていた。思えば遠くまで来たものだ。その後、プラグイン間で共通のライブラリを使いたいという至極当然の欲求から、プラグインの依存関係を記述して解決するパッケージマネージャー機能のアイディアが説明された。

質疑応答では、Bram MoolenaarはLSP(Language Server Protocol)についてあまり興味がなさそうであった。しかしLSPをVimでサポートするのはなかなかよさそうなアイディアに思える。

昼になり弁当が配られた。国際会議なので様々な思想に配慮した結果、すき焼き弁当とベジタブル弁当が用意されていた。私はすき焼き弁当を取りそこねたので、余っていたベジタブル弁当を食べた。ベジタブル弁当の中身はとても品数が多く豪華であった。酒のつまみによさそうな中身だった。

昼休みの余興として、ホワイトボードに模造紙を貼って、Vimで書く言語についてのアンケートが行われた。

ありえないことにCとC++が"C/C++"とひとくくりにされていたので、分割した。

その他の欄には様々な言語が学んだ。まずMarkdownだ。当然ながらVimscriptもVimで書く。Markdownもそうだ。VimでVimを書く人もいた。これはVimでVimの開発をしているということだ。要するにC言語を書くことでもあるのだが。

Python 2を書いてみたところ、シールがいくつか貼られていた。まだPython 2を書かなければならないかわいそうな人たちも参加していたらしい。

ネタで書いたEmacs Lispにもシールが貼られていた。これはネタではなく理由のあることで、環境構築をする際にまずデフォルトで入っているVimでEmacsの設定ファイルを記述し、その後にEmacsをインストールするので、VimでEmacs Lispを実際に書くのだという。

更にわからないことに、Jupyter Notebookが追加されてた。Jupyter Notebookというのはプログラマーではなく科学者向けソフトウェアだ。科学者は頭のいい人間であり、研究に必要なコードは当然書ける。しかし彼らは本物のプログラマーではないので、プログラマーらしいコンピューターの使い方やプログラミング言語の環境構築は苦手だ。Jupyter Notebookはそういう手間を省き、科学者でも様々なプログラミング言語を使えるようにした環境だ。Jupyter Notebookというソフトウェア一つ入れれば、後は何も考えなくてもいい。そのJupyter NotebookをVimから使うとはどういうことか。聞けばVimからJupyter Notebookを操作しているのだという。それができる人間なら、Jupyter Notebookをわざわざ使わずともプログラミング言語の環境構築は簡単にできるはずなのだが、世の中はわからない。

午後の発表になった。Vimの従来のプラグインの機能は、実は今のVim標準の機能で代替可能であることを示す発表があった。Ctrl-Xから始まる各種保管の説明があったが、私は使いこなしていない。

今回の複数の発表によれば、Vimは就職活動に役立つらしい。

vim-historyレポジトリも興味深い。これは1991年にリリースされて27年の歴史を持つVimの更新履歴を単一のgitレポジトリで再現したものだ。Vimは当初、当時の慣習としてtarballで配布され、その後CVSで管理されるようになり、何度かのレポジトリの断絶を経て、今はgitで管理されている。レポジトリの全歴史をgitレポジトリで表現することにより、gitによる様々な操作が可能になる。例えば特定のコントリビューターは何件コミットしているのか。あるコントリビューターの最初のコミットはどれか。などといった、様々な変更の歴史がgitで検索できるようになる。

似たような試みはUNIXにもある。UNIXの歴史をgitレポジトリで再現するプロジェクトがある。

そして、:termdebug機能が言及された。この後の発表はあまり覚えていない。:termdebug機能のあまりの素晴らしさに発表を聞くのがおろそかになってしまったからだ。

:termdebugはVimにデフォルトで同梱されているVimによるGDBのフロントエンドを提供するプラグインだ。使い方は、":packadd termdebug"して、":Termdebug プログラム名"するだけだ。VimはGDBを起動してGDBと通信する。そして、GDBとやり取りするウインドウ、デバッグされるプログラムの標準入出力のウインドウが追加される。現在のウインドウはソースコード表示に使われる。

素晴らしいことに、マウスサポートを有効にしている場合、StepやNextといったボタンが現れ、クリックすら可能になる。そしてGDBに該当のコマンドを送る。

これがすべてVimの中で動くということは、リモートサーバーにsshして動かすことすら可能になるということだ。

しかし、使うとすぐにバグが見つかった。ブレイクポイントはソースコード上で表示されるのだが、break/deleteを繰り返すと存在しないブレイクポイントの表示が消えなくなるのだ。この問題は原因を特定したのだが、最新版のVimでは治っていることが判明した。

もう一つの問題は、Bram MoolenaarがC言語しか想定していなかったための機能不全だ。C++では複数の関数が同じ名前を持つことができる。

void f() {}
void f(int) { }
void f(long) { }

この状態で"break f"とすると、関数fすべてにブレイクポイントが設定される。termdebugはこれに対応していない。

この場合のGDBのブレイクポイント番号の付与は変わっている。"break f"とした場合、1.1(f()), 1.2(f(int)), 1.3(f(long))のようにメジャーブレイクポイント番号と関数ごとにマイナーブレイクポイント番号が付与される。結果としてブレイクポイントは3つできるが、それはすべてブレイクポイント番号1として扱われる。enableコマンドなどは"enable 1.1"のように指定できるが、deleteは指定できない。"delete 1"とするとブレイクポイント番号1に属するすべてのブレイクポイントが削除される。

termdebugはブレイクポイント番号をキーにしてmapでブレイクポイントを管理しているのだが、ひとつのbreakコマンドで複数のブレイクポイントが設定されることを想定していないし、ましてやその複数のブレイクポイントが一つのメジャーブレイクポイント番号に属することを想定していない。そもそもマイナーブレイクポイント番号があることすら想定していない。ブレイクポイント番号をキーにしてmapでブレイクポイントを管理していて、削除時にブレイクポイント番号をキーに検索して削除している。

現在のコードを大幅に変えずに関数のオーバーロードのブレイクポイント表示に対応するのは難しい。HandleNewBreakpointで"1.1", "1.2", "1.3"のようなキーで複数のブレイクポイント番号をキーにしてs:breakpointsに挿入し、HandleBreakpointDeleteで"1.1", "1.2", ...のようにマイナー番号の削除を見つからなくなるまで試みる実装が、とりあえず使えるだろうとは思う。

termdebugは素晴らしい。そして、Termdebugとそのバグのおかげで、Bram Boolenaarと会話ができたという思わぬ副産物もあった。VimconfにBram Moolenaarが来ると聞いて会話をしたいとは思っていたものの、特に話すべき内容は思いつかなかった。なるほど、私はVimを毎日使っているが、Vimの開発に参加しているわけはない。せいぜい挨拶をするのが関の山だと思っていたのだが、Termdebugの存在で会話内容ができてしまった。英語によるスピーキングは普段全くしていないので英語が口から一切出てこないのだが、不思議なことにtermdebugがC++をサポートしていないことについてとその原因についてであれば、英語で説明をすることができた。言語の利用には慣れた文脈が必要のようだ。

termdebugをなぜ今まで知らなかったのだろうと疑問に思っていたが、どうやら今年の7月にVimに入ったばかりのだいぶ新しい機能であるようだ。道理で知らないわけだ。termdebugの存在を知ることができたという理由だけでvimconf 2018のスタッフをしたかいがあった。

その後、もう一枚ホワイトボードが追加され、今度はVimに欲しい新機能のアンケートが行われた。人気の機能はVimscriptの高速化であった。私は、VimがtmuxやScreenのように、シェルからのdisownによるログアウト後の実行継続と、detach/attach機能がほしい。この機能があれば、tmuxはいらなくなる。Vimがtmuxの代わりを務めることができるのだ。リモートサーバーにsshしてvimでテキストを編集し、その編集中のvimの実行を継続したままログアウトし、後にログインして前回の続きから作業を再開したい時、今はtmuxの中でvimを実行しなければならない。これがvimだけで済むようになるのだ。

新機能では端末でエスケープシーケンスによるグラフィック表示をするSixelも人気があった。これは解せないことだ。Sixelはテキスト処理だけで完結するが、グラフィックの表現としては非効率的すぎる。効率を重視するならば、ビットマップデータを直接流し込むようなAPIがほしい。もちろんこれはNULも扱えるようにBLOB型が必要になるだろう。

Vimconf 2018は素晴らしかった。来年も開催されるだろうか。楽しみだ。

ワンナイト人狼とボードゲームの知的財産権について

なぜか一部のボードゲーム作者は、事実の羅列や純粋な思想、新規性も進歩性もない発明であるゲームルールに排他的な独占権を欲しがる。そのような権利が認められた場合、我々は日常会話すら困難になるのだが、そのことに思いが至ることはないようだ。

ワンナイト人狼と同等のルールがオリジナルを考案した我々の許諾なく販売されたと嘆いている。

「太刀打ち」という物騒な言葉まで用いて攻撃的な対立姿勢を明らかにしている。

しかし、本人も認めるように、事実の羅列や抽象的な思想にすぎないゲームルールは著作権では保護されない。特許として認められるほどの新規性と進歩性も満たしていない。

ライセンスというのは排他的な独占権があってはじめて成立するものだ。そのような権利を持たずして一体何を求めているのか。

唯一なにかできるものがあれば、「ワンナイトルール」という商標の有効性についてだけだ。

望む内容に注意せよ。期待通りの結果をもたらさないことがある。

2018-11-18

自転車を買おうか悩んでいる

私は職場から直線距離4kmの場所に住んでいるのだが、電車による通勤は40分ほどかかる。理由は自宅が駅から遠いことと、乗り換えが必要なためだ。

自宅から職場まで歩くと50分かかる。道なりに5kmほど歩くので、6km/hで歩くとそんなものだろう。

これを考えると、自転車通勤をしたほうがいいのではないかと思う。しかし、駐輪場に自転車を止めるのは面倒だ。では折りたたみ式の自転車を使えばいいのではないか。

と考えていると、同僚からCARRYMEを勧められた。これは10万円するとても小さな折りたたみ自転車の自転車だ。実際に載ってみたが、やはりホイール径が8インチでは乗り心地が悪い。するとBROMPTONという自転車を勧めらた。これは20万円する折りたたみ自転車でホイール径も14インチ。なかなか悪くないがまだ乗り心地が悪そうだ。調べたところDAHHONはホイール径が20インチの折りたたみ自転車だ。これはなかなかよさそうだが少し大きい。これならKHSのような普通の自転車を2つに折りたたみましたぐらいの自転車の方が乗り心地がよさそうだ。

しかし、折りたたみ性能と乗り心地は両立できないらしく、どちらかに振らなければならない。そして、10万、20万も出すのであれば、とても乗り心地のいい折り畳めない自転車が買える。であれば駐輪場の手間を考えても普通の自転車を買うべきだろうか。

2018-11-13

C++標準化委員会の2018サンディエゴ会議の結果

2018 San Diego ISO C++ Committee Trip Report (Ranges v1 TS for C++20; consensus on modules design; new Language and Library Evolution Incubators) : cpp

2018年サンディエゴ会議のトリップリポートが公開されている。今回も大きく変わった。

Range

Rangeが入った。Rangeは膨大なのでここでは解説しない。

Yet another approach for constrained declarations

autoと書くべきところをCocept autoと書けるようになった。


template <auto N >
auto f( auto x )
{
    auto y = x ;
}

というコードを、


template < Concept auto N >
Concept auto f( Concept auto x )
{
    Concept auto y = x ;
}

と書ける。

関数の戻り値の型と変数宣言の場合はautoを省略できる。


template < Concept auto N >
Concept f( Concept auto x )
{
    Concept y = x ;
}

こんなところがまだ変わるようでは、まだまだC++20参考書は書けそうにない。書いたそばから変わっていく。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1073r2.html

必ずコンパイル時に評価されるconsteval関数が追加された。

consteval int f( int x )
{
    return x+1 ;
}

constexpr関数は実行時評価でよい場合は評価を実行時に遅延させてもよいという規定がある。consteval関数は必ずコンパイル時に評価される。

std::is_constant_evaluated

コンパイル時評価されているときにtrueを返すstd::is_constant_evaluatedを追加する。


constexpr double power(double b, int x) {
  if (std::is_constant_evaluated() && x >= 0) {
    // A constant-evaluation context: Use a
    // constexpr-friendly algorithm.
    double r = 1.0, p = b;
    unsigned u = (unsigned)x;
    while (u != 0) {
      if (u & 1) r *= p;
      u /= 2;
      p *= p;
    }
    return r;
  } else {
    // Let the code generator figure it out.
    return std::pow(b, (double)x);
  }
}

これにより、constexpr関数の中にコンパイル時処理と実行時処理を同時に書くことができるようになる。

少し異質なライブラリで、コンパイラーマジックでサポートされるので、ヘッダーファイルに依存せず使うことが可能となっている。

[C++標準化委員でなければ読めない] p1330r0.pdf

unionの有効なメンバーを切り替える処理をコンパイル時定数にする。std::stringやstd::optionalをconstexpr化するのに必要。

p1002r0.pdf

try, catchをコンパイル時処理では無視する。コンパイル時定数への対応ではない。標準ライブラリの多くをconstexpr化するのに必要。将来的に例外をコンパイル時定数に対応する可能性を閉ざすものではない。

Allowing dynamic_cast, polymorphic typeid in Constant Expressions

dynamic_castとtypeidをコンパイル時定数にする変更。すでにコンパイル時にvirtual関数を使えるようになっているため、制限する理由がなくなった。C++20ではC++コンパイラーはコンパイル時に確保されたオブジェクトの型を把握して適切にディスパッチする必要がある。

p1006r1.pdf

std::pointer_traitsをconstexprに対応させる変更。std::vectorをconstexprにするために必要。

今回はまだ入らなかったが、動的メモリ確保も次回あたりにコンパイル時定数になる予定だ。つまりコンパイル時に動的メモリ確保ができるようになる上、その他の例外やらvirtual関数やらunionやらといった処理もすべてコンパイル時定数になるので、std::stringやstd::vectorがそのままconstexprに対応することになる。C++20ではほとんどの処理がコンパイル時定数になる。これは静的リフレクションを入れるために必要な変更だ。

Misc constexpr bits

標準ライブラリのconstexprにできる部分を積極的にconstexprにしていく変更。

P0668R4: Revising the C++ memory model

C++のメモリーモデルの変更。一部のアーキテクチャのとても弱い保証に対応した。一部のアーキテクチャー、PowerやNVIDIAのGPUとARMは、memory_order_seq_cstに対応しつつrelease/aquireに対応できない。memory_order_seq_cstの存在を許すaquire/releaseを実装するためには、よりペナルティの高い強めのフェンスを挿入しなければならない。しかしそのような理論的な問題のためだけに強いフェンスを使いたくはない。そのために、memory_order_seq_cstには対応しない弱いatomic型を追加する。

P1236R0: Alternative Wording for P0907R4 Signed Integers are Two's Complement

符号付き整数型の値の表現は2の補数であることがC++の規格で保証する変更。

char8_t: A type for UTF-8 characters and strings (Revision 5)

UTF-8文字リテラル、UTF-8文字列リテラルの文字の型を表現するchar8_tを追加する提案。私が9年前にC++0xのときに提案したところ、「でもchatは生のバイト列を表現するのに適切な型だからー」と寝ぼけた主張で却下されたにもかかわらず、後になって「やっぱchar8_tにしとけばよかったなぁ」となったので変更された。私には愚痴を言う権利がある。

Nested Inline Namespaces

インライン名前空間をネストで書けるようにする。


namespace lib::container {
    inline namespace v1 {
        namespace node {
        }
    }
}


namespace lib::container {
    inline namespace v2 {
        namespace node {
        }
    }
}

のように中間のinline名前空間を書く際にはC++17に追加されたネストされた名前空間で書けなかったが、


namespace lib::container::inline v1::node {
}

namespace lib::container inline v2::node {
}

のように書けるようにする。

p1289r0.pdf

contractの中ではアクセス指定を無視する変更。

p1007r2.pdf

std::assume_aligned<N>(ptr)の追加。ポインターptrの指すアドレスがNでアラインされていることをコンパイラーにヒントとして与える


// intの配列から合計をSIMD演算で計算する関数
int sum_ints( int * ptr, std::size_t n )
{
    std::assume_aligned( ptr, alignof(int) ) ;    
    // アライメント要求のあるSIMD演算で合計を計算
    return 
}

実際に指定したアライメントになっていることを保証するのはユーザーの仕事だ。std::assume_alignedはアライメントが保証されていると仮定してよいとコンパイラーにヒントを与えることによって、コンパイラーがSIMD演算のようなコード生成を行うときに、アライメント調整用のコードを生成せずに住むようにする。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1085r2.md

spanからoperator ==を取り除く変更。spanをregularにするために必要な変更。

STLの作者Alexander StepanovはC++では型はRegularであるとが重要だと力説した。型がRegularでない場合、もたらす利便性よりも混乱のほうが大きくなる。

コピーコンストラクターとコピー代入演算子は、オブジェクトの「値」をコピーする。

operator ==やoperator <はオブジェクトの「値」を比較する。

型がRegularであるためには、コピーと比較は同じ「値」を比較しなければならない。コピーと比較で「値」の定義が異なっている場合、混乱の元だ。

さて、spanはどうなっているか。spanのコピーはshallowだ。つまり、ポインターとそのサイズがコピーされる。一方、spanのoperator ==はdeepだ。つまり、ポインターの参照する先のストレージが比較される。

spanをRegularにするためには、spanのoperator ==を廃止する。

Smart pointer creation with default initialization

make_unique_default_init<T>/make_shared_default_init<T>を追加する。これはデフォルト初期化されたunique_ptr<T>/shared_ptr<T>を返す。

size_t型の引数nを取るものもあり、こちらはunique_ptr<T[]>/shared_ptr<T[]>を返す。


// デフォルト初期化されたint型の値の
// std::unique_ptr<T>
auto p = std::make_unique_default_init<int>() ;
// それぞれデフォルト初期化されたint型の値で要素数が5の
// std::unique_ptr<T[]>
auto a = std::make_unique_default_init<int>(5) ;

C++標準化委員会では、特定の分野について議論するStudy Groupが設置されるが、今回、新しいStudy Groupとして、SG19 Machine LearningとSG20 Educationが追加された。SG19は名前だけみると機械学習についてで、SG20は前から作ると宣言されていた教育に関するSGだ。

C++を発展させるEvolution Working Groupでは以下のような興味深い議論があった。

モジュールの中でmain関数を定義できる提案と、プログラムにデータを埋め込むstd::embed提案はより深い議論とフィードバックが必要だとされた。

void main提案は却下された。

興味深いのは、operator []の中の operator , の利用をdeprecatedにしようという決定だ。


int a[5] ;
a[1,2] ; // a[2]と同じ

このコードがdeprecated扱いになる。operator []の中のカンマは、多次元配列を実装するための何らかの新しい機能として予約される。

short float提案についてコンセンサスは得られなかった。

std::colonyはもっと作業が必要だとされた。

設計的には賛同できるのでC++20に追加する方向で進めるライブラリとして、テキストフォーマット(std::format)、スタックトレースライブラリがある。

SG13 Graphics Study Groupではオーディオに関する興味もあるらしい。またweb_viewに対するさらなる作業を推奨する雰囲気だ。

今後の予定としては、2019年春のKona会議でFeature freezeをし、2019年夏のドイツのCologne会議でCommittee Draftの文面を完成させる。つまり来年の半ばにはC++20の概要は決定するわけだ。

モジュールはおそらくC++23以降に延期される。コルーチンやExecutorも延期される。ネットワークライブラリはおそらくC++26以降になるだろう。

2018-11-10

かつてPSエミューレーターにスラップ訴訟を仕掛けたソニーのPSクラシック、自由ソフトウェア実装のPSエミュレーターであるPCSX ReARMedを使っていることが判明

かつてPSエミュレーターをスラップ訴訟により嫌がらせをして事実上の販売停止に追い込んだ邪悪なソニーが販売するPSクラシックには、自由なソフトウェア実装のPSエミュレーターであるPCSX ReARMedが使われていることが判明した。

Kotakuによるレビューによれば、PSクラシックの使用する自由ソフトウェアのライセンス表記の一覧にPCSX ReARMedが確認できたという。

PCSXは自由ソフトウェアによるPSエミュレーター実装で、2000年に公開された。その開発は停滞したが、2006年にPCSX-dfとしてforkされた。またPCSX-Revolutionいうforkもあった。2009年にはこの2つのforkを参考にPCSX-Reloadedいうforkも行われている。

PCSX ReARMedはPCSX-Reloadedのforkで、PCSXをARMアーキテクチャに移植する目的で開発されている。

さて、ソニーはPSエミュレーターに対して悪名高いスラップ訴訟を仕掛けてきた歴史がある。

Mac用のPSエミュレーター実装であるConettixのVirtual Game Stationの販売を著作権侵害のスラップ訴訟を起こして差し止めようとした。これは最終的にソニー側に不利な和解で終わっているが、その間VGSの販売が差し止められた。

また、Bleem CompanyによるPSエミュレーターBleem!を著作権侵害と不正競争防止法によりスラップ訴訟を起こして差し止めようとした。この訴訟でソニーが完全に敗北している。PSエミューレーターは不正競争防止法に反しないばかりか、宣伝に使ったPSゲームのスクリーンショット利用すら、著作権法に照らし合わせて正当な引用であるとの当然の判決が下った。しかし、物語はハッピーエンドには終わらない。長引く訴訟により膨れ上がった訴訟費用に耐えかね、Bleem Company は倒産。結果的に邪悪なソニーはBleemの販売を事実上差し止めることに成功した。

その悪名高い札付きのソニーが当時の愚かな行いに対する謝罪もなく、何食わぬ顔で自由ソフトウェアを使ったPS互換機を販売するとは、恥知らずにも程がある。ソニーはPSクラシックの販売にあたって、過去の過ちを認め、公に謝罪するべきである。

結局、抵抗は無意味であり自由ソフトウェアが勝利するのだ。

参考文献:

PlayStation Classic Plays Fine, But It’s A Bare-Bones Experience

Sony using open source emulator for PlayStation Classic plug-and-play | Ars Technica

Sony to sue Connectix over PlayStation emulator • The Register

Connectix Virtual Game Station - Wikipedia

Bleem! - Wikipedia

PCSX-Reloaded - Wikipedia

PCSX ReARMed