NesTalkでマリオを動かす

Pharo上でマリオが動くという。ウチのゼミではマリオゲームもどきを作っているだけに、どんなものかを試してみた。
NesTalkというパッケージがそれらしい。パッケージ名のとおりNESのエミュレータをPharoで実装したもののようである。
YouTubeのビデオを見るとちゃんと動いていることがわかる。
そのままインストールしようとするとパッケージが不足している旨の警告が出るため、BabyMockのインストールからはじめる。

MCHttpRepository
    location: 'http://ss3.gemstone.com/ss/BabyMock'
    user: ''
    password: ''

上記のレポジトリから、ConfigurationOfBabyMockをインストールする。続いて、

ConfigurationOfBabyMock loadDevelopment.

によってBabyMockをインストールする。
次に、以下のレポジトリからNesTalkをインストールする。

MCHttpRepository
	location: 'http://smalltalkhub.com/mc/zeroflag/NesTalk/main'
	user: ''
	password: ''

適当にロムイメージを入手して、以下のように起動する。パス名の指定のところは適当に変える必要がある。

nes := NesTalk new.
nes insertCartridge: (NtCartridge romFile: (FileSystem disk workingDirectory / 'mario_bros' / 'Mario Bros.nes') pathString).
nes powerOn.

終わったらビデオの通り、以下のようにシャットダウンする。

nes powerOff.

うちの環境(MacBookAir)では、8キーで左、0キーで右に移動できたが、その他のキーがよくわからないためクリアすることはできなかった。
どうやらキーコードの取り方の問題のようで、NesTalkWindow>>#handlesKeyDown:と#handlesKeyUp:を変更することで操作できるようになった。

handlesKeyDown: anEvent
	anEvent keyValue = 6 ifTrue: [joypad pressButtonAt: NtJoypad buttonA. ^ true].
	anEvent keyValue = 7 ifTrue: [joypad pressButtonAt: NtJoypad buttonB. ^ true].
	anEvent keyValue = 125 ifTrue: [joypad pressButtonAt: NtJoypad buttonDown. ^ true].
	anEvent keyValue = 126 ifTrue: [joypad pressButtonAt: NtJoypad buttonUp. ^ true].
	anEvent keyValue = 123 ifTrue: [joypad pressButtonAt: NtJoypad buttonLeft. ^ true].
	anEvent keyValue = 124 ifTrue: [joypad pressButtonAt: NtJoypad buttonRight. ^ true].
	anEvent keyValue = 36 ifTrue: [joypad pressButtonAt: NtJoypad buttonStart. ^ true].
	anEvent keyValue = 49 ifTrue: [joypad pressButtonAt: NtJoypad buttonSelect. ^ true].
	^ false
handlesKeyUp: anEvent
	anEvent keyValue = 6 ifTrue: [joypad releaseButtonAt: NtJoypad buttonA. ^ true].
	anEvent keyValue = 7 ifTrue: [joypad releaseButtonAt: NtJoypad buttonB. ^ true].
	anEvent keyValue = 125 ifTrue: [joypad releaseButtonAt: NtJoypad buttonDown. ^ true].
	anEvent keyValue = 126 ifTrue: [joypad releaseButtonAt: NtJoypad buttonUp. ^ true].
	anEvent keyValue = 123 ifTrue: [joypad releaseButtonAt: NtJoypad buttonLeft. ^ true].
	anEvent keyValue = 124 ifTrue: [joypad releaseButtonAt: NtJoypad buttonRight. ^ true].
	anEvent keyValue = 36 ifTrue: [joypad releaseButtonAt: NtJoypad buttonStart. ^ true].
	anEvent keyValue = 49 ifTrue: [joypad releaseButtonAt: NtJoypad buttonSelect. ^ true].
	^ false

なお、上記の変更を行えば、Mac以外の環境では動かないと思われるので注意。