Technically Impossible

Lets look at the weak link in your statement. Anything "Technically Impossible" basically means we haven't figured out how yet.

Xanadu Clone - ザナドゥ クローン(ザナクロ)をソースからコンパイル、ビルドする。~RAD Studio (C++Builder)

f:id:espio999:20210711202715p:plain
XANADU』(ザナドゥ)とは、80年代の名作PCゲームだ。アクションRPGに分類されるゲームだが、それではゲームの本質的な特徴を網羅しきれない。その詳細は、Wikipediaをはじめ、様々なネット・メディアで語られているし*1YouTubeでも多数の攻略動画が配信されている。
端的には、トレードオフを伴う、限られたリソース(モンスターの数、得られる経験値、アイテム、資金…)を按配して、キングドラゴンを倒すゲームだ。目的を果たす以外に、ストーリーや謎解きの要素は一切なく、前述の制約に基づいてプレイヤーなりの「攻略」を楽しむ。

Rogue』のクローンがオープンソース、フリーウェアとして流通している様に、『XANADU』にもクローンが存在していることに気付いた。しかし、それはオープンソースでも、フリーウェアでもなかったのだが、実行ファイルとともに、ソースコードMakefileまで収録されていたのには、驚かされた。
web.archive.org

そのC言語で記述されたコードは、役割、機能ごとに明瞭に区別、整理されており、コメントも適切に挿入されていることから、とても読みやすいものだった。
リソース(画像、音声、マップ、モンスターなど)はソースとは独立しており、設定やファイル名を書き換えることで差し替えることができる。レベルごとのフロア構成、モンスター配置はバイナリ・ファイルだった。
一方、ゲーム上の仕掛け、仕組みだけでなく、武器や魔法、ユーザーのデータはソース中に記述されており、それらの改変にはソースコードのリビルドを伴うのだった。つまり「強くてニューゲーム」的な遊び方をするには、プログラムを書き換え、それらをビルドする必要がある。

まずは、ソースコード全体がエラーなく、コンパイルできる状態であるのかを確認しておく必要がある。エラーなくコンパイルを完了し、実行ファイルが出力されることを目的として、ザナクロをビルドし、独自の実行ファイルを出力する手順を紹介する。

念のため、次の2点を申し添えておく。

前提

Xanadu Clone

prosbiboroku.blogspot.com
この参照先によると、ザナクロには複数のバージョンが存在しているようだ。そして、それらは単純にバージョン・アップを積み重ねたものではなく、異なる開発者が、それぞれにフォーク版をリリースした結果であることが読み取れる。
私が参照しているソースコードは、「Ver.08-392」に該当しているようだ。実行中の画面から”REVISION 1.1.4”の記載を確認できた。
f:id:espio999:20210711203049p:plain

ツール

この投稿で紹介する作業では、次のツールを用いる。必要なものをダウンロード、インストールする。

DCS ファイルの文字コードをUTF8へ変換する。
Make for Windows Makefileを実行する。
C++Builder Community Edition ソースコードコンパイル、ビルドする。

ツールのダウンロード
www.vector.co.jp
gnuwin32.sourceforge.net
www.embarcadero.com

RAD Studio - C++Builder Community Edition

RAD Studio (C++ Builder Community Edition)のインストールに際し、オプション選択を求められる。この投稿で紹介するコードの読解、コンパイル、ビルドの範囲であれば、最低限のオプションで構わない。コンパイル、ビルドの範囲であれば、実際のところGUIすら必要ない。
端的には、「オプション選択」で示すように”C++ Builder Windows 32-bit Community”さえインストールできていればよい。

オプション選択
f:id:espio999:20210716004143p:plainf:id:espio999:20210716004151p:plain

紹介する作業手順では、コマンドを実行するに際し、適切に環境変数が設定されていることを前提としている。各ツールのインストール先は、各自の環境によって異なるだろう。各自の適切なパスを設定すること。
この投稿が前提としている環境では、次のパスが環境変数”Path”に登録されていることを前提としている。

DCS dcsw.exe C:\myapp\dcs1_10\windows
Make for Windows make.exe C:\Program Files (x86)\GnuWin32\bin
C++Builder Community Edition bcc32.exe
ilink32.exe
brcc32.exe
C:\Program Files (x86)\Embarcadero\Studio\20.0\bin

環境変数が適切に登録されていることを確認するため、PowerShellで次のコマンドを実行する。適切な環境であれば、それぞれのヘルプが出力される。

dcsw -h
make -h
bcc32 -h

フォルダ

この投稿では、ザナクロのソース・ファイルは、次のフォルダに収録されている。以後、このフォルダを「ソース・フォルダ」と呼ぶ。適宜、各々の環境に合わせたパスへ読みかえること。

D:\user temp\work\xanadu\src

文字コードの変換

ザナクロに収録されているファイルは、異なる文字コードで記述されたものが混在している。txtファイルはShift JISだが、ソースとヘッダー・ファイルはJISで記述されていた。そのため、ソースコードをエディタで参照する際、適切なエンコードが指定できなければ、特にコメントが文字化けしてしまう。例えばVSCodeでは、Shift JISを指定することはできるが、JISを指定することはできない。
次の3種類のファイルについて、文字コードをUTF8へ変換する。

  • txt
  • c
  • h

PowerShellで、次のスクリプト(dcs.ps1)を実行する。このスクリプトでは、次のことを実行している。

  1. xanadu”フォルダ配下の全ファイルを精査し、対象ファイルの一覧を取得する。
  2. 対象ファイルの一覧から一ファイルずつ、DCSを用いてUTF8へ変換する。

dcs.ps1

$src = "D:\user temp\work\xanadu"
$ext = @("*.txt", "*.c", "*.h")

function dcs($files){
  foreach ($i in $files){
    $from = '"' + $i.fullname + '"'
    $to = '"' + $i.fullname + '"'
    dcsw -d u8 -o $to $from
  }
}

foreach ($i in $ext){
  $files = get-childitem -path $src -recurse -include $i
  dcs($files)
}


”$from”が変換前のファイル、”$to”が変換後のファイルだ。このスクリプトでは、どちらも同一に設定している。つまり変換前のファイルが上書きされる。変換後のファイルを別に保存したければ、$toの値を書き換えればよい。

Makefileの編集

ソース・フォルダに”Makefile”が格納されている。ザナクロをビルドするには、このファイルを実行する必要がある。実行前に、その内容に目を通すと、いくつかのポイントを修正しておく必要があることに気付く。具体的には、

  • bcc実行オプションを変更する。
    • ”-wTE”→”-wT”
  • UNIXファイル・パスを、Windowsのものへ変更する。
    • ”/”→”\”
  • UNIXコマンドを、Windowsコマンドプロンプトのものへ変更する。
    • ”rm”→"del"
    • ※コマンド”make”から実行される都合上、PowerShellコマンドレットは指定できない。
  • アーカイブ用のターゲットを削除する
    • ”ARCHIVE_DIR = d:/home/archive”以下の行を削除する。
    • 再配布する意図はないので、アーカイブ、圧縮ファイルは不要。

Makefileの全文は、次のようになる。

Makefile

.autodepend
.cacheautodepend

CC	= bcc32
LINK	= ilink32
RCC	= brcc32

CFLAGS	= -5 -O2 -OS -c -tW -I..\include
LFLAGS	= -x -aa -Tpe

.c.obj:
	$(CC) $(CFLAGS) $<

.rc.res:
	$(RCC) -fo$@ $<

OBJS1	= main.obj graphics.obj image8.obj image16.obj image24.obj image32.obj
OBJS2	= audio.obj dungeon.obj goods.obj user.obj message.obj status.obj 
OBJS3	= context.obj field.obj tower.obj battle.obj boss.obj cave.obj
OBJS4	= equip.obj inventory.obj shop.obj user_dead.obj use_item.obj
OBJS5	= animation.obj menu.obj pause.obj opening.obj ending.obj
OBJS6	= numinous.obj user_io.obj fade.obj

OBJS	= $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) $(OBJS5) $(OBJS6)

STARTUP	= c0w32.obj
LIBS	= cw32mt.lib import32.lib
RES	= xanadu.res
TARGET	= xanadu.exe midiplay.exe waveplay.exe

all: $(TARGET)

xanadu.exe: $(OBJS) $(RES) xanadu.rsp
	$(LINK) @xanadu.rsp

xanadu.rsp: Makefile
	echo $(LFLAGS)+ > $@
	echo $(STARTUP) $(OBJS1)+ >> $@
	echo $(OBJS2)+ >> $@
	echo $(OBJS3)+ >> $@
	echo $(OBJS4)+ >> $@
	echo $(OBJS5)+ >> $@
	echo $(OBJS6)+ >> $@
	echo ,xanadu.exe,, $(LIBS),,$(RES) >> $@

midiplay.exe: midiplay.obj
	$(CC) -O2 -OS -WC -e$@ midiplay.obj cw32.lib import32.lib

waveplay.exe: waveplay.obj
	$(CC) -O2 -OS -WC -e$@ waveplay.obj cw32.lib import32.lib

clean:
	del *~ *.obj *.ilc *.ild *.ilf *.ils *.tds *.csm *."#"* *.res *.TR2
	del ..\include\*~

rebuild:
	del $(TARGET)
	make clean
	make all


リビルド

まだソースコードには何も変更を加えておらず、既にコンパイル済みのバイナリ・ファイルも存在しているため、まずリビルドを試す。PowerShellにて、ソース・フォルダをカレント・フォルダとし、次のコマンドのいずれかを実行する。

  • リビルド中の出力をログに記録する場合。

コマンド終了後、フォルダ””src中にlog.txtが出力される。

make rebuild > log.txt
  • リビルド中の出力を記録しない場合。
make rebuild

リビルド中に出力されるのは、多数の”Warning”だ。それらはすべて、次のいずれかに該当している。

  • 未参照の変数が定義されている。
  • sigined、unsigned(符号付き、符号なし)の比較

Comparing signed and unsigned values in function

開発者の意図が分からないため、このWarningを放置してもよいのか、訂正しなければならないのかは、Warningで指摘された行と、関連処理を精査する必要がある。
特に後者は、プログラム実行中に予期せぬエラーや、期待に添わない動作、結果を生じるリスクがある。気になる人はリビルド中の出力を手掛かりに、該当ファイルの該当業を参照し、ロジックを追跡して、必要ならばプログラムを手直しすることになるだろう。
この投稿では、まずコンパイルを通して実行ファイルを得ることを第一義としているため、その詳細には触れない。”Error”が出力されていないため、とりあえずの目的は果たせた。

実行

リビルドが終了すると、フォルダ”src”に”xanadu.exe”が出力される。これはWin32形式の実行ファイルなので、実行前にプロパティの設定を変更する。具体的には、Windows 98の互換モードで実行するよう、設定する。
f:id:espio999:20210711203940p:plain
"Windows XP (Service Pack 3)"までの動作を確認した。それ以降のバージョンでは、起動画面でのキー操作に反応しなかった。プログラムが記述された年代を考慮して、ここでは”Windows 98/Windows ME”を選択している。

記念撮影

XANADU
f:id:espio999:20210711204749p:plain
f:id:espio999:20210711204811p:plain
f:id:espio999:20210711204829p:plain
f:id:espio999:20210711204844p:plain

XANADU scenario II
f:id:espio999:20210711204859p:plain
f:id:espio999:20210711204913p:plain
f:id:espio999:20210711204926p:plain

読みやすく、改変しやすい環境へ

ソースコードは問題なくビルド、実行できることが分かった。より効率的に読みやすく、設定やパラメータを改変しやすい環境を用意したい。次回の投稿では、この環境をVisual Studioへ取り込むことにする。
その次に、ソースコードの全体像を把握しやすいよう、可視化ツールであるSourcetrailも導入する。
impsbl.hatenablog.jp
impsbl.hatenablog.jp

余談

XANADU』は過去数回、Windows向けに再版されている。現状では、いずれも高額で取引される部類の商品になってしまった。
また80年代に出版された関連書籍も、非常に高額で取引されている。