dnjiro’s 9VAe blog

誰でもアニメが作れる無料ソフト9VAeきゅうべえ開発者のブログ

9VAeきゅうべえの X68000 Z への移植

9VAeきゅうべえは、下のようなアニメが作れる無料のモーショングラフィックスアプリです。その開発の原点が伝説のマシン X68000 で、X68000 Z はその復刻版です。Z68000 Z は X68000 初期型を忠実に再現しており、1.2MB のフロッピーディスク2枚しか使えなかったのですが、数ヶ月で 1GB のハードディスクイメージが使える無料アップデート(Ver1.3.1)が行われたため、数10MBある 9VAeが移植できる可能性がでてきました。今は 64bitアプリになった9VAeを、16bitマシンの X68000 Z 実機に移植できるのか、苦労した点を紹介します。

GCCを使ってるが、リンクエラーがなくならない、実行するとエラーが出るといった方には参考になるかも。

MicroPython開発ディスクの作り方X68000 Z 実機開発の仕方はこちら

9VAeプロジェクトの構造

9VAeきゅうべえのプロジェクトは、多くの機種に移植するために、以下の構造になっています。

  1. 機種依存のない C プログラム (9VAeエンジン) 95%
  2. OSに依存したプログラム、描画、文字入力、ダイアログなど・・ 5%
  3. ユーザーインタフェース画像(PNG1枚)
  • 1. を GCCコンパイルし、2. を X68K用関数に置き換えると移植完了になります。
  • 最近のアプリは、OSごとに、ボタンや画面表示部品が用意されており、OSごとに違う部品プログラムを用意するのケースが多いのですが、9VAeは、ボタンやメニューのUIパーツは共通コード1. で自力で作成しており、描画関数とわずかな入力関数を作れば移植できます。Cの共通部分が大きいのが9VAeの特徴です。
  • 2.は、iOS / Android / Windows / Linux / Mac / Amazon Fire 用があります。それぞれの完成度があがるまで、かなり時間がかかりました。今回、X68000版を作成しようというわけです。

X68000 Z の開発環境整備、苦労した点

  • 9VAeは C++ のコメントである // を多用しており、XC ではエラーになるので使えません。GCC(真理子版)は、// が使えるオプションがあります。
  • X68K は最初は XCコンパイラが標準で、GCC はそれを置き換える(最初は XCのライブラリ、インクルードファイルを使う)形で開発されたようです。その後本家の ANSI ライブラリが提供され、X68030 への対応など、バージョンアップも行われたようで、どのライブラリを使えば、どの GCCが動くのかわかりにくいです。これなら動くという完全なセットがあるとよいのですが・・わかりません。
  • ビルドには make.x makefile が必須です。make clean には、rm.x が使われるみたいですが、うまくいかず、del /Y * を使ってます。
  • インクルードファイルが見つからないエラーがぽんぽん出ました。XCのインクルードが古いせいでしょう。X68KANSIライブラリから、足らないファイルだけコピーし、エラーが出なくなるように修正しました。
  • こうすると、古いファイルの中に新しいインクルードが混ざって、やばい状態になりますが、XCと GCC を差し替て動くことを優先します。そうないと、実行時にバスエラーがでたとき、GCCのエラーなのか、ソースのエラーなのか、ライブラリのエラーなのかわかりません。本番はGCCを使いますが、不明なエラーがでたときに、XC でテストプログラムを作成し、原因を調べます。
  • たとえば、GCC では、doscall.equ がないエラーが出ました。x68kの開発環境からこのファイルを追加しましたが、実行するとバスエラー。XCではエラーが出ないので比較した結果、doscall.mac を複製して doscall.equ にリネームしたらバスエラーが出なくなりました。
  • スタックが足らないというエラーが出ました。GCCオプションでスタックを追加するとビルドできるようになりました。ほんとに動くのか・・
  • 変数未定義などのエラーは、コメントアウトするとか、仮の値を定義して、とにかくビルドを通します。

zlib関数

  • png の読み書きプログラムから、zlib の関数(InflateResetなど)がないと言われました。最近の環境では、zlib の基本関数が基本ライブラリに組み込まれていて、x68k にはそれがないようです。zlib のソースコードからその関数のソースコードを入手していれました。zlib は、ソースコードを公開しなければ(自分で行った改造を世の中に広めなければ)利用してもよいというライセンスです。

MicroEmacs

  • MicroEmacs は、Undo ができない、fgrep ができないという欠点がありますが、サイズが大きいソースコードでも、高速に編集できるのでつかってます。
  • lanma.x 開発当時は、XVI で、mule を動かしていたような気がするのですが、入手できていません。mule は遅いので、MicroEmacsを使っているという記事もありました。

shell バッファとmakefile、日付、時間設定

  • X68000 Z では、MicroEmacs の shell バッファ(Shift+F10)の中で、make を実行すれば、エラー表示から、tag-jump (Shift+F8)してエラー箇所が読み出せます。
  • ただ、shell バッファの1行に限りがあるため、ファイルをリンクするときに、全部のファイル名を記述できません。リンクする .o ファイルリストをテキストに保存しておき、それを読み出してリンクするという方法をとりました。
  • X68000 Zで 9VAe プロジェクトを全部ビルドするのに半日くらいかかります。
  • 一度作成した .o は、2重に作成しないように、日付、時間をソースコードと比較します。そのためには、X68000 Z の時計が正しい時刻になっている必要があります。電源ON/OFF したときは、DATE.x, TIME.x で日付、時刻を設定する必要があります。最初それを忘れていたので、Unix ツールの touch.x で、.o ファイルの時刻を最新に修正しました。
  • 今は、autoexec.bat の最後に「date」といれて、起動時に日付入力(そのあと「time」で時刻入力)するようにしてます。お勧めです。

 

マウスイベント、描画の動作確認

  • ビルドエラーがなくなったら、とりあえず実行してみます。バスエラーがでました。ここからデバッグ開始。
  • 最初に実行する関数は、main() という関数です。その直後に printf("1¥n"); return; を入れて実行するとエラーなく、「1」と表示して終了しました。¥n は改行で、これをいれておかないと、shell バッファに文字がでてきません。文字表示できれば、ひとまず安心。
  • つぎに、マウス座標の取得をいれます。これは、lanma.x のソースからコピーしました。実行するとバスエラーが出ました。
  • ここで、GCCで、マウス関数のビルド、リンクが正しいかどうか検証します。マウス座標入力だけのテスト関数を作成して、ビルド、実行するとバスエラーが出ました。
  • C コンパイラーを、XCに変更して実行すると正常に動きました。ここで、アセンブラ、リンカーを同じにしているので、GCCだけを疑います。GCCで作成したアセンブラと、XCで作成したアセンブラを比較し、GCCの場合は、doscall.equ をインクルードしていました。これは未定義だったので、ほかの開発環境から取得したものです。
  • doscall.equ の中身をみてみると、中で、doscall.mac をインクルードしていたので、XC用のライブラリを使うことにして、doscall.mac と同じ内容のファイルにしました。これで、正常に動くようになりました。doscall.equ は、バージョンの高いライブラリにしないと正常に動作しないものと思われます。
  • 当面、X68K の描画を動かさないといけないので、XC で動作するライブラリを使います。
  • 次に lanma.x でキー入力に使っていた INPOUT 関数のアセンブラで「illegal relative」エラーがでました。相対ジャンプができないエラーと思い、すべて絶対ジャンプにする「-fall-jsr」オプションをつけるとGCCで「不正なオプション」がでて使えません。全部相対にする「-fall-bsr」はOK。なんでだろう
  • 仕方がないので、X-BASIC で、時間待ちなし入力(inkey$(0))を使ったBASICを作成し、BASICからCにコンパイル。すると、INPOUTでなく、 b_inkey0() が作成されました。開始はb_init(), 終了には b_exit(0) が挿入されました。これを使うとバスエラーはなくなりました。lanma.x では ANSI の新しいライブラリを使っていたと思われます。今回は、そのライブラリセットがわからないので、X-BASICでも動くライブラリを使います。
  • キー入力で終了できるようになったので、マウスイベント取得を作ります。

 

移植の順番

  • 移植を行うときの鉄則は、階段をのぼるように、1歩1歩移植していくことです。一度に、多くの機能を実装すると、それが動作しないとき、何が原因かわかりません。
  • 見た目のエラーがわかりやすいので、まず画面表示を作成し、そのあと、マウスイベント、メニュー表示をつくっていきます。
  • 9VAeには、マウスイベントをファイルに記録し、それを読み出しながら、動作を再現する機能を組み込んでいます。これが動くようになれば、エラー動作を再現できるようになり、移植速度が早まります。

 

PNG, グラフィック処理

  • 9VAeのユーザーインタフェースは1枚のPNG画像から矩形コピーで作成しています。PNGの読み書きは普通、OSの処理を使うのですが、今回は、9VAeに内蔵しているソースをつかいます。
  • X68000 当時は、PNGフォーマットがなく、JPEGができたころだったと思います。画像を高速に読み出すフォーマットがいろいろ開発されました。ということは、PNGがどれだけの速度で動くのか不安・・動きましたが遅いです。
  • PNGは1行単位でデータが作成されます。1行をいかに高速に X68000に転送できるかが鍵になりそう。
  • SCSIディスクから動画再生する方法(Zclubログイン必要)がすごい。これをつかうのがよさそう(作者tantan)。プレーヤー(RAWMVP.x)連番動画からGVRAM作成。256x200, 27.729fpsで連番出力し、RAWMVPで再生できるのを目標にしよう

heapサイズ

  • 実行すると、mallocPNGを展開するメモリの取得ができませんでした。
  • ヒープサイズを大きくするには、-z-heap=3000000 とすればよいのですが、これは使うには、1. リンカーを gcc にする。2. HLK.x を lk.x にリネームする。が必要みたいです。GCCから、HLKを起動してヒープサイズが拡張できるみたいです。ただ、GCC から直接実行ファイルを作らなければ、-z-heap オプションが効きません。
  • 今回複数の .o をたくさん作っており、GCC から直接実行ファイルができません。
  • そのため、AR.X を使って複数の.o をライブラリにまとめ、最後に、main 関数のあるファイル1個だけ、gcc で実行形までビルドすれようにすれば、heapサイズを拡張できました。デフォルトの100倍のサイズを与えています。

グラフィック処理の調査

  • X-BASICでは、get(x1,y1,x2,y2,mm) でメモリに画像を取得でき、put(x1,y1,x2,y2,mm) で画像の書き込みができます。この仕組みで画像を記憶することにして、ユーザーインタフェースのPNG画像をこの展開し、画面に描画するプログラムを作りました。
  • PNG画像を展開し、1次元配列にデータをいれて、x-basicの put 関数で画面に表示するところまでは動作しました。これでユーザーインタフェース画面まではできるはず。
  • グラフィックスは、512x512x256色x2面モードをつかいます。アニメ再生時には裏画面に描画して、描画完了したら表示を切り替えるという方法を目標にします。
  • 512x512x256色x2面モードでは1ドットの画面比率が4:3で、1:1ではありません。UI画面のPNG画像は水平方向に3/4にし、それにあわせて座標も3/4にすると、画面ボタンが正しく表示されました。ピクセルを正方形にするCRTMOD16.X (M.Kamada氏)というのもあるらしいです。

マウスイベントの搭載

  • ボタン表示ができたので、マウスイベントを搭載。ボタン表示が変化するか調べます。画面の左側の動作は正常に動作。右端の図形パレット、文字パレットの切り替えがおかしかったのでデバッグしてから、線の描画に移ります。

MicroEMACS用 fgrep.el

  • プロジェクトが複数ファイルにわかれていると、関数がどこで定義されているか、使われているか、検索する fgrep と、そのリストからソースを読み出す tag-jump の機能が欲しくなります。MicroEMACSにその機能がなかったので作りました。

 

  • 導入方法
  1. grep.x をベクターからダウンロードして、BIN フォルダにいれます。
  2. 以下のプログラムを、MicroEMACSのフォルダ( a:¥emacs など)に fgrep.el という名前で保存します。文字コードはShiftJIS。
  3. emacs.rc の最後に「execute-file "a:¥emacs¥fgrep.el"」を追加します。パスは保存先に応じて変更してください。
;------------------------------------------------------------
;	fgrep.el	for microEmacs
;	@dnjiro dnjiro.hatenablog.com/entry/x68000z
;	You need grep.x vector.co.jp soft x68 util
;------------------------------------------------------------

store-procedure fgrep

	set $discmd FALSE
	!if &seq %fgrep-file "ERROR"
		set %fgrep-file "*.*"
	!else
		!force copy-word
	!endif
	set %fgrep-find $kill
		
	set $temp &cat &cat "search [" %fgrep-find "]: "
	!force set %%pattern @$temp
	!if &not $status
		!goto abort
	!endif
	!if &equ &len %%pattern 0
		!if &equ &len %fgrep-find 0
			write-message "[中止]"
			!goto end
		!endif
		set %%pattern %fgrep-find
	!endif
	set %fgrep-find %%pattern

	set $temp &cat &cat &cat &cat "file " $current-dir "[" %fgrep-file "]: "
	!force set %%file @$temp
	!if &not $status
		!goto abort
	!endif
	!if &equ &len %%file 0
		set %%file %fgrep-file
	!else
		set %fgrep-file %%file
	!endif

	set %cmdline &cat &cat "dir " $current-dir %fgrep-file
	set %search-buffer "*console*"
	search-buffer
	!force wcom %cmdline

	beginning-of-line
	insert-string &cat "¥" %fgrep-file
	search-reverse "¥"
	forward-character
	kill-to-end-of-line
	beginning-of-line
	delete-next-character
	set-mark
	end-of-line
	kill-region
	set %fgrep-dir $kill
	insert-string " "
*loop
	search-reverse "ファイル使用量"
	!while &not &equ $curchar 32
		beginning-of-line
		next-line
		!if &equ $curchar 32
			!goto exit
		!endif
		!if &not &equ $curchar 42
			!goto next
		!endif
	!endwhile
*next
	set-mark
	search-forward " "
	backward-character
	copy-region
	set %fnam1 $kill
	next-word
	copy-word
	set %fname &cat &cat %fnam1 "." $kill
	beginning-of-line
	insert-string "*"
	set %cmdline &cat &cat &cat &cat "grep -n -i " %fgrep-find " " %fgrep-dir %fname

	end-of-file
	insert-string "*"

	!if &seq $kill "dir"
		!goto loop
	!endif
	!force wcom %cmdline
	set %cmdline &cat &cat &cat %fgrep-dir %fname ":"

	beginning-of-line
	!while &not &equ $curchar 42
		!if &equ $curchar 10
			!goto loop
		!endif
		!if &not &equ $curchar 32
			insert-string %cmdline
		!endif
		previous-line
		beginning-of-line
	!endwhile
	!goto loop
*exit
	beginning-of-line
	insert-string &cat &cat &cat &cat "-- fgrep " %fgrep-find " " $current-dir %fgrep-file
	end-of-file
	previous-line
	beginning-of-line
	!while &not &equ $curchar 45 ;-
		!if &equ $curchar 42 ;*
			delete-next-character
		!endif
		!if &equ $curchar 32
			delete-next-character
		!endif
		!if &equ $curchar 10
			delete-next-character
		!endif
		previous-line
		beginning-of-line
	!endwhile
	!goto end
*abort
	write-message "[中止]"
*end
	set $discmd TRUE
!endm
  • 使い方
  1. ESC x fg TAB で、fgrep を実行します。
  2. 検索する単語を入力します。なにも入力せずに Enter すると、カーソル位置の単語が検索できます。大文字小文字を区別しません。
  3. 検索するファイルを「*.c」「el¥*.el」のように入力します。検索結果が表示されます。
  4. 検索された行で Shift F8 (tag-jump) で、そこを表示できます。

*.el でフォルダの中の EMACS Lisp が検索できます。この fgrep.el も、MicroEMACS Lisp から似た処理を検索して作成しました。

 

ラバーバンド、ポップアップメニューの描画

  • ボタン描画ができたので、つぎはラバーバンドを移植します。図形を選択するときの線の描画で、マウスの移動によって書いたり消したりしないといけません。それを X68000 Z で高速に行うには図形画面とラバー画面は別画面とし、2画面合成表示(vpage(3))を使うのがよさそうです。これで、マウスイベントが正常動作していることがわかりました。
  • ポップアップメニュー、カラーパレットも同じ方法がつかえそうです。vpage(3)では画面0が最前面になることがわかったので、apage(1)で通常の描画を画面1に行い、ポップアップメニューやラバーバンドは、apage(0)で画面0に描画、消去することにしました。

カラーパレット、クリッピング、ポリゴン塗りつぶし、太い線

  • X68K描画関数には多角形塗りつぶしがないため、自力描画する必要があります。グラデーション塗りつぶしの自作ルーチンをいれました。
  • X68K描画関数のクリッピングエリアはwindow(x1,y1,x2,y2)で設定しました。ただ、線の描画のクリッピングが不正確で、太い線にクリッピングがかかると太線の間にすきまができました・・
  • 256色2面をつかうとき、カラーパレットは、R3G3B2ビットの色を設定しました。

メニューバー

  • 「ファイル開く」など、メニューバーは、下のファンクションキーを使いました。key(番号,"ラベル")でファンクションキーを設定できます。ラベルの最後に「  @X」のようにコントロールコードを入れ、それを検出してプルダウンメニューを表示しました。
  • メニューバーが動作すると、ヘルプメニューからサンプルデータの読み出しが可能になります。データ読み出しは、fopen をつかっており、すぐ動作しました。サンプルの、わらえもん、さけび、など、単純なものはOK。グラデーション塗りつぶしをつかったものは、読み込めるがハングアップ。画像をつかったリミックスはバスエラーが出ました。これをデバッグします。
  • デバッグの方法としては、読み込みプログラムを修正し一部の図形を読まない様にしてエラーがなくなるか調べます。文字でエラーが起こっていることがわかりました。

ダイアログ

  • Yes/Noダイアログなどの部品は用意されていないので、自力で描画します。ダイアログは apage(0) で画面0に描画し、vpage(3)で画面0、画面1を合成表示します。
  • b_inkeyS()で、Yキー、Nキーなどのキー入力待ちすることにしました。

 

ファイル

  • ファイル開く、保存のダイアログをどうするか、FILES, NFILES という dos関数をつかうと、カレントフォルダの中のファイルを取得できるみたいです。「illegal relative error」が出た場合、include¥doscall.equ の FILES, NFILES の行頭の「_」を削除すればよいです。
  • X68000の場合はコマンドプロンプトから起動するのでフォルダ表示はなしで進めると、ファイルの保存、読み出しまで動作しました。

 

tantan RAWMVP

  • tantan RAWMVP は、SCSIハードディスクの動画データを X68000 Z で再生するプレーヤーです。
  • 連番PNGから動画を作成するツールも公開されてます。グラフィック画面を単純に保存するだけなので、画面作成したあと、get で取得して保存。
  • フレーム画像は、256x256, 384x256、512x256 の3種類。横256画像は、2フレームを左右に繋げて512x256の画像にする、横384画像は、右側にパディングして横512にする必要があります。9VAeは 512x256 10(9.243)fps にします。
  • ファイルは2GBが最大なので、256x256なら約16000フレーム、384x256/512x256の場合約8000フレームが上限。5-10分程度のアニメがつくれます。
  • エディタが256色モードで動作しているので、まず256色で出力し、get で画像を取得してから、R5G5B50 の16bitカラーに変換してからRAWデータを出力します。
  • 再生は、rawmvp 512 256 20 <raw-movie-file> <adpcm-file>

内容:


解説動画の作り方

この記事のひとコマ解説GIFは、フリーソフト9VAeきゅうべえの「ひとコマ機能」で作成しています。

9VAeきゅうべえのダウンロード


音声で解説した動画

  • 9VAeきゅうべえで、キャプチャー画面に、矢印や説明を加え、ページに「ひとコマ」設定するだけで作れます。
  • FFmpeg を使って Youtube 動画にすることもできます。

 

画面キャプチャ方法

OS
画面キャプチャ方法
保存先
 Windows
クリップボード
 Mac
  • Shift + Command + 4 (ShiftキーはZの左、スペースでウィンドウ指定)
デスクトップ
 Android
  •  電源 + 音量Down
 adbコマンド (開発者向け)
  •  adb shell screencap -p /sdcard/screen.png
     adb pull /sdcard/screen.png
フォトアプリ>
ライブラリ>
Screenshots
 
iPhone / iPad
  •  ホームボタン + 電源ボタン
  • サイドボタン + 音量UP
写真>
アルバム>
スクリーンショット
 Linux Mint
  • Print Screen キー
クリップボード
ファイル
 Amazon Fire
  • 電源 + 音量Down 1秒長押し
  • USBケーブルでPCと接続し、
    設定>接続デバイス>USB>ファイル転送
ピクチャ >
スクリーンショット
 Chromebook
  • Shift + Ctrl + ウィンドウ一覧キー(上の中央のキー)
マイファイル >
ダウンロード
 X68000 Z
 

アニメGIF、動画出力

  • ファイルメニュー>アニメGIF出力」または「動画出力」で、好きなサイズのアニメGIF または MP4動画 が作成できます。
    Win / RaspberryPi / Linux版 でMP4動画を作るには FFmpeg が必要Youtube解説
  • スマホの場合、端末内の「9VAe」フォルダの中に出力されます。フォトアプリで、「端末内の写真>9VAe」で見ることができます。
  • アニメGIFは、背景を透明にできます。音がいれられません。
  • MP4動画には音が入れられます。Youtubeに投稿できます。Youtubeに投稿する場合、1秒30コマ、高さ720 または 1080 で出力するとよいでしょう。

 

 

9VAeをつかえば素材動画が作れる 

      • 9VAeきゅうべえを使えば、オリジナルの素材動画が簡単に作れます。
      • Openclipart や  FreeSVG などフリーのSVGイラストをつかって動くキャラクタが作れます。
      • 動画編集ソフトで動画に合成できます。

OS

フリーソフト

9VAeで作成する素材動画

Windows

AviUtl

連番PNG または MP4

Mac/iPhone/iPad

iMovie

MP4 または QuickTime(古いMac)

Android

PowerDirector

GIF または MP4

作り方

 

      • もっと長いアニメを作ることもできます。以下をご覧ください。

9VAeきゅうべえ:長いアニメを作る方法 - Qiita

 

 

9VAeきゅうべえに関する質問