Linux向け Lotus 1-2-3
(lock.cmpxchg8b.com)- 30年前のプロプライエタリなスプレッドシート Lotus 1-2-3 が、偶然復旧された資料とバイナリハックを経て、発売当時には存在していなかった Linux 上でネイティブ動作するようになった
- 1990年代のBBSバックアップから、失われたと思われていた LPL アドイン SDK と Lotus 1-2-3 for UNIX が見つかり、サンプルプラグインのビルドと UNIX バイナリ解析が可能になった
- UNIX 配布物には圧縮された Intel 80386 COFF オブジェクト
123.oが含まれており、約20,000個のシンボルとデバッグ情報が内部構造を明らかにした - 移植は COFF を ELF に変換するだけでは終わらず、Linux と UNIX の システムコール・構造体 ABI の違い を
coffsyrupとラッパー関数で回避する必要があった - 現在のポートはクラッシュせず動作し、100% 使用可能だが、一部の問題や端末ドライバの移植が残っており、見た目では DOS エミュレーション版のほうがまだ優れている
30年前のプロプライエタリアプリを Linux に移植した出発点
- Lotus 1-2-3 は30年前の abandonware として残っていたが、いくつかの発見とハックによって Linux ネイティブポート が可能になった
- 移植対象は古典的な Lotus 1-2-3 R3 であり、Lotus 1-2-3 自体は 2002 年までリリースがあった
- このプロジェクトは、現代のシステムで Lotus 1-2-3 を正しく動作させるための lotusdrv ドライバ保守作業から始まった
- ドライバ API はリバースエンジニアリングで解明され、既存ドライバは現代のシステムでもうまく動作する
失われた LPL SDK と BBS バックアップ
- Lotus 1-2-3 はプラグイン、つまり アドイン(add-in) で拡張できるよう設計されていたが、アドインは LPL という特殊な言語で書かなければならなかった
- LPL コンパイラと SDK は失われており、Lotus は SDK を無料配布せず 395ドル で販売していた
- 1990年代の BBS システムのテープバックアップを保管していた元 sysop を通じて、warez 形式の SDK が復旧された
- 復旧された ADK は 123DADK.ZIP から取得できる
- サンプル LPL プログラムは modern.pl として公開されている
- 同じ BBS バックアップには、広く失われたと考えられていた Lotus 1-2-3 for UNIX の warez コピーも含まれていた
Lotus 1-2-3 for UNIX ディスクイメージの解析
- UNIX 版は
123UNIX1.TD0から123UNIX5.TD0までの TD0 ファイル 一式として残っていた - TD0 は1980年代の古い圧縮ディスクイメージ形式であることが確認され、samdisk を使って raw ディスクイメージに変換した
- 変換したイメージのうち最初のものは
tar archive、残りは pre-SVR4 または odc 形式の ASCII cpio archive だった - ディスクイメージ一式は Internet Archive にアップロードされた
- 展開すると
lotus/123.v10配下に実行ファイル、ヘルプ、キーマップ、プリンタ・ビデオドライバデータ、サンプルファイル、マニュアルなどが現れた- 全体構成は 35個のディレクトリと338個のファイル 規模だった
決定的な手がかりとなった 123.o
sysV386/libディレクトリで123.o.z_1と123.o.z_2に分割された大きなファイルが見つかった- 2つの断片を結合して展開すると、
123.oは Intel 80386 COFF object file であることが確認された- stripped されていないオブジェクトファイル
- 5つのセクション
- シンボルオフセット
0x1efbdc -
19,755個のシンボル
- optional header size 28
- このファイルには private symbol とデバッグ情報が含まれており、Lotus 1-2-3 の内部構造を理解するうえで大きな助けになった
alt.folklore.computersで得られた回答では、このファイルは誤って含まれたものではないという見方だった- 1990年代初頭の UNIX では
dlopen()が広く使われていなかったため、拡張機能と再リンクするための partially linked オブジェクト だった可能性が高い
デバッグ情報が明かした内部構造
- UNIX 版は DOS 版の 直接的なソースポート に近く、ほとんどが同じ方式で動作していた
- 含まれていたデバッグ情報は、Lotus 1-2-3 の内部に関するさまざまな疑問を解決してくれた
- グラフ出力を改善するため、ドライバで ラスタライザ(rasterizer) にフックをかけたかったが、文書だけでは動作を理解しにくかった
- デバッグ情報により、ラスタライザが小さな バイトコードプログラム を動的に生成し、グラフィックエンジンがそれを解釈していることが判明した
- opcode が分かったことで、raster.c でそれを逆アセンブルして変更し、出力改善に活用できるようになった
COFF から ELF への変換
objcopyは COFF オブジェクトファイルを Linux で使う ELF 形式へ変換できるobjcopy -I coff-i386 -O elf32-i386 123.o 123elf.oコマンドで123.oを123elf.oに変換した- 変換結果は
ELF 32-bit LSB relocatable, Intel 803386, version 1 (SYSV), not strippedと確認された objdumpによれば、元のオブジェクトファイルのコンパイル時刻は 1990年9月8日 06:23:50 で、Linux の最初のバージョンより前だった
Linux と UNIX の ABI 差異への対応
- 最初の問題は、Linux と UNIX が互換性のある システムコールインターフェース を使っていない点だった
- UNIX 版は
lcall7インターフェースを使用しており、たとえばopen()はcall 0x7:0x0形式の callgate を呼び出していた - Linux ではこの callgate がサポートされておらず、そのまま実行するとクラッシュした
- Linux にはかつて
lcall7とlcall27の互換サポートがあったが、現在はない
- Linux にはかつて
- 目標はこうした呼び出しを除去し、すべての呼び出しを glibc 経由にルーティングすることだった
再配置と coffsyrup
- 単純に
objcopy --strip-symbol openでシンボルを削除しようとしたが、openが relocation に使われているためobjcopyに拒否された - relocatable object file は、どのアドレスにロードされても動作するようシンボル参照と再配置情報を含んでいる
- シンボルを削除するには、そのシンボルを参照する 再配置情報 も一緒に修正しなければならない
- そのために小さなツール coffsyrup を作成した
objcopyが拒否する COFF シンボルも削除できる- 例として
openシンボルと関連する relocation を見つけて処理した
バイナリ互換ではない UNIX 関数群
- 標準 UNIX 関数のかなりの部分は ソース互換 ではあっても バイナリ互換 ではない
- 代表例は
struct stat- 同じ C コードでも、複数の UNIX 系でコンパイルできる
- しかしコンパイル済みオブジェクトファイルは
struct statのサイズやst_sizeオフセットの違いにより別のシステムでは壊れる可能性がある
- 対応が必要な主な関数は
stat(),times(),uname(),fcntl(),ioctl()などだった - アプローチは、
objcopyでシンボル名を変え、coffsyrupで undefined にしたうえで、Linux 構造体を UNIX 構造体へ変換する ラッパー関数 を書くことだった termiosはとくに大きな難所で、細かな動作が UNIX システムごとに微妙に異なり互換性がなく、デバッグが難しかった
ライセンスチェックと実行結果
- いくつものハックのあと、プログラムはクラッシュせず起動したが、ライセンス がなければ動作しなかった
exit()にブレークポイントを置いて確認した結果、有効なライセンスを確認する内部シンボルはlic_init()だった- IDA でコードを調べたところ、ライセンスチェックは
LICENSE.000ファイルを探し、その中の有効期限、ユーザー名、システム名がシステムの報告値と一致するかを確認する方式だった - 最終的に Lotus 1-2-3 は新しい OS である Linux へ移植された
- 現在の状態は以下の通り
- クラッシュせず動作する
-
100% 使用可能
- まだいくつかの問題を詰める必要がある
- 端末ドライバの移植が残っている
- 現時点ではエミュレーション上で動く DOS 版のほうが見た目は良いが、修正は可能
- 移植コードは github で公開されている
1件のコメント
Hacker News の意見
古い BBS システムのテープバックアップから SDK の warez コピーを復元し、サンプルプラグインまでビルドしたというのは信じがたいほどです
Why History Needs Software Piracyを思い出します
こうした機器は数十年後も残っているハードウェアなので、メーカーごとに個人のクラウドへ保管する程度を超えて、コミュニティ全体で使える中央集権的で長く存続するリポジトリがあれば、公共的価値は大きいです
毎年アーカイブを配布したり、100年ほど持つ物理メディアとして archival Blu-ray を販売したりする方法も考えていました
そうすれば、ARM ベースの DSP Eurorack モジュールの壊れたファームウェアを復旧するときに必要な最後の希少な
.binファイルを、誰かが持っている確率は 1 に近づくはずです父が古い Windows の入った予備ノートPCに重要な Lotus 1-2-3 ファイルを大量に保存していて、たまに開く必要があったため、その状態はかなり不安でした
最近、LibreOffice が Lotus ファイルを ODF/ODS に、しかもコマンドラインからでも変換できることを知り、簡単な bash スクリプトで全部変換しました
変換したファイルを Collabora 付きの Nextcloud に一括アップロードし、父にアカウントと簡単な使い方を教えたところ、今ではオンラインでファイルを見られ、サーバーの通常のバックアップルーチンにも含まれています
OP のようなデータ考古学者と LibreOffice コントリビューターには大いに感謝しています
7歳のとき Nintendo を買ってほしいと頼んだら、父が代わりに 286 PC と Lotus 1-2-3、Indiana Jones のテキストアドベンチャーを買ってくれた記憶がよみがえります
そのため最初の言語は LISP ではなく BASIC になり、人生のあらゆる失敗をこの悲劇のせいにするつもりで、反論は受け付けません
Spectrum がすでに下火になりつつあった時期でもそうでした
似たような作業をしていますが、プログラムの一部をまずオブジェクトファイルに変換する段階を追加しています
そのため、既存の残っているオブジェクトファイルだけに縛られませんが、動作させるにはある程度のリバースエンジニアリングが必要です
Atari Jaguar のリンカーである
alnで概念実証を作り、Linux x86 のa.out実行ファイルを ELF オブジェクトファイルに分離したうえで、ABI の違いを回避して ELF x86 実行ファイルとして再リンクしましたhttps://forums.atariage.com/topic/354341-porting-the-original-atari-jaguar-sdk-to-elf/
いろいろな面で興味深かったです
ソースコードも元のコンパイラと言語もなしに、UNIX バイナリから Linux バイナリへ移植する過程が見事に見えましたし、こういうのこそ HN らしい内容です
2023年になっても Usenet が単に rar ファイルの流通以外の用途で使われていることも思い出させてくれます
インターネット普及前の BBS 文化が、熱意と優れたシェアウェア配布を一般に広めていた過去も思い起こさせます
Twitter をはじめとするソーシャルメディアが崩れていく流れを見ると、なおさらですし、年長の Z 世代は80〜90年代レトロにはまって、モデムのネゴシエーション音を着信音としてダウンロードしたりもしています
23歳の甥も最近そうしていましたし、American Horror Story や Stranger Things のような作品がそのノスタルジーをさらに養っています
十分長く待てばすべてがまた流行する、という古い言葉は正しいということです
昨年2022年5月にも良い議論がありました
https://news.ycombinator.com/item?id=31455968
この素晴らしい記事からリンクされていた https://scenelist.org/ は、今朝まさに必要としていたノスタルジー爆弾でした
思い出旅行にとても良く、強くおすすめします
関連リンクです
Lotus 1-2-3 for Linux - https://news.ycombinator.com/item?id=35807639 - 2023年5月、コメント73件
Lotus 1-2-3 - https://news.ycombinator.com/item?id=35872758 - 2023年5月、コメント117件
Lotus 1-2-3 For Linux - https://news.ycombinator.com/item?id=31455968 - 2022年5月、コメント83件
Lotus 1-2-3 arbitrary resolution - https://news.ycombinator.com/item?id=26316637 - 2021年3月、コメント123件
昨年少し使ってみたせいで、1-2-3 のことをすっかり忘れていました
今でも Linux で
123バイナリが問題なく動いており、はるか昔に消えたソフトウェアがそのまま動作するというのは、かなり大した成果ですずっとこういうものが欲しいと思っていました。スプレッドシートでフォントや図をあまり使わないので、ターミナルベースのスプレッドシートがぴったりです
ついに出たのはうれしいですし、Mac と Windows にも移植されるといいですね
https://lock.cmpxchg8b.com/spreadsheet.html
使ったことはありませんが、確認してみる価値はあります
また Emacs の Org-Mode は際限なく掘り下げられるツールで、org-mode の表セルを Emacs の
Calc機能と一緒にスプレッドシートのように使う方法もありますhttps://www.youtube.com/watch?v=15aDIvb5LJs
かなり強力そうで、Emacs らしくターミナルでもウィンドウ環境でも実行できます
scがあります: https://www.unix.com/man-page/linux/1/sc/