TOP > プログラミング関係解説&調査

プログラミング関係解説&調査

本攻略のトップページでも紹介しているが、本作のデータや各種計算式(ダメージ量の算出方法など)は、以下ウェブサイト様に掲載されており、本攻略でも引用させていただいている。

見ればわかるとおり、上のふたつのウェブサイト様は、「ライブ・ア・ライブ」関連の知識の教科書兼百科事典と言っても過言ではない。
当コンテンツは、教科書兼百科事典の副読本程度として、「どうしてそういう計算式になるのか?」「ここに載っている以外の計算方法は?」といった話を紹介することが目的である。

計算式を理解する上で必要な数学・プログラミングの基礎知識については、プログラミング関係の表記及び解説で紹介したが、ここでは更に一歩踏み込んで、実際のプログラムではどうなっているのか、という話をする。
ただし筆者はプログラミングについて大した知識はないため、プログラム内容を見てみてもわからないこともあるし、間違った読み方をしていることもあるかもしれないことをお断りさせていただく。

それぞれの解説ページは以下リンクから飛べるが、その前に、この先の説明にひととおり目を通していただきたい。

このページでは、以降の説明を読む上で必要となる基本事項について述べている。

スーパーファミコンのプログラムについて

「ライブ・ア・ライブ」はスーパーファミコンのゲームソフトなので、まず、スーパーファミコンのプログラムの方式についてざっと説明する。

スーパーファミコンのCPU(演算などを行う装置)は、65C816互換16ビットマイクロプロセッサ(厳密には「Ricoh 5A22」というカスタム版CPU)が使われている。
このCPU向けのプログラム言語はアセンブリ言語という言語が使われており、アセンブリ言語はCPUにより仕様が変わるため、スーパーファミコンのプログラムは65C816向けのアセンブリ言語(以下単に「65C816」とする)で書かれている。
アセンブリ言語 - Wikipedia及び、65816 (コンピュータ) - Wikipediaも参照のこと。
当コンテンツでは、65C816のプログラムの説明をしているため、ある程度のプログラミングの知識がないとわかりにくいと思われる。

リメイク版発売の2020年代に主流となっているプログラミング言語(C系言語、Python、JavaScriptなど)は、人間が読み書きする時に比較的わかりやすい、高水準言語(高水準言語 - Wikipedia)と呼ばれるものなのだが、アセンブリ言語は人間側にもコンピュータ側にもわかりやすいことを優先した低水準言語(低水準言語 - Wikipedia)であるので、高水準言語の知識がある程度あるとしても、アセンブリ言語の読み書きはややハードルが高い。
また、1980年~90年代のコンピュータの技術であるから、現代から見るとプログラミングにかなり制限があるように見えることも(扱える数字の幅が狭い、乗除算の手間がかかるなど)、ハードルの高さに繋がっている。
ただし、プログラムの基本構造である、「ある条件で分岐する」や「ある条件を満たすまで繰り返す」という理屈は、どんな言語でもだいたい同じである。
ここでは、細かいことは抜きにして、「そういう理屈でプログラムが書かれている」という説明を中心にしたつもりである。
わかりにくいところは飛ばして、結論だけ見る程度でも構わない。

65C816はスーパーファミコンのプログラミング言語として使われているため、検索してみると、それなりに解説や資料が見つかる。
英語の資料が多いが、日本語での説明もあるため、参考にしていただきたい(筆者も参考にさせていただいた)。

「ライブ・ア・ライブ」のデータについて

「ライブ・ア・ライブ」は、容量が「16メガビットロムカセット」のスーパーファミコンソフトであり、内部データはすべてのデータが16進法、0~9,A,B,C,D,E,Fの16文字で記されている。
1ビットとは2進法での1文字分。16進法での1文字は8ビットに当たる。16メガビット=16,000,000ビットで、16進法の文字では2,000,000文字分ということになる。
内部データをパッと見ただけでは、数字とA~Fの文字が2,000,000文字分、ずらずら並んでいるだけで意味不明である(この状態でもプログラミングに慣れている人はデータを読み取れるそうだが)。
スーパーファミコンのカセット内に記録された内部データを、スーパーファミコン本体のメモリ領域に読み込み(ロード)して、プログラムを実行しゲームがプレイできるのである。
バーチャルコンソールの場合は、Wii Uやニンテンドー3DSの本体に、カセット内データを保存してあり、それを読み込んでいるということになる(はずだが、筆者はバーチャルコンソールの仕組みまではわからない)。

16進法で内部データが記されているが、16進法の2ケタ分(2文字分)を1バイト(Byte)として、2文字ずつ区切り、1バイトごとにナンバー(16進法)を振って、場所(アドレス)を決めている。
たとえば、データが

01 23 45 67 89 AB CD EF 98 76 54 32 10 FE DC BA

こんな感じだったら、01のアドレスは「00」(1番目)、ABのアドレスは「05」(6番目)、DCのアドレスは「0E」(15番目)である。

スーパーファミコンのカセットのデータは、スーパーファミコン本体のメモリ領域に読み込み(ロード)するが、本体のメモリ領域の場所にも番号を振ってアドレスが決められている。
番号は16進数で6桁であり、上2桁を「バンク」、下4桁を「アドレス」と呼ぶ。
形式としては、バンクとアドレスで区切り、更に16進数であることを示すために頭に「$」をつけ、
$00:0000
や、
$00/0000
としたり、区切りなしで記すこともある。
また、同一バンク内で、アドレスのみを記す時は下4桁だけ「$0000」とする場合もある。
最大値は$FF:FFFFになる。
とりあえず「こんな風に表記していたら、メモリの位置を示したアドレスのこと」だと思ってくだされば問題ない。

ゲームデータの16メガビット内には、キャラクターや敵のデータ、技やアイテムのデータ、グラフィック関連のデータ、効果音やBGMなど音関連のデータ、セリフなどテキストデータ、そしてそれらを実際にゲームとして動かすためのプログラムのデータが詰め込まれている。
当コンテンツで紹介するのは主に、色々なデータをゲームとして動かすためのプログラム部分である。

2進法・16進法

プログラミングの話をする上では、中学~高校数学の基本的な知識と共に、コンピュータで扱われる2進法・16進法の知識があることが望ましい。最低限、仕組みについては知っておいた方が良い。
65C816では、数値はすべて16進数で表記し、2進法や16進法ならではのテクニックで計算を行うことが多いからである。

数学関連だと、基本的な四則演算(累乗など含む)、中学~高校数学レベルの確率計算と、高校数学で習う、数列・漸化式(漸化式 - Wikipedia)の知識があるのが望ましい。

また、65C816では、頭に$をつけることで16進数の数値であることを示す。
つまり「$12」は16進数表記だから、10進数では「18」である。
$FF」は2桁の16進数の最大値で、10進数だと「255」である。
2進数の場合は頭に%をつけて「%0101」(10進数の5)とするが、65C816の中ではこの表記をすることはまずない(たぶん)。
ただ、2進数の考え方が必要な時、説明には使うかもしれない。

ビット(bit)やバイト(byte)などの単位について

コンピュータでのデータ容量の単位はビットやバイトなど、似たようなネーミングの単位があって少しややこしい。
16進法での1文字である8ビットを1単位分と考えるのが、バイト(byte)である。
つまり8ビット = 1バイトである。
スーパーファミコンのゲームソフトのデータは、16進法の文字で書かれているので、「バイト」を単位にするとわかりやすいことがある。

2進法だと1文字分の最小単位が1ビットで、16進法だと1文字分の最小単位が1バイト(= 8ビット)である。
と、いうことである。

スーパーファミコン&65C816の基礎知識

この先、プログラムに関してはその都度説明を付けているが、頻出となる、重要度の高い65C816の仕様についてまとめておく。

「レジスタ」について

「レジスタ」は、プログラムの実行中、一時的に様々な値(16進数)を記録しておく場所のことである。
メインで使うことになるのが、「アキュムレータ」という名前のレジスタで、当コンテンツでは「Aレジスタ」としたり、頭文字をとってAと省略表記していることが多い。
省略表記するくらい頻出という意味でもある。

他に「インデックスレジスタX」「インデックスレジスタY」というレジスタも頻出であり、当コンテンツでは「Xレジスタ」「Yレジスタ」としたり、頭文字をとってX, Yと表記することが多い。

レジスタには値を一時的に記録しておく、と記したが、65C816で記録できる値(つまり計算などで使える値)には制限がある。
4バイト(16進数で4文字)分が限度なので、0から16進数FFFF(10進数65535)まで、ということになる。

レジスタには値を「記録する(書き込む)」、記録された値を「読み込む」ことができるが、値の桁数が大きいほど読み書きに時間がかかることになる。
よって、レジスタの「下2桁だけ読み書きする」「4桁すべて読み書きする」と、読み書きの桁数を切り替えることで、読み書きの時間を変え、プログラム実行時間を変更することができる。要するに基本的な時短テクニックである。
2桁のみで読み書きするのが「8bitモード」で、4桁すべて使うのが「16bitモード」である。
「8bitモード」の方が扱う桁が少ないから、読み書きの時間が少なくて済む。
よって、基本的には、「必要がない限り8bitモードでプログラムを実行する」ことになる。

「プロセッサステータスレジスタ」とフラグ

「レジスタ」には何種類かあり、重要なのは上で紹介したA, X, Yの3種類である。
それに加えてもうひとつ、「プロセッサステータスレジスタ」というものについても覚えておく方が良い。
ここには8ビット分、つまり2進法で8文字分のデータの記録しかできないのだが、1文字ずつが重要な意味を持つ。
8文字がそれぞれ別々の名前を持っており、「ネガティブフラグ」や「ゼロフラグ」、「キャリーフラグ」など、「○○フラグ」という名前がついていて、2進法1文字分の「0か1」しかデータが入っていない。
言い換えると「そのフラグがONかOFFか」というデータが入っているだけである。
1ならON、0ならOFFで、ONの時は「フラグが立つ」、OFFにする時は「フラグをクリアする」などという言い方をする。
また、各フラグは頭文字だけ取ってNフラグやZフラグ、Cフラグと省略表記することもある。

フラグの中で覚えておくと良いのは、上にも記した「ゼロフラグ」「キャリーフラグ」である。
「ゼロフラグ」は文字通りに、「何かを計算した結果、0になった」や、「何かの値をロードしたら、その値は0だった」など、結果が0の時にONになる。
これがどのような時に使われるかというと、例えば、「攻撃した相手がオディオモールだったら、ダメージ量は1に変更する」という条件分岐の時、

  1. 「現在攻撃した敵のID」-「オディオモールのID」を計算する
  2. ゼロフラグが立ったら(つまり引き算の結果が0なら)、ダメージ量を1にする

こんな風に使えるし、実際にこんな風に内部で計算されているのである。

「キャリーフラグ」は少しややこしい。
結論だけ先に書くと、「2進数で計算した時、足し算で繰り上がりが起きた または 引き算で繰り下がりが起きなかった」時にキャリーフラグがONになる。
このややこしいフラグも、ゼロフラグに近い形で条件分岐に使える。
たとえば、0~255の乱数を、疑似乱数計算で作ったとする。
作った乱数が、0~127だったら「テレポートコマンドが成功して通常通り逃げられる」、128~255だったら「テレポートコマンドが失敗しチビッコハウスに飛ばされる」というように分岐させたい場合は、

  1. 乱数 - 128」を計算する
    (実際には2進数の計算なので、乱数は「00000000~11111111」であり、128は2進数で「10000000」である)
  2. キャリーフラグによって条件分岐させる
    • キャリーフラグが立つ場合(減算の結果が0か正の数の時)、テレポート成功で逃げられる
    • キャリーフラグが立たない場合(減算の結果が負の数の時)、テレポートコマンド失敗時の飛び先計算に進む

このように実行可能なプログラムを書けば良い。
2進数「10000000」を引く時、一番上の位(27の位)にしか「1」がないから、引き算で繰り下がりが生じるのは、27の位が「0」の数だけである。
この条件を満たすのは、2進数「10000000」より小さい、「0???????」の時のみ、つまり10進数でいえば127以下の数だけである。
よって、乱数が128~255の時、「乱数-128」で繰り下がりが生じず、キャリーフラグが立つのでテレポート成功で逃げられる。
逆に、乱数が0~127の時、「乱数-128」で繰り下がりが生じ、キャリーフラグが立たないのでテレポートコマンド失敗判定である。

という判定が、実際にテレポート実行時に行われている。

以上の、ゼロフラグによる分岐と、キャリーフラグによる分岐は、「ライブ・ア・ライブ」のプログラム内で頻繁に行われている。
上のとおり、ゼロフラグによる分岐は「ある値とある値が同一かどうか」の判断に、キャリーフラグによる分岐は「乱数によって条件分岐する場合」に使用することが多い。

キャリーフラグの詳細は
キャリーフラグとオーバーフロー
にある通りだが、非常にややこしく難しいので、無理に理解する必要はない。

なお上で名前だけ出した「ネガティブフラグ」もそこそこ登場するが、これは「2進数で負の数」の時に立つフラグである。
10進数なら負の数といえば、頭にマイナスがついた「-1」などと表現するが、2進数の負の数はマイナスの記号を使わない。
理屈としては上のキャリーフラグと通じる部分があり、2進数に慣れていないとわかりにくいが、きちんと知りたいのなら以下あたりを読んでいただきたい。

65C816の命令(ニーモニック)

65C816のプログラムは、何をするかをアルファベット大文字3文字で命令していくことで成り立っている。
このアルファベット大文字3文字の命令のことを「ニーモニック」といって、色々な命令があるが、プログラマーでない限り、それらをまるごと暗記する必要はない。
わからなければ、命令一覧から調べれば良いだけである。
命令(ニーモニック)は、
65C816 プログラミング リファレンス
ここなどで調べれば良い。

たとえば「LDA」という命令があるが、これは上で説明したアキュムレータ(A)に、指定した値をロード(読み込み)しろ、という意味である。
値の指定方法が色々とあるのが少しややこしいが、これも命令一覧で何の意味か調べれば良いだけなので無理に覚える必要はない。
とりあえず書き方としては、

LDA #$01

こんな感じで、命令の後に読み込みたい数値や、内部データのアドレスを記す。
頭に「#」がついている時は数値であり、上の命令は「Aに16進数の01をロードしろ」の意味になる。
アドレスは先に説明した通り、

LDA $7EFEF0

このようにアドレスの数値を指定し、頭には「#」を付けない。
上の命令は、「Aにアドレス$7EFEF0の中に入っている数値をロードしろ」の意味になる。
($7EFEF0という数値のロードではない)
他にも色々な指定の方法があるが、どれが何の意味かは、その都度解説しているので参照していただきたい。

また、この先では、

$C1/85D9 LDA $7EFEF0 ;Aに[$7EFEF0]をロード

このように命令&解説を記しているが、最初の「$C1/85D9」は、命令「LDA $7EFEF0」が書かれているアドレスのことである(よって、実際にはプログラムには書かれていない)。
「;」以降は解説で、「;」を付けた後から改行までの文章は、プログラムで読み込まないようになっている。
(ついでに、色分けはわかりやすさ重視でしてあるだけである)

基本の計算方法

65C816における基本的な計算方法をまとめておく。
足し算や引き算は、該当のニーモニックを使えば良いのだが(足し算はADC、引き算はSBC、他に「+1」や「-1」するための専用のニーモニックもある)、他の計算には一工夫必要である。
また、16進数や2進数の計算であることを利用したテクニックもいくつかある。

なお、プログラミング関係の表記及び解説で記したとおり、65C816での計算では、掛け算や割り算の結果で小数点以下の端数が出たら切り捨ての処理を行う、ということも覚えておくこと。

掛け算と割り算

まず、65C816には、乗除算、つまり掛け算と割り算の機能はない。
(実は引き算もできず、足し算しかできないという話は、キャリーフラグとオーバーフローにある通りである)
乗除算をする方法は、

ここなどに記されているとおりである。
簡単にまとめると、

  • 2倍する(×2):ASL(算術左シフト)を使う
  • 2で割る(÷2):LSR(論理右シフト)を使う
  • それ以外:コプロセッサというCPUの拡張機能で上サイト様のようなコードを使って行う

となっている。
※単に割り算のやり方としてこういうものがあると覚えていていただければ良いが、「算術左シフト」や「論理右シフト」について詳しくは、 ビット演算 > ビットシフト - Wikipediaなどを参照のこと。

また、特定の数で掛け算や割り算をする時に使える方法もある。
本作のプログラムでよく出てくるのが、「256で割る」、16進数でいえば「$100で割る」方法である。

わかりやすくするため、我々が普段使う10進法の話にする。
÷100÷102)を計算する場合、小数点を2つ左に移動させる。
例えば、
1234.56÷100 = 12.3456
である。この時、動いたのは小数点だけで、数字の並び自体はまったく変化していない。

では16進法だとどうなるかというと、小数点を2つ左にずらすということは162 = 256で割り算をすることと同義である。
つまり16進法での÷256の計算とは、16進法において小数点を2つ左にずらすことである。
例えば16進法で「$1234」という数に対し÷256(10進法)を行うと、小数点が2つ左に移るから、上の2桁だけ取り「$12」が答えなのである(これまでも述べたとおり、65C816での計算で小数点以下の数値が出たら切り捨て処理なので、下2桁の34は切り捨てられる)。

割り算の時だけではなく、16進法で4桁の数から、上2桁だけを取り出して2桁の数にしたい(上で言えば「$1234」から上2桁の「$12」だけ取り出す)という処理も、結局は「256で割る」計算をすれば可能ということである。

8bitモードと16bitモードの応用

8bitモードと16bitモードの切り替えで、実質的な割り算をする方法もある。
8bitモードでは16進数で2桁(2バイト)、16bitモードで4桁(4バイト)の数値をレジスタ(AXY)に出し入れできる。
だが、出し入れする先のアドレスのメモリには、2バイトしか数値が収まらない。
16bitモードで4バイトの数値をメモリに入れろ、という命令の時、どうやって2バイト分のメモリに値を入れるのだろうか?

こういう時には、「下2桁分の2バイトは、指定先のアドレスに値を入れる」「上2桁分の2バイトは、指定先のアドレスに+1した場所に値を入れる」という仕様になっている。
入れる時だけではなく、出す(ロードする)時でも同じである。
たとえば、16bitモードで、$1234という値を、メモリのアドレス[$00:0030]に入れろ、という命令があったとしよう。
この時は、下2桁の$34[$00:0030]に入り、上2桁の$12[$00:0031]に入る。
ではこの後に8bitモードに切り替えて、[$00:0031]Aに読み込め、という命令を実行するとどうなるか。
Aには、[$00:0031]から$12が読み込まれる。
最初の数値$1234から、上2桁の$12だけ読み込んだので、実質上と同じように「256で割る」計算をしたのと同じである。

ということからもわかる通り、現在8bitモードなのか、それとも16bitモードなのかは、数値の読み書きをする上で重要である。
8bitモードの時は、レジスタに4桁の値が入っていても、下2桁だけで計算をする、ということも覚えておくこと。

論理積と「数値の取り出し」

プログラミング関係の表記及び解説の、ビット演算で説明したことの繰り返しになるが、これも頻出な計算方法なので紹介しておく。

ダメージ量計算には、敵や味方のステータスが必要になる。
それら各種データは、スーパーファミコンのカセット内部からスーパーファミコン本体のメモリに読み込まれているのだが、丁寧に「ローキックの属性は足技で、最大2ヒット」などと細かい説明までされてはいない。
ひとつの技につき、16進数で50文字分、つまり50バイト分のデータしか書かれていないのである。
各技には番号が振られていて、その番号の順に、50バイトずつデータがずらずらと並んでいる。
このコンテンツでは、便宜上、2バイト(2桁)ずつ区切って、「技データ0」から「技データ24」と名前を付けている。
(というのは、メモリ上のアドレス1個につき2バイト分のデータを格納できるため、2バイトで区切るのがわかりやすいからである)
例えば技データ17は、1桁目の数値が「技が発動するまでの待機時間」で、2桁目の数値が「技LV」となっている。
ダメージ量計算に必要な、「技LV」だけを取り出したい場合、

  1. 技データ17をアキュムレータ(A)にロードする
  2. ロードした値の下1桁だけ取り出す

という、2段階の作業が必要になる。
この時に役立つのが「論理積」である。
ビット演算における「論理積」とは、2個の数値を2進数にし、各桁の数値を比較して、共通して「1」なら「1」に、それ以外だったら「0」にする、という計算のことである。

実際に、「忍法矢車草」の技データ17「$2A」から、「技LV」を取り出すことを考えてみる。
$2Aは2進数で「0010 1010」である。
(プログラマー電卓があれば変換が楽。Windowsパソコン付属の電卓でも可能)
2進数の上4桁(4ビット)が、16進数での上1桁(1バイト)の部分であり、2進数の下4桁(4ビット)が、16進数での下1桁(1バイト)の部分である。
技LVのみ、つまり16進数の下1桁を取り出したいのであれば、2進数の下4桁がすべて「1」である、「0000 1111」との論理積を取れば良い。
0010 1010」と「0000 1111」の論理積を取ると、上4ビット分がすべて0、下4ビット分はそのままの、「0000 1010」となる。
これを16進数に戻すと、「$2A」と「$0F」の論理積をとって「$0A」になった、という計算になる。

なお、「$0A」は10進数の10だから、「忍法矢車草」の技LVは10である。
また、上の桁の「$20」は「技が発動するまでの待機時間」なので、「忍法矢車草」の待機時間は10進数で32となる。

というのが「論理積」の使い方である。
結局のところ、特定の桁を取り出したい時、16進数なら、取り出したい桁はF、それ以外は0の2進数で論理積を取れば良い、というのが結論になる。
アキュムレータと指定の値で論理積を取るニーモニックは「AND」なので、「AND #$0F」という命令が出てきたら、「Aに入っている数値の下1桁だけ取り出したいのだな」という判断ができる。

なお、技データの中には、2進数にした時に上2ビット分だけ取り出して計算する値なども存在する。
そういう時は「1100 0000」との論理積を取れば良いことになる。
とりあえず、「論理積を取っている時は、何かの数値を取り出したいのだろう」と見当がつくということである。

用語集

その他、当コンテンツでよく使う用語について記しておく。

サブルーチン

プログラミング用語における「サブルーチン」について説明する。
この用語は、65C816やアセンブリ言語だけではなく、他のプログラミング言語でも使われる一般的な用語なので、知っている方は飛ばして構わない。

プログラム内におけるひとまとまりの計算手順のことを、プログラミング用語で「Subroutine/サブルーチン」という。
先程の、テレポートの話であれば、

  1. 乱数 - 128」を計算する
    (実際には2進数の計算なので、乱数は「00000000~11111111」であり、128は2進数で「10000000」である)
  2. キャリーフラグによって条件分岐させる
    • キャリーフラグが立ったらテレポート成功で逃げられる
    • キャリーフラグが立たない場合はテレポートコマンド失敗時の飛び先計算に進む

この一連の手順(プログラム)は、「テレポート」コマンドを選ぶ度に毎回実行される。
「テレポートの成功・失敗判断用サブルーチン」という言い方ができる。
また、このテレポート判断用サブルーチンの前には、乱数を生成する計算をしている。
乱数生成用の一連の手順もまたサブルーチンであり、いわば「乱数生成用サブルーチン」である。
本作ではテレポートだけではなく、籐兵衛のアイテム改造が成功するか失敗するか、また、2~3種類から改造先が選ばれる時に何が選ばれるか、など、色々な場面で乱数が必要とされ、その都度「乱数生成用サブルーチン」を実行している。

というような形で「サブルーチン」という言葉をよく使って説明をするので、覚えておいていただきたい。

フレーム

フレームレート - Wikipedia

「フレーム」(frame)という英単語自体には色々な意味があるが、当コンテンツにおいては「フレームレート」の意味で使っている。
ゲームや映像において、「フレームレート」とは、1秒あたり画面に何枚の絵を表示できるか、その枚数を示すと考えていただいて良い。
単位は「Frames Per Second」、頭文字を取って「FPS」である。
ゲーム好きなら、「ゲーム画面の滑らかさの単位」という意味で「FPS」を捉えている人が多いだろうが、概ね、それで正解である。
スーパーファミコンは、60FPSでプログラムを処理し、画面の表示ができる。
つまり、1秒あたり60枚の絵を表示可能である。
このため、1/60秒を単位として「1フレーム」という言い方をする。

人間からすれば、1フレームというのはほんの一瞬である。
だが、本作においては(というか、他のスーパーファミコンのゲームでもできるが)、実はその1フレームの間に乱数を生成するサブルーチンを1周回して、1フレームに1個、乱数を作っている。幕末編や西部編だったら、同時に「1分間隔で鐘を鳴らす」というタイマー処理もやっているし、背景やキャラクターといった画像の処理もして、BGMを流し、場面に合ったサウンドエフェクトも鳴らしている。中世編や最終編はランダムエンカウント関係の計算もしている。
それくらいの処理能力を持っているのがスーパーファミコンというゲームハードであり、当時のプログラマーが工夫した様々なプログラムが動いていたのである。

なお、リメイク版の「ライブアライブ」は、Nintendo Switch版が30FPS、PlayStation4版が60FPS、Steam版はプレイするパソコンなどのスペックにより60FPS以上に上げることも可能、となっている。
ただしリメイク版の時代においては、スーパーファミコンの時代とは異なり、グラフィック処理において3D描画など桁違いの性能を必要とするし、そもそも表示する画面のサイズ(解像度)や色数などの基本スペックがまったく異なるので、単純にFPSだけで処理能力の比較はできない。

この「フレーム」という単位も、本作のプログラムを説明する上で時折登場するので、用語として説明した次第である。
例えば、本作には西部編の罠仕掛けなど、時間制限イベントが存在するが、この時にどのように「鐘が鳴るまでの1分間」を測定しているのかというと、「1フレームでカウントが1減るカウントダウンタイマー」を使っている。
幕末編の1分間隔に鳴る鐘や、原始編で荒野に追い出された時に時間経過でフィールドが暗くなっていくのも、この「1フレームでカウントが1減るカウントダウンタイマー」を利用したイベントである。

余談だが、1/60秒、1フレームの間にスーパーファミコンはどれくらいの処理ができるのか。
上で、

LDA #$01

というプログラム(1回分のニーモニック)を紹介した。
実際には、

LDA #$01
STA $22
STZ $23
LDA #$08
STA $08
STZ $20
LDA $7ECE00,x
JSR $20CD
……

というように、ニーモニックがひたすら続いていく。
1回のニーモニックの処理時間は内容により少しずつ違うので厳密に何回できるのかは明言できないが、「ライブ・ア・ライブ」のプログラムでいえば、1フレームの間にニーモニックを10,000回くらい処理してしまう。
1秒だと60倍だから、600,000回くらい
コンピュータに慣れ親しんでいないと、とんでもない回数の計算をこなしているように見える。
だがこれでも1980~90年代の技術であり、リメイク版が発売された2020年代のゲーム機は当然、計算回数が桁違いに増加している(らしい)。
詳しいことを知りたいのなら「クロック周波数」などで調べてみると良い。



このページをシェアする

上へ