まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

2019/05

自分の「人生最初のプログラミング」は BASIC でした。

それも Visual Basic でなければ、N-88 BASIC でもありません。SHARP 製ポケットコンピュータに標準付属されていた BASIC(正式名称は知りません)で、一人用ブラックジャックなどを作って遊んでいたのでした。そんなわけで BASIC はそれなりの思い入れのあるプログラミング言語の一つです。

そしてヤフオクでたまたま見つけたファミリーベーシックを落札することができ、いつかこいつでプログラミング環境を・・・と思ったまま2年近く経ってしまいました。 (^^; この連休を使って改めてファミリーベーシックによるプログラミング環境を構築してみました。どれだけ需要があるか不明ですが(笑)、その経緯をまとめました。


まず「ファミリーベーシック」を知らない人向けの説明を。これは任天堂伝説の家庭用ゲーム機であるファミリーコンピュータ(以下、ファミコン)を使って動かすプログラミングソフトです。ファミコンは8ビットCPUを搭載した本体に ROM カセットと呼ばれるゲームカートリッジを差し込んで使うことで、様々なゲームソフトを楽しむことができました。2016 年には代表的な 30 本のゲームソフトを内蔵した「ファミコンミニ」が発売されて話題になりました。

ファミリーベーシックはそんなファミコンのソフトの1つで 1984 年(昭和 59 年)に発売されました。完成されたゲームそのものを楽しむというよりも、音楽を演奏したり、ビット絵を描いたり、、といった創作活動を楽しむソフトカートリッジでした。またコントローラーもファミコン付属のものを使うのではなく、ファミリーベーシックカートリッジに付属している外付けキーボードを接続して、キーボードによる入力がサポートされていました。このファミリーベーシックが持つ機能の1つが「BASIC 言語によるプログラミングと実行」でした。まだプログラミングが今ほど一般的でなかった時代にリリースされた、画期的すぎるソフトウェアでした。

そんなファミリーベーシックをヤフオクで(実行環境などをよく調べずに)落札し、しばらく経って実際にプログラミング環境を整えてみよう、と思い立ったのでした。普通に安いファミコン互換機(以下、FC互換機)を所有していたので、それを使って接続すればよい、と軽く考えていたのですが、いざ実際にパッケージを開けて接続してみようと思ったら意外な問題が発覚しました。



ファミリーベーシックは外付けキーボードを使うプログラミングソフトなのですが、この外付けキーボードはゲームコントローラーの代わりに本体に付けるものだとばかり思っていました(なのでファミコンのゲームコントローラーが使えるFC互換機であれば動かせると思っていました)。しかし実際には上記ツイートのようにエキスパンドコネクタと呼ばれる拡張インターフェースを使って接続する必要があるものだった、という事実が発覚したのでした。

自分が所有していたFC互換機を調べてみてもエキスパンドコネクタは付属していませんでした。ということは、少なくともこの時点で所有している機器だけではカセットを挿してソフトを起動することができてもキーボードを使って操作することはできない、ということです。それではプログラミング環境としてはあまりに貧弱なので、改めてエキスパンドコネクタ付きのFC互換機を探す必要がありました。

で、秋葉原に向かって、こういうのに詳しそうな「スーパーポテト」というお店へ行き、店長さんと相談しながら調べてみました。結論としては以下の2つの選択肢から選ぶ必要がありそうでした:
 ・互換機ではない「中古のファミコン」を購入するか、
 ・レトロフリークというFC互換機を、コントローラーアダプターセット付きで購入する

実はもう少し選択肢があるかと勝手に思い込んでいたのですが、エキスパンドコネクタ付属というのは思っていた以上に高い壁となりました。FC互換機で付属しているものは皆無で、唯一レトロフリークだけはオプション機器であるコントローラーアダプターセットがあればエキスパンドコネクタのインターフェースを持つこともできる、という状態でした。ちなみにFC互換機は安いものだと 2000 円前後で購入できるのですが、レトロフリークをコントローラーアダプター付きで購入すると 20000 円を超えます。出費額が完全に想定外。。。

ちなみにFC互換機でなく、本物のファミコンを中古で買う、という選択肢もありました(値段は少しだけこちらの方が安い)が、これだと AV 出力がアナログ、つまり昔のアナログ端子を持ったテレビでないと接続できません。一方のレトロフリークは HDMI 接続もできるという長所もあり、結論として、現在ファミリーベーシック環境を揃えるならレトロフリークが必要、ということになると思います。というわけでレトロフリークを購入しました:



こういってしまってはアレですが、昭和59年発売のゲームソフトを今の環境で再現する、という需要そのものが少ないと思っています。いますが、一方で「レトロフリークでファミリーベーシックを動かす」という環境での実現例を探すことができませんでした。「もしかしたら動かなかったりして・・」という不安に駆られつつも、実際に試せば済む話なので挑戦してみました(結論としては問題なく動きました)。

まずは普通(?)にレトロフリークを箱から取り出してセットアップします。本体にコントローラーを接続し、また HDMI ケーブルをモニターに接続して、それぞれの電源を ON にします。普通に起動しました。一般的なファミコンゲームソフトを動かすだけであれば、ゲーム ROM カセットをレトロフリークに差し込めば動くはず:
IMG_6241


さてここからがファミリーベーシックを使う場合のセットアップです。レトロフリーク付属のコントローラーアダプターがこれ。このアダプタにエキスパンドコネクタのインターフェースもついているので、こいつをレトロフリークに接続します:
IMG_6242


コントローラーアダプターをレトロフリークに接続し、そのエキスパンドコネクタにファミリーベーシックのキーボードを接続します。そしてファミリーベーシックのゲーム ROM も挿入:
IMG_6243


そして電源 ON ! おお!起動してるっぽい!! 
IMG_6245


そしてコントローラーのボタンを適当に押すと、なにやらメッセージが。「ワタシハファミリーコンピュータ デス」。ほうほう、そうですか。カタカナで聞かれるのがもう昔っぽい:
IMG_6248


そして「アナタハ ダレデスカ? ナマエヲ イレテクダサイ」と聞かれました。いよいよキーボード入力・・・ おお、普通に認識している!! レトロフリーク+HDMI 接続環境でもファミリーベーシックとそのキーボードはちゃんと動くようです:
IMG_6246


ちなみにこのキーボード、よく見ると "BS(Back Space)" キーがありません。間違えて入力した場合は矢印キーで戻って上書きしていくスタイルのようです:
IMG_6247


※ついでに書いておくと、このキーボードの F キーや J キーに他のキーと比べた特徴がなく、ブラインドタッチが非常に難しい、という難点がありました。。


そして約 30 年ぶりとなる古典 BASIC のプログラミング。当然スクリーンエディタ的な便利なものはなくて、プログラミングモードの画面に行番号を付けて入力していく感じ。とりあえず "HELLO WORLD."、まあ普通に動く動く: 
IMG_6251


なお、このソフトはプログラミングだけでなく、楽譜(音源)を入力して演奏させたり、日付を入力して(バイオリズム的な?)占いをすることもできます。世間では令和対応が間に合うとか間に合わないとか話題ですが、昭和59年製のこのソフトでは当然平成対応もしていません(笑):
IMG_6249


まあ表記以外は別にこれで困らないんだよな。。


今でもファミリーベーシックはヤフオクアマゾンで売られていることを見つけることがあって、入手困難というレベルではないと思っています。 ノスタルジーからつい買ってしまった人が現代の環境で実際に動かす際の参考になれば。



令和最初のブログエントリです。


Node.js アプリの中で git を使う方法を調べてみました。git で Node.js のソースコードを管理する、のではなく、アプリケーションの中で特定の git リポジトリに対して clone したり、pull したり、add して commit して push したり、、、といった操作を Node.js アプリ側から行う方法、という意味です。

この操作を実現するためのライブラリとして simple-git というものを使ってみました。npm を使って以下のコマンドを実行することで導入できます:
$ npm install simple-git

2019050201


そして、以下のコードで扱う git リポジトリは https://github.com/dotnsf/simple-git-sample.git であると仮定します。異なるリポジトリで実験する場合は( fork してコピーを作るなどして)適宜読み替えてください。またローカル側のワーキングフォルダ(git で管理するフォルダ)は ./work/ であると仮定します。


【初期化】
まず、このライブラリを使って Node.js アプリを作る際の初期化方法を紹介します(実はここが一番ややこしい所だったりします)。ここは「実行時に git clone して初期化」するのか、「実行時に git pull して初期化」するのかによって手順が異なります。

実行時に git clone して初期化する場合は以下のようにします:
//. git-clone.js
var git = require( 'simple-git' );

var git_url = 'https://github.com/dotnsf/simple-git-sample.git';
var local_folder = 'work';


//. clone
git().clone( git_url, local_folder );

このコードを node コマンドで実行すると、work/ というフォルダが新規に作成され、https://github.com/dotnsf/simple-git-sample.git のクローンがそのフォルダの中に作成されます。

一方、実行時に git pull して初期化する場合は以下のようにします:
//. git-pull.js
var git = require( 'simple-git' );

var git_url = 'https://github.com/dotnsf/simple-git-sample.git';
var local_folder = 'work';


//. pull
git( local_folder ).pull();

このコードを node コマンドで実行すると、既にワーキングフォルダとして存在している ./work/ フォルダの中に最新のリポジトリ状態が git pull されます。

ここでややこしいのが「どちらを使って初期化するべきか?」です。既にワーキングフォルダ ./work/ が存在している状態で git clone を実行するとエラーになってしまうし、一方ワーキングフォルダが存在していない状態では git pull してもエラーとなってしまうからです。というわけで、以下のように実行すべきだと思いました:
//. git-init.js
var git = require( 'simple-git' );
var fs = require( 'fs' );
var path = require( 'path' );

var git_url = 'https://github.com/dotnsf/simple-git-sample.git';
var local_folder = 'work';

//. フォルダの存在確認
var dirname = path.dirname( './' + local_folder );
fs.access( dirname, fs.constants.R_OK | fs.constants.W_OK, ( err ) => {
  if( err ){
    //. clone
    git().clone( git_url, local_folder );
  }else{
    //. pull
    git( local_folder ).pull();
  }
});

ワーキングフォルダが存在しているかどうかを確認し、存在していなかった場合は git clone を、存在していた場合は(git clone 済みと解釈して)git pull を、それぞれ実行して初期化しています。


【ファイル追加】
次にこの(初期化済みの)ライブラリを使って、リポジトリにファイルを追加する方法を紹介します。厳密にいうと「(git pull して、)git add して、git commit して、git push する」までの一連の方法を紹介します。

といっても、実は結構簡単でこんな感じで一連の処理を実現できます:
//. git-push.js
var git = require( 'simple-git' );
var fs = require( 'fs' );
var path = require( 'path' );

var git_url = 'https://github.com/dotnsf/simple-git-sample.git';
var local_folder = 'work';

//. pull, add, commit, and push
git( local_folder ).pull()
  .add( 'README.md' )
  .commit( 'README.md updated.' )
  .push( [ '-u', 'origin', 'master' ] );

add() のパラメータに追加したいファイル名、commit() のパラメータにはコミットメッセージ、そして push のパラメータにはオプションを指定します(この例だと $ git push -u origin master を実行しているのと同じ処理をしています)。


実際にはブランチ切ったり、マージが必要になったりすることもあるので、全ての git 処理を全自動でというのはなかなか難しい所もあると思いますが、一連の決まった処理を(例外処理無しで)実現するにはシンプルで便利なライブラリだと思いました。


このページのトップヘ