続・ファンタジーゾーンコンプリートコレクション update
長くなったので分割
お約束
抽出は全て自己責任でお願いします
手順などの不備がありましたら
お手数ですがコメントをいただけると幸いです
あらかたぶん投げてるので、補完のコメントも大歓迎です
こちらは後編になりますので
事前準備などは前編をご参照いただければ。
Fantasy Zone II – The Tears of Opa-Opa (System 16C)
現行のMAMEセット準拠への変換は
0.227からの追加分である
315-5298.b9が変換で不足すると思います。
0.225位までなら動作可能と思われます。
変換
テキストファイルにコピペでfantzn2x_convert.pyとして保存
下記ファイルを同一フォルダーに配置
fz2_s16c.p00
fz2_s16c.p01
fz2_s16c.spr
fz2_s16c.scr
fz2_s16c.snd
コマンドプロンプトからpython fantzn2x_convert.pyを実行
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pathlib import Path
# --------------------------------------------------
# HSP: #deffunc writedata str filename,int ofs,int size
# --------------------------------------------------
def writedata(filedat: bytes, filename: str, ofs: int, size: int):
buf2 = bytearray(size)
for i in range(size):
buf2[i] = filedat[i * 2 + ofs]
Path(filename).write_bytes(buf2)
def main():
# ==================================================
# CPU
# ==================================================
filedat = Path("fz2_s16c.p00").read_bytes()
filesize = len(filedat)
writedata(filedat, "fz2.a7", 0x000000, 0x20000)
writedata(filedat, "fz2.a5", 0x000001, 0x20000)
filedat = Path("fz2_s16c.p01").read_bytes()
filesize = len(filedat)
writedata(filedat, "fz2.a8", 0x000000, 0x20000)
writedata(filedat, "fz2.a6", 0x000001, 0x20000)
# ==================================================
# SPRITE
# ==================================================
filedat = Path("fz2_s16c.spr").read_bytes()
filesize = len(filedat)
writedata(filedat, "fz2.b1", 0x00001, 0x20000)
writedata(filedat, "fz2.b5", 0x00000, 0x20000)
writedata(filedat, "fz2.b2", 0x40001, 0x20000)
writedata(filedat, "fz2.b6", 0x40000, 0x20000)
writedata(filedat, "fz2.b3", 0x80001, 0x20000)
writedata(filedat, "fz2.b7", 0x80000, 0x20000)
writedata(filedat, "fz2.b4", 0xC0001, 0x20000)
writedata(filedat, "fz2.b8", 0xC0000, 0x20000)
writedata(filedat, "fz2.a1", 0x100001, 0x20000)
writedata(filedat, "fz2.b10", 0x100000, 0x20000)
writedata(filedat, "fz2.a2", 0x140001, 0x20000)
writedata(filedat, "fz2.b11", 0x140000, 0x20000)
# ==================================================
# BG
# ==================================================
filedat = Path("fz2_s16c.scr").read_bytes()
filesize = len(filedat)
if filesize % 4 != 0:
raise ValueError("fz2_s16c.scr のサイズが4の倍数ではありません")
word_count = filesize // 4
outbuf = [
bytearray(word_count),
bytearray(word_count),
bytearray(word_count),
]
for i in range(word_count):
ofs1 = i * 4
ofs2 = i
tmp = 0
for j in range(4):
tmp = (tmp << 8) | filedat[ofs1 + j]
bytebuf = [0, 0, 0]
for bit in range(8):
tmp2 = (tmp & (0x70000000 >> (bit * 4))) >> (28 - bit * 4)
mask = 0x80 >> bit
if (tmp2 & 0x01) != 0:
bytebuf[0] |= mask
if (tmp2 & 0x02) != 0:
bytebuf[1] |= mask
if (tmp2 & 0x04) != 0:
bytebuf[2] |= mask
for p in range(3):
outbuf[p][ofs2] = bytebuf[p]
Path("fz2.a14").write_bytes(outbuf[0])
Path("fz2.a15").write_bytes(outbuf[1])
Path("fz2.a16").write_bytes(outbuf[2])
# ==================================================
# SOUND
# ==================================================
filedat = Path("fz2_s16c.snd").read_bytes()
filesize = len(filedat)
# fz2.a10 : 開始 0x00000 / サイズ 0x8000
Path("fz2.a10").write_bytes(filedat[0x00000:0x00000 + 0x8000])
# fz2.a11 : 開始 0x10000 / サイズ 0x10000
Path("fz2.a11").write_bytes(filedat[0x10000:0x10000 + 0x10000])
print("Conversion completed successfully.")
if __name__ == "__main__":
main()
旧変換
#packopt name "fantzn2x"
#module
#deffunc writedata str filename,int ofs,int size
sdim buf2,size
repeat size : poke buf2,cnt,peek(filedat@,cnt*2+ofs) : loop
bsave ""+filename,buf2,size
return
#global
;//cpu
notesel filedat
noteload "fz2_s16c.p00" : filesize = strsize
writedata "fz2.a7", $000000, $20000
writedata "fz2.a5", $000001, $20000
noteload "fz2_s16c.p01" : filesize = strsize
writedata "fz2.a8", $000000, $20000
writedata "fz2.a6", $000001, $20000
;//sprite
noteload "fz2_s16c.spr" : filesize = strsize
writedata "fz2.b1", $00001, $20000
writedata "fz2.b5", $00000, $20000
writedata "fz2.b2", $40001, $20000
writedata "fz2.b6", $40000, $20000
writedata "fz2.b3", $80001, $20000
writedata "fz2.b7", $80000, $20000
writedata "fz2.b4", $c0001, $20000
writedata "fz2.b8", $c0000, $20000
writedata "fz2.a1", $100001, $20000
writedata "fz2.b10", $100000, $20000
writedata "fz2.a2", $140001, $20000
writedata "fz2.b11", $140000, $20000
;//bg
noteload "fz2_s16c.scr" : filesize = strsize
sdim outbuf,filesize/4,3
repeat filesize/4
ofs1 = cnt*4 : ofs2 = cnt
tmp = 0 : repeat 4 : tmp = (tmp<<8)|peek(filedat,ofs1+cnt) : loop
dim bytebuf,3
repeat 8
tmp2 = tmp&($70000000>>(cnt*4)) : tmp2 = tmp2>>(28-cnt*4) ;特定位置の4bitを取り出す
tmp3 = $80>>cnt
if (tmp2&1)!0 : bytebuf.0 = bytebuf.0 | tmp3
if (tmp2&2)!0 : bytebuf.1 = bytebuf.1 | tmp3
if (tmp2&4)!0 : bytebuf.2 = bytebuf.2 | tmp3
loop
repeat 3 : poke outbuf.cnt,ofs2,bytebuf.cnt : loop
loop
bsave "fz2.a14", outbuf.0, filesize/4
bsave "fz2.a15", outbuf.1, filesize/4
bsave "fz2.a16", outbuf.2, filesize/4
;//sound
;// noteload "fz2_s16c.snd" : filesize = strsize
;// writedata "fz2.a10", $00000, $8000
;// writedata "fz2.a11", $10000, $20000
endHSP3.1用です。エディターを開いて、実行ファイル自動作成を選ぶと
fantzn2x.exeができあがるので、アンパックしたBINフォルダーで実行。
サウンドROMの切り出しは、HSPで上手く書けないので
Romcutterを用いて分割しました。
Romcutterは上記のはむさんのサイトからダウンロード出来ます。
HSPに通じている方なら、ファイルから切り出すように書けば一発変換可能です。
romcutter fz2_s16c.snd fz2.a10 0 8000
romcutter fz2_s16c.snd fz2.a11 10000 20000全てのファイルを生成したら
fantzn2x.zipとして保存すれば作業は完了です。
FinalBurnNeoはoptionalで315-5298.b9が不要なので監査OKです。
繰り返しますが、MAMEは0.225までになります。
実機動作の話
Fantasy Zone IIの実機動作は
上記のサイトで検証されていました。
どうやらSYSTEM16Bにメモリを増設し
SYSTEM16Cに改造すると動作するようです。
メモリ増設の経緯は
Fantasy Zone (Time Attack, bootleg)
Python版
必要ファイル
fz1_s16b_ta.p00
fz1_s16b_ta.obj
fz1_s16b.scr
fz1_s16b.snd
同一フォルダーに配置して実行でおk(のはず)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pathlib import Path
# --------------------------------------------------
# HSP: #deffunc writedata str filename,int ofs,int size
# --------------------------------------------------
def writedata(filedat: bytes, filename: str, ofs: int, size: int):
buf2 = bytearray(size)
for i in range(size):
buf2[i] = filedat[i * 2 + ofs]
Path(filename).write_bytes(buf2)
def main():
# ==================================================
# CPU
# ==================================================
filedat = Path("fz1_s16b_ta.p00").read_bytes()
filesize = len(filedat)
writedata(filedat, "fzta__a07.bin", 0x000000, 0x20000)
writedata(filedat, "fzta__a05.bin", 0x000001, 0x20000)
# ==================================================
# SPRITE
# ==================================================
filedat = Path("fz1_s16b_ta.obj").read_bytes()
filesize = len(filedat)
writedata(filedat, "fzta__b01.bin", 0x00001, 0x20000)
writedata(filedat, "fzta__b05.bin", 0x00000, 0x20000)
writedata(filedat, "fzta__a01.bin", 0x100001, 0x20000)
writedata(filedat, "fzta__b10.bin", 0x100000, 0x20000)
# ==================================================
# BG
# ==================================================
filedat = Path("fz1_s16b.scr").read_bytes()
filesize = len(filedat)
if filesize % 4 != 0:
raise ValueError("fz1_s16b.scr のサイズが4の倍数ではありません")
word_count = filesize // 4
outbuf = [
bytearray(word_count),
bytearray(word_count),
bytearray(word_count),
]
for i in range(word_count):
ofs1 = i * 4
ofs2 = i
# 4バイト → 32bit(ビッグエンディアン)
tmp = 0
for j in range(4):
tmp = (tmp << 8) | filedat[ofs1 + j]
bytebuf = [0, 0, 0]
for bit in range(8):
tmp2 = (tmp & (0x70000000 >> (bit * 4))) >> (28 - bit * 4)
mask = 0x80 >> bit
if (tmp2 & 0x01) != 0:
bytebuf[0] |= mask
if (tmp2 & 0x02) != 0:
bytebuf[1] |= mask
if (tmp2 & 0x04) != 0:
bytebuf[2] |= mask
for p in range(3):
outbuf[p][ofs2] = bytebuf[p]
Path("fzta__a14.bin").write_bytes(outbuf[0])
Path("fzta__a15.bin").write_bytes(outbuf[1])
Path("fzta__a16.bin").write_bytes(outbuf[2])
# ==================================================
# SOUND
# ==================================================
filedat = Path("fz1_s16b.snd").read_bytes()
filesize = len(filedat)
# 開始アドレス 0x00000 から 0x8000 バイト切り出し
Path("fzta__a10.bin").write_bytes(filedat[0x00000:0x00000 + 0x8000])
print("Conversion completed successfully.")
if __name__ == "__main__":
main()
旧版
Fantasy Zone (Time Attack, bootleg)で変換可能でした。
MAMEのROMSET準拠変換は
HSPスクリプトと(自分のスキル不足で)Romcutter併用です
HSPを書ける人はfz1_s16b.sndの先頭32kbを切り出すようにすればOK
#packopt name "fantzoneta"
#module
#deffunc writedata str filename,int ofs,int size
sdim buf2,size
repeat size : poke buf2,cnt,peek(filedat@,cnt*2+ofs) : loop
bsave ""+filename,buf2,size
return
#global
;//cpu
notesel filedat
noteload "fz1_s16b_ta.p00" : filesize = strsize
writedata "fzta__a07.bin", $000000, $20000
writedata "fzta__a05.bin", $000001, $20000
;//sprite
noteload "fz1_s16b_ta.obj" : filesize = strsize
writedata "fzta__b01.bin", $00001, $20000
writedata "fzta__b05.bin", $00000, $20000
writedata "fzta__a01.bin", $100001, $20000
writedata "fzta__b10.bin", $100000, $20000
;//bg
noteload "fz1_s16b.scr" : filesize = strsize
sdim outbuf,filesize/4,3
repeat filesize/4
ofs1 = cnt*4 : ofs2 = cnt
tmp = 0 : repeat 4 : tmp = (tmp<<8)|peek(filedat,ofs1+cnt) : loop
dim bytebuf,3
repeat 8
tmp2 = tmp&($70000000>>(cnt*4)) : tmp2 = tmp2>>(28-cnt*4) ;特定位置の4bitを取り出す
tmp3 = $80>>cnt
if (tmp2&1)!0 : bytebuf.0 = bytebuf.0 | tmp3
if (tmp2&2)!0 : bytebuf.1 = bytebuf.1 | tmp3
if (tmp2&4)!0 : bytebuf.2 = bytebuf.2 | tmp3
loop
repeat 3 : poke outbuf.cnt,ofs2,bytebuf.cnt : loop
loop
bsave "fzta__a14.bin", outbuf.0, filesize/4
bsave "fzta__a15.bin", outbuf.1, filesize/4
bsave "fzta__a16.bin", outbuf.2, filesize/4
;//sound
;// noteload "fz1_s16b.snd" : filesize = strsize
;// writedata "fzta__a10.bin", $000000, $8000
end上記でfzta__a10.bin以外を抽出可能です。
コメントアウトしてるコマンドではODD/EVENになってしまって
そのまま32kb切り出しがうまく行きませんでした・・・
HSPの自動実行ファイル生成を選ぶとfantzoneta.exeになりますので
BINフォルダーにコピーして実行するとファイルが変換されます。
romcutter fz1_s16b.snd fzta__a10.bin 0 8000これでfzta__a10.binもCRC一致します
バイナリカット出来るソフトなら何でもOKです。

これで変換されたファイル全てをまとめて
ZIPにしたのちfantzoneta.zipにリネームします
MAMEベースなら監査は通過出来ました。
Arcade 0.251.0で確認済です。
Fantasy Zone (PS2) for HBMAME
HBMAMEではPS2版のファンタジーゾーンとして
ROMを読み込むドライバーが実装されていました。
タイムアタック版とプログラム以外は同一になっているようです
タイムアタック版の変換にあわせ
fz1_s16b_p00をODD/EVENで2分割すればOk
.a5がCRC:2e131b1dで.a7が8c6fe14dです。
差分はプログラムだけですから
HSPに下記を追記してあげればOKです。
;//cpu
notesel filedat noteload "fz1_s16b.p00" : filesize = strsize
writedata "fz1_s16b_p00.a07", $000000, $20000
writedata "fz1_s16b_p00.a05", $000001, $20000もしくは、はむさんのROM masqueradeを使って
EVEN/ODDでそれぞれ手動でSaveDumpする方法もあります。
fantzone01.zipとしてタイムアタック版の必要分も入れてZIP圧縮すれば完了です。
コインを複数入れるとsの色がおかしいですね。
実機だとパッチ(消滅済)を当てないと最終面で問題が起きるようです。(海外フォーラムより)
〆
追記していったら、可読性がダダ下がったので分割しました
これで現状できる範囲の変換は完了したとおもいます。
記述ミスや修正などありましたら
たいへんお手数ですがコメントまでお願いします。
HSPで単純バイナリカットができれば一発変換できますが・・・
自分は3.1をいまさら弄る気力がないので楽に走りました(スミマセン
しかしファンタジーゾーンやってると
STGってこれくらい素朴な方がホッとするなぁ・・・(下手くそ)





























ディスカッション
コメント一覧
ファンタジーゾーン2の抽出ができるのは嬉しいですね。
早速実行し、Retroarch上のMAME2016で動作する事を確認しました。
自分は[PS2] SEGA AGES 2500 テトリスコレクション からの抽出をしてみました。
PGMは”発明の友”さん作成のものを利用させてもらいました。
http://blog.livedoor.jp/scrap_a/archives/23162697.html
ASP_cache2rom_v2.zip
【テトリス】=================================
bcut.exe tetris_e.bin epr12213.7 0 0x8000
bcut.exe tetris_e.bin epr12212.5 0x8000 0x8000
bcut.exe tetris_e.bin epr12211.4 0x10000 0x8000
echo 抽出されたファイルを”tetrisse.zip”としてまとめる
pause
===================================
【ブロクシード】=================================
bcut.exe bsc.bin bsc.bin.temp1 0 0x40000
bcut.exe bsc.bin bsc.bin.temp2 0x40000 0x40000
BSwap.exe d B bsc.bin.temp1 oddeven.txt epr12908.32 epr12907.31
BSwap.exe d B bsc.bin.temp2 oddeven.txt epr12993.34 epr12992.33
del bsc.bin.temp1
del bsc.bin.temp2
echo 抽出されたファイルを”bloxeedc.zip”としてまとめる
pause
===================================
Jackさんこんにちは!コメントありがとうございます。
直接リンクはお行儀がよろしくないので
記事ページに書き換えさせていただきました。
テトリスコレクションからも抽出できるのですね~感謝です!
テトリス系はふと遊びたくなるので抽出可能なら購入しようかなぁ
(プレミアも付いてませんし)
SYSTEM16Bのゲームをもう一つ追加することは可能でしょうか?
ありがとう。
Romarioさんコメントありがとうございます。
”system16bのゲームをもう一つ追加する”
別製品のPS2版SDIやPS2版のモンスターレアなどを抽出可能か?というご質問でしょうか?
それともファンタジーゾーンコレクションから16Bタイトルを他に抽出できるか?という質問でしょうか?
もうしわけないのですが、質問の意図がわからないので回答できません。
申し訳ありませんが、正しい質問をしませんでした。
たとえば、ファンタジーゾーンを忍のような別のゲームと交換することは可能かどうか知りたいです。
.scr ファイルの作成方法。
ありがとう
コメントありがとうございます
scrの作成でsystem16bを入れ替えて動作可能かというお話ですね
すみませんが私は技術力がないので、記載されたコードを再利用しているにすぎません。
ただHSPスクリプトでbg抽出のコードを逆転させれば、SCRを作ることは可能だと思います
それでも非プロテクトのタイトルでないと(おそらく)うまく動作しないでしょう
さらにPS2がファイルを読み込んでくれるかわからないので、難しいかもしれません。
お力になれず申し訳ありません
どうもありがとうございます。
とても有用な記事をありがとうございます。おかげでシステム16版ファンタジーゾーン2作4バージョンの抽出が出来ました。
ただし、記事内のプログラムにミスがあり、修正をしないと正常な抽出が出来ない状態です。自分でプログラムに修正を行って使用しました。修正版ソースコードの提供も可能ですが、いかがでしょうか?
ファンタジーゾーンII(システム16C)について、
・CPUファイルに関して、fz2.a7とfz2.a5、fz2.a8とfz2.a6がそれぞれ逆のファイル名になっています。データベースに記載のオフセットと逆の奇遇関係となっているようです。プログラム内での保存先を入れ替えるか、抽出後にリネームで入れ替えるを行うことで解決します。
・スプライトファイルに関して、プログラムで指定されているfz2_s16c.sprからでは抽出が出来ませんでした。全てのスプライトファイルがCRC不一致でした。抽出元ファイルをfz2_s16c.objに変更すると、抽出に成功しました。
・・sprファイルとobjファイルの内容は同じのようですが、バイトの並び方が異なります。
・プログラム内のwritedata命令は、プログラムの3~8行目で定義されたユーザー定義関数です。奇数/偶数単位での抽出しかすることが出来ない為、サウンドロムなどの抽出に失敗するようです。
・・私はバイトスキップを伴わない切り出しに対応した関数を定義して使用しました。romcutterで行う処理と同等かと思われます。
ファンタジーゾーンIのタイムアタックバージョンに関しても、CPUファイルの保存先が入れ替わっていたため、プログラムの修正かリネームが必要になりました。fzta__a07.binとfzta__a05.binが逆になっています。
また、ファンタジーゾーンIIの不足ファイルである315-5298.b9に関しても、CRC書き換えを応用してダミーファイルを作成し、現行バージョンのMAMEでの動作が出来ることを確認しました。警告は表示されます。
degharlさんコメントありがとうございます
改良されたコードを投稿いただけるなら大歓迎です!
ボケ倒して間違えまくってたようなので、お手数をおかけいたしました;
MAMEでも警告ありで動作できているとのことで情報ありがとうございます!