wonx/README
Hiroaki Sakai 103ffe29f1 We implemented mmap (). Specifically, see README.
Added service function.  (A service function dumping information for debugging,
Added service function for screen drawing ON / OFF control) Specifically, see README.

Make the object's destructor called from bios_exit ()
Add appropriate Destroy function to each object.  Delete objects properly
We have checked the termination process as a whole, as done.

Fix to accept interrupts even during key_wait ().
(Previously, only key input was accepted)

Some timer interrupts are improved.  (UNIXTimer.c)

Change the wonx_include directory to wonx.

Changed to search the full path to perl automatically and insert it at the beginning of perl script.

Makefile review, improvement.

Changed ON / OFF of screen drawing to switch according to display level.
(See README for details.)
Also change to display level lowered by F9 and display level raised by F10.
In accordance with that, we have reviewed a part of ON / OFF part of drawing and key input event processing.

Fixed to display message when pressing key.

Obj ObjListData_GetPrev (ObjListData data)
Obj ObjListData_GetNext (ObjListData data)
To
ObjListData ObjListData_GetPrev (ObjListData data)
ObjListData ObjListData_GetNext (ObjListData data)
Fixed to.

Added install, uninstall target to Makefile.  Fixed challsrc.sh.

Version 2.2 - from wonx-2.2.tar.gz
2018-03-07 23:07:30 +00:00

1123 lines
38 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

WonX - WonderWitch on X.
■ 配布に当たって
ご意見,ご要望など歓迎します.どしどしお寄せください.
バグ情報やアドバイスがあれば,作者の坂井弘亮まで,どんどんメールください.
アドレスは,
hsakai@m8.people.or.jp
です.
(ただし,返事を書くとは限らないし,要望を反映するとも限りませんので
その点はご容赦ください)
また,坂井の気が向く限り,アップデートは随時行っていきます.
http://www.seki.ee.kagu.sut.ac.jp/~sakai/WonderWitch/index.html
で,随時公開していきます.
以下はミラーサイトです.
http://hp.vector.co.jp/authors/VA014157/WonderWitch/index.html
http://www.people.or.jp/~hsakai/WonderWitch/index.html
ミラーサイトは,坂井が気が向いたときにアップデートするので,常に最新,
というわけではありません.あくまでバックアップ用です.
■ はじめに
WonX はWonderWitch 用のプログラムを X アプリケーションとしてコンパイルする
ための,ライブラリです.以下の特徴があります.
・C言語レベルで互換機能を持っているのでWonderWitch 用のプログラムを
UNIX上でそのままコンパイルできる(-lwonx でコンパイルする)
・UNIX上でデバッガを使用してデバッグできるようになる(強力!)
・キャラクタデータやパレットデータのダンプ機能がある.
・不正な引数の値や,パレットやキャラクタを初期化しないで使用するなどを
厳しくチェックし,エラーを出力する(ようにする).厳しくエラーチェックする.
・使用できない機能(関数は用意してあるが,まだ実装してなかったり,
実装が困難だったりして,中身が空のもの)はたくさんある.
徐々に追加していくつもり.
・ゲームの画面写真が簡単に撮れる.(デジカメで撮ったり,画像取り込み用の
プログラムを使ったりする必要が無くなる) これはわりとべんり.
・エミュレータでなくライブラリであり,ソースコード公開しているので,
自由にカスタマイズが可能.
・描画速度は遅いが,デバッグ目的のためなので,速度を速くすることは
あまり考えていない.(それよりも上記のデバッグ性を優先する)
・WonderWitch 用のプログラムをX上で楽しむためのものではない
また,エミュレーションが目的なのではない.
あくまでデバッグ目的のもの.(そういうポリシーで開発を進める)
従ってWonderWitch での動作を模倣することよりも,デバッグ情報を
出力することや改造のしやすさを優先したような実装をする場合がある.
■ 必要なもの
WonX では,以下のものを使用しています.
・perl
(WonderWitch用ソースコード → WonX用ソースコードの変換用 perl スクリプトを
添付しているのでWonderWitch用ソースコードの中に漢字が入っているのならば
日本語 perl が望ましい)
添付の perl スクリプトはmake 時に自動で先頭に perl へのフルパス
(#!/usr/bin/perl など)が付加されるので,日本語 perl が別のところにある
ばあいには,修正してから使用してください.
日本語 perl が無ければ,まあ,ふつうの perl でもたぶん大丈夫でしょう.
・qkc
漢字コード変換,改行コード変換に必要.
(nkf でもべつにいいんだけどqkc だと改行コードも変換してくれるので,
この文書では qkc を使用しています)
qkc は,以下のサイトから入手できます.
http://hp.vector.co.jp/authors/VA000501/index.html
qkc にはMS-DOS 版Windows 版UNIX 版などがありますので,
UNIX 版(qkcc100.zip)を入手してください.
コンパイルはmake するだけなのでとっても簡単です.
・unzip
添付の smac-b02.zip, wwterm-b05.zip を解凍するのに必要.
このマニュアルは,以上のものがすべてインストールされていることを前提として
説明を進めます.必要ならばインストールするか,他のアプリケーションで
代用してください.
■ 3分WonX
とりあえず,どんなものか見てみたいことでしょう.そんな人は,
サンプルプログラムをコンパイル・実行してみましょう.
以下のようにしてみてください.
~>% tar xvzf wonx-x.x.tar.gz
(中略)
~>% cd wonx
~/wonx>% make sample1
(中略)
~/wonx>% ./sample1
ウインドウが開いて,標準出力にメッセージが出力されます.
スペース・バーを押すと,終了します.
~/wonx>% make sample2
(中略)
~/wonx>% ./sample2
カーソルキーの上下で,キャラクタを移動します.
スペース・バーを押すと,終了します.
~/wonx>% more sample1.c
~/wonx>% more sample2.c
で,サンプルプログラムのリストを見てみましょう.
次にWonderWitch 用のゲーム,"SpeedMac" をコンパイル・実行してみます.
~/wonx>% make smac
(中略)
~/wonx>% cd smac
~/wonx/smac>% ./smac
ウインドウが開いて,標準出力にメッセージが出力されます.
いったん F9 を押して画面描画を OFF にします.(何度も押すと表示レベルが
下がってしまうので,1回だけ長めに押してください)
しばらくしたら(メッセージの内容が変わったら) F10 を(長めに1回だけ)押して
再び画面表示を ON にするとsmac のタイトル画面が表示されます.
ここでスペースを押して,さらにまた F9 で画面表示を OFF にして,
しばらくしたら(メッセージの内容が変わったら) F10 で画面表示を ON にします.
どうですか? SpeedMac のゲーム画面が表示されているでしょうか?
カーソルキーで移動,スペースキーで射撃です.
ただし,キー入力はキー入力用関数が呼ばれたときしか有効ではないので,
キーは反応するまで長めに押してください.
F9, F10 を押して頻繁に描画の ON, OFF を切替えるのは,描画が非常に遅いため,
ONのままだと画面クリアとかに異常に時間がかかるからです
最後にWonderWitch 用の端末エミュレータ "WWTerm" をコンパイル・実行
してみます.
~/wonx>% make wwterm
(中略)
~/wonx>% cd wwterm
~/wonx/wwterm>% ./terminal
■ 10分WonX
次に,なにかあなたが作った WonderWitch 用のプログラムを WonX 使って
コンパイル・リンクしてX Window System 上で動作するような実行形式を
作ってみましょう.
まずWonX を展開してmake してくださいlibwonx.a と各種 perl スクリプトが
できあがります.
~>% tar xvzf wonx-x.x.tar.gz
(中略)
~>% cd wonx
~/wonx>% make
(中略)
~/wonx>% ls libwonx.a
libwonx.a
~/wonx>%
次にlibwonx.a とwonx ディレクトリと,
challsrc.sh, filters.pl, sys2wonx.pl, int2sint.pl をあなたの作ったプログラムの
ディレクトリ(ここでは例としてyoursample とします)にコピーします.
~/wonx>% cp -R libwonx.a wonx ../yoursample
~/wonx>% cp challsrc.sh filters.pl sys2wonx.pl int2sint.pl ../yoursample
~/wonx>% cd ../yoursample
~/yoursample>%
*.C というファイル名のファイルがあったら,*.c に変更します.
(*.C だと C++ のプログラムだと思われてしまうので)
~/yoursample>% mv SAMPLE2.C sample2.c
あなたの作ったプログラムのすべてのファイルに対して,以下のことを行います.
・MS-DOS テキスト形式から UNIX のテキスト形式に変換する.
(つまり,改行コードを \r\n から \n に変換して,漢字コードを SJIS から
EUC に変換します)
・プログラム中の #include <sys/disp.h> のようなのを,
#include "wonx/disp.h" に変更する.(sys2wonx.pl を通すことで変換してくれる)
・デフォルトの int をshort int に変換する.
(int2sint.pl を通すことで変換してくれる)
これらのフィルタをまとめて通してくれる filters.pl というスクリプトを
添付してあるので,以下のようにして,すべてのソースファイルに対して,
必要なフィルタを通してください.
~/yoursample>% ./filters.pl "qkc -e -u" ./sys2wonx.pl ./int2sint.pl -f *.[ch] [Mm]akefile* MAKEFILE*
もしくは,以下のようにしてもよいです.
~/yoursample>% ./challsrc.sh *.[ch] [Mm]akefile* MAKEFILE*
(注意! filters.pl や challsrc.sh は,*ファイルの本体を書き換えてしまう*ので,
変更されると困るようなファイルは必ずバックアップしてください)
makefile を以下のように修正する.
・コンパイラには gcc を使用する.
・オブジェクトファイルを *.obj から *.o に変更.
・コンパイルフラグに -I. -L. -L/usr/X11R6/lib -lwonx -lX11 -lXt を追加.
・mkfent などによる *.fx ファイルの作成などがあったら,コメントアウトする.
~/yoursample>% emacs makefile
おそらくmakefile の修正が2番目に面倒です.(一番面倒なのはWonX がうまく
適用できなかったときのソースの修正です)
添付の makefile_for_smac や makefile_for_wwterm を参考にしてmakefile を
修正してください.
最後にmake をします.
~/yoursample>% make
うまくいけば,一撃でコンパイルが通って,実行できます.
~/yoursample>% ./sample
■ WonX 概要
WonX はWonderWitch の display_control() とか display_status() といった関数
(BIOS に対するシステムコール)と代替の関数を持っています.
これらの関数はX上にウインドウを開いてそこで WonderWitch と互換の動作を
するように書いてあります.
WonX を make するとlibwonx.a というライブラリができます.
WonderWitch 用のプログラムをUNIX 上で -lwonx してコンパイルしてやれば,
WonderWitch の display_control() とかのかわりにWonX の display_control() が
リンクされX 上で動作するようになる,という仕組みです.
■ ヘッダファイルについて
WonX はUNIXシステム上にある libc を使用します.つまり,/usr/include の
下を include します.(このため strlen(), fopen() などの標準ライブラリは
UNIX 付属のものが使用可能)
またWonderWitch にはsys/types.h などといったヘッダファイルがあります.
よってWonderWitch のヘッダファイル構成をそのまま WonX に引き継ぐと,
WonX のヘッダファイルと UNIX のヘッダファイルがコンフリクトする
可能性が出てきます.
(たとえばWonderWitch の sys/types.h と UNIX の /usr/include/sys/types.h が
コンフリクトする,などです)
これはWonderWitch用のアプリケーションをコンパイルするときに要注意です
コンパイルがうまくとおらないという障害の原因は,ほとんどがこのような,
「ヘッダファイルのコンフリクトもしくは誤認」に起因しています.
対策としてWonX では wonx というディレクトリの下にヘッダファイルを
格納してあります.(本当は sys というディレクトリにしたかったが,
上記の対策のため,このようにした)
WonderWitch 用プログラム中の,
#include <sys/types.h>
のような部分は,すべて,
#include "wonx/types.h"
のように修正する必要があります.
(stdio.h や stdlib.h はUNIX システム付属のものを使用するので,
そのままでかまいません)
(ただし,コンフリクトしないという絶対の自信があるなら,この限りではありません)
WonderWitch のプログラムの,#include <sys/*.h> は,すべて
#include "wonx/*.h" に修正する必要がある,ということです.
(これをまとめて行うための sys2wonx.pl という perl スクリプトを添付して
あります../filters.pl ./sys2wonx.pl -f *.[ch] を実行すると,ごっそりと
書き換えてくれます)
またUNIXシステムによっては/usr/include/sys/types.h で ushort, ulong を
定義しているものといないものがあります.よって,コンパイル中に
ulong が2重定義されているとおこられる場合があります.(Linux ではそのように
なるようである)
このあたりの微調整にはwonx ディレクトリ以下のファイルを直接修正して
調整してくださいwonx/system_configure.h を修正することにより,
調整できるようになってます.
■ WonX のコンパイル
まず WonX をコンパイルしてlibwonx.a を作成する必要があります.
WonX のコンパイルは,以下の手順で行います.
1. WonX を展開する.
~>% tar xvzf wonx-x.x.tar.gz
~>% cd wonx
~/wonx>%
2. WonX を make する.
~/wonx>% make
gcc -c WWCharacter.c -O -I. -I/usr/X11R6/include
gcc -c WWColorMap.c -O -I. -I/usr/X11R6/include
...(中略)...
gcc -c wonx.c -O -I. -I/usr/X11R6/include
ar ruc libwonx.a WWCharacter.o WWColorMap.o WWDisplay.o WWLCDPanel.o WWPalette.o WWScreen.o WWSprite.o WonXDisplay.o XDisplay.o disp.o text.o key.o system.o timer.o etc.o wonx.o
~/wonx>% ls lib*
libwonx.a
~/wonx>%
このとき,各種 perl スクリプトも同時に作成されます.
必要があれば make install すると,各種ヘッダファイル,ライブラリ,
perl スクリプトがインストールされます.(インストールしなくても構いません.
以降はインストールしなかったものとして説明します)
~/wonx>% su
Password:
# make install
ここまでで,ライブラリの作成は終りです.
■ WonderWitch 用アプリケーションのコンパイル
次にWonX の利用の例として,拙作の SpeedMac という WonderWitch 用の
ゲームをコンパイルしてみます.
(SpeedMac はサンプルプログラムとしてWonX に標準添付してあります)
SpeedMac は WonderWitch 用のゲームプログラムです.本来は WonderWitch を
使用してコンパイルしWonderSwan 上でゲームを楽しむためのものです.
今回は例としてSpeedMac に WonX をリンクしてX 上で動作する SpeedMac の
実行形式を作成してみます.
1. 展開する.
~/wonx>% unzip smac-b02.zip
...(中略)...
~/wonx>% cd smac-b02
~/wonx/smac-b02>%
2. ヘッダファイルと libwonx.a をコピーする.
~/wonx/smac-b02>% cp -R ../wonx .
~/wonx/smac-b02>% cp ../libwonx.a .
~/wonx/smac-b02>%
3. ソースを修正する.
~/wonx/smac-b02>% emacs chara.c
~/wonx/smac-b02>% emacs dsp.c
... (ファイルをひとつひとつ修正する)
MS-DOS のファイル形式になっているファイルはUNIXのテキスト形式に
変換します.具体的には,以下の変換をします.
・改行コードを \r\n から \n にする.
・漢字コードを SJIS から EUC にする.
qkc というアプリケーションで,上記のことを一度に行うことができます.
面倒なかたは,以下のようにすれば,まとめて変換されます.
~/wonx/smac-b02>% ./filters.pl "qkc -e -u" -f *.[ch]
qkc が無い人は... nkf とかてきとうに使って変換してください.
また,ソース中の,
#include <sys/disp.h>
#include <sys/key.h>
のような部分を,
#include "wonx/disp.h"
#include "wonx/key.h"
のように修正します.
これをまとめてやるための perl スクリプト (sys2wonx.pl) を添付してあるので,
面倒なかたは,
~/wonx/smac-b02>% cp ../filters.pl ../sys2wonx.pl .
~/wonx/smac-b02>% ./filters.pl ./sys2wonx.pl -f *.[ch]
のようにしてください.
(filters.pl は,引数で指定したファイル自体を書き換えてしまうので注意)
さらにWonderWitch では sizeof(int) == sizeof(short int) ですが,
UNIX ではふつうは sizeof(int) == sizeof(long int) なので,
キャラクタのビットマップなどint 型のバイトサイズに依存する部分で
int を使用している場合にはshort int などと明示します.
これをまとめてやるための perl スクリプト (int2sint.pl) を添付してあるので,
面倒なかたは,
~/wonx/smac-b02>% cp ../int2sint.pl .
~/wonx/smac-b02>% ./filters.pl ./int2sint.pl -f *.[ch]
のようにしてください.
(filters.pl は,引数で指定したファイル自体を書き換えてしまうので注意)
日本語 perl は EUC コードでないと正常に動作しないので,
sys2wonx.pl や int2sint.pl を使用する場合には,まず先に qkc で漢字コードを
EUC に変換してからsys2wonx.pl や int2sint.pl を使用してください.
4. makefile を修正する.
~/wonx/smac-b02>% emacs makefile
以下のように修正します.
・漢字コードを EUC に,改行コードを \r\n から \n に変換する.
(改行コードを変換しないと make が正常に動作しませんqkc を通すと
いいでしょう)
・gcc でコンパイルをするように修正する.このときに,コンパイルオプションに,
-I. -L. -L/usr/X11R6/lib -lwonx -lX11 -lXt
を追加する.
(必要なら,-g も追加する)
・mkfent によるファイルのコンバートなどがあったら,削除する.
修正後の makefile を添付してあるので,面倒なかたは手で編集するかわりに,
~/wonx/smac-b02>% mv makefile makefile.orig
~/wonx/smac-b02>% cp ../makefile_for_smac ./makefile
のようにしてコピーしてください.
5. make する.
~/wonx/smac-b02>% make
gcc -c chara.c -g -I.
gcc -c game.c -g -I.
...(中略)...
gcc -c main.c -g -I.
gcc -g -o smac chara.o game.o man.o mansub.o mansub2.o map.o mapsub.o menu.o monster.o picture.o player.o smac.o stage.o dsp.o etc.o main.o -lwonx -lX11 -lXt -L. -L/usr/X11R6/lib
~/wonx/smac-b02>% ls smac
smac
~/wonx/smac-b02>%
6. smac を起動する.
~/wonx/smac-b02>% ./smac
と,ここまでけっこう面倒ですが,実は,
~/wonx>% make smac
すると,これらの作業を全部やってくれるようになってます.
■ 操作
smac を起動すると,ウインドウが開きます.また,ターミナルには,
以下のデバッグ用の情報が表示されます.
・WonderWitch の代替関数が呼ばれると,引数と戻り値を表示します.
またここでは,以下の操作が行えます.
・カーソルキーがWonderSwan のX1X4ボタンに対応している
・i,j,k,l キーがWonderSwan のY1Y4ボタンに対応している
・スペースバーと左シフトキーがA,Bボタンに対応している
・sキーがSTARTボタンに対応している
・F1 を押すとLCDカラーマップのデータをダンプ出力する
・F2 を押すと,パレットのデータをダンプ出力する.
・F3 を押すと,キャラクターのデータをダンプ出力する.
・F4 を押すと,スプライトのデータをダンプ出力する.
・F9 を押すと,画面の表示レベルを下げる.
・F10 を押すと,画面の表示レベルを上げる.
表示レベルはデフォルトで 1 になっており,現在のレベルが 1 以上の場合のみ
画面の描画を行う0 以下の場合には,画面への描画を行わないがそのぶん高速.
・F11 で10秒間停止(画面写真をとるときなどに利用できる)
(F11は短めに押してください長めに押すと復帰しなくなるようです)
・q もしくは Ctrl-c もしくは F12 で強制終了.
・Ctrl-i でアイコン化.
デフォルトではなにか関数が呼ばれるたびに画面の再描画を行うため,
非常に低速です.
たとえば,以下のようなことをやっていると,非常に低速になります.
/* 画面のクリア */
for (y = 0; y < 32; y++)
for (x = 0; x < 32; x++) {
screen_fill_char(0, x, y, 1, 1, 0); /* ここで毎回再描画される */
}
}
このような場合はF9 を押して表示レベルを下げて,ループ処理が終ったら
再び F10 を押して表示レベルを上げてください.(何度も押すと表示レベルが
どんどん下がって(もしくは上がって)しまうので,長めに1回だけ押してください)
F1 や F2 を押すと,データをダンプ出力するのですが,標準ではその他にも
メッセージが大量に出力されているので,ふつうに F1 を押しただけでは,
あっというまに大量のメッセージに流されてしまうことがあります.
このようなときは,以下のようにして起動します.たとえばコンパイルして
smac という実行形式ができているのなら,
> smac | grep -v call
もしもキャラクタ番号10番のキャラクタのデータだけが見たい場合には
以下のように実行してからF3 キーを押せば良いでしょう.
> smac | grep "character\[010\]"
WonX はメッセージを出力する際にgrep でフィルタリングできるように,
かならず出力メッセージの先頭に,統一性のある文字列を追加しています.
たとえば,関数呼び出し時に表示されるメッセージには,先頭に必ず
"call" という文字列が追加されてますよってgrep -v call を通せば,
関数呼び出しのメッセージがごっそり出なくなる,というようになってます.
標準では大量のメッセージが出てくるのでgrep をうまく使うようにしてください.
もしくは,
> smac | grep call > function_call.log
のようにして,ログをとるのも有効でしょう.
> smac > /dev/null
だと,文字列を kterm などに表示しないぶん,(かなり)高速になります.
■ 足りないもの
以下のものにはまだ対応してません.したがって,例えばサウンド関連の
関数を呼び出しても,何も起こりません.(空の関数になっている)
・サウンド
・プロセス
・インダイレクトライブラリ
■ 注意しなければならないこと
WonX は,本来は WonderWitch 用として書かれた(もしくは,書かれる)プログラムを,
UNIX 上でコンパイル・リンクするためのライブラリであり,ハードウエアを
エミュレートするものではありません.
ですからWonderWitch と UNIX 上のC言語のギャップのため気をつけなければ
ならないことがいくつかあります.これらは WonX の性質上,仕方の無いことです.
以下のことは,意識することと,きれいなプログラムを書くことで,
かなり回避できると思います.(ビットマップ操作などでshort int にすべき
ところでは,省略せずにちゃんと short int と明示するとか)
まあWonX の目的は論理的なバグを早い段階で無くすことと,
論理的バグとハードがらみのバグを切り離して原因を狭めることと,
坂井が電車の中でも WonderWitch のプログラムを書けるようにすることにあるので,
このへんはそういうものだと割り切って使ってください.
WonX を使う限り,なるべく機種依存を無くすように心がけましょう.
(とくに int のサイズにあまり依存しないようにしましょう)
[コンパイルの問題]
先にも書きましたが,コンパイルできないという障害が出たら,原因はたいていは
ヘッダファイルのコンフリクトですとくにWonderWitch で sys 以下の
ファイルをインクルードしている場合は注意してください.
ushort, ulong などはsys/types.h で定義されているシステムもあるし,
そうでないシステムもありますこのへんはwonx/system_configure.h で
調整してください.
(FreeBSD では ushort のみ定義されているがRedHat Linux では,
uchort, ulong ともに定義されているので,そのままだとコンパイル中に
2重定義のワーニングが出ます)
[int 型の扱い]
WonderWitch では sizeof(short int) == sizeof(int) < sizeof(long int) ですが,
UNIX ではふつう sizeof(short int) < sizeof(int) == sizeof(long int) です.
このことはint 型を単なるカウンタとして使用するような場合には問題に
なりませんが,ビットマップの格納場所として使用するようなときには,
問題になります.
一番問題になりやすいのは,キャラクタのビットマップを扱う場合です.
(bmpcnv を使用して,ビットマップデータの出力が unsigned int bitmap = {
のようになっている場合など)
font_set_colordata()などは16*8 バイトのキャラクタデータを
short int 型の配列として引数に持ちますWonderWitch では
sizeof(short int) == sizeof(int) なのでWonderWitch 用のプログラム上では,
キャラクタデータを short int とせずにint 型の配列として定義してしまう
ことが考えられます.(当然 WonderWitch ならば問題は無いがUNIX 上で
実行したら,キャラクタに妙な縞々が入るだろうと思われる)
このような場合にはUNIX 上でコンパイルするときには,コンパイラオプションで
デフォルトの int は short int になるように指定するか,もしくはソース中の
int を short int にじかに修正する必要がありますi386 上で gcc を使用する
場合には,このようなコンパイラオプションは無いので,じかにソースを修正する
ことになります.
int2sint.pl を通すと,明示されていない int はすべて short int に変換しますが,
もしもあなたが int2sint.pl が信用できなければ,手で修正してください.ふつうは
キャラクタのビットマップデータとそれを扱う部分のみを修正すれば十分でしょう.
コンパイル時のワーニングもちゃんと確認してください.また,コンパイル時には
-Wall オプションをつけましょう.
wonx-2.1 からは,キャラクタのビットマップ設定関連(font_set_colordata()など)
の関数の引数は,適切な型のポインタに修正したので,コンパイラがワーニングを
出していたら,ビットマップデータの型がおかしいかもしれません.
単なるカウンタやフラグとして使用しているような int は,多くの場合は
short int でも long int でも動作は変わりませんが,たとえそうだとしても,
WonX を使用してgcc で -Wall オプションをつけてコンパイルすると,
WonderWitch で動作させるときの潜在的なバグ(short int の上下限にまつわる
バグなど)を発見できることがあるので,なるべくなら int2sint.pl で int を
ごっそり short int にしてしまうことをおすすめします.
[バイトエンディアンの問題]
WonderWitch の CPU は x86系ですSPARC などで使用する場合には,
エンディアンに注意する必要があります.
font_set_colordata()などはshort int 型の配列でキャラクタデータを受け取る
のでunsigned char * で定義したキャラクタデータを short int * にキャストして
font_set_colordata()に渡すなどのことをしていると,画像がひっくり返る
ことが考えられます.
i386 系のいわゆる PC-UNIX ならば,おそらく問題は無いでしょう.
WonX-2.1 から,キャラクタデータに関しては,極力エンディアンに依存しないように
修正しましたi386 と SPARC でエンディアンに依存しないことを動作確認
しています.しかしそれでも,キャラクタデータを unsigned char * で定義して,
ビットマップ読み込み用の関数にキャラクタデータを渡すときに short int * に
キャストして渡すような書き方をしていると,依存してしまいます.つまり,
WonX 自体はエンディアンに依存していないがWonX を利用するプログラムが
エンディアン依存に書いてあっては,どうしようもないということです.
キャラクタデータのビットマップ読み込み用の関数には,適切な型のデータを
渡すようにしてくださいshort int * を渡すべきところにunsigned char * を
渡したりすると,このようなバグの原因になる可能性があります.不適切な
ポインタを渡している場合には,コンパイラがワーニングを出すので,
コンパイラのワーニングに十分に注意してください.
[タイマ割り込みの問題]
WonderWitch にはタイマ割り込みがありますがWonX の動作は非常に遅いため,
WonderWitch の時間単位をそのまま UNIX に持ってきたら,割り込みが
かかりっぱなしになってしまいます.よってタイマ割り込みの時間単位は,
WonderWitch よりもかなり大きめにしてあります.
これはwonx_configure.h で調整できます.
割り込みハンドラの中で,非常に時間のかかる画面描画などをしている
場合には,割り込みの時間単位を大きくしてください.でないと,ハンドラから
戻った瞬間にまたハンドラが呼ばれて,全然実行が先に進まない,ということに
なり得ます.
[キー入力割り込み,シリアル受信割り込みの問題]
(あまりやることはないと思いますが)キー入力割り込みとキー入力検査用関数を
同一ループ内で併用すると,割り込みのとりこぼしが起きやすくなる可能性が
あります.
つまり,以下のようなプログラムを書くときには注意してください.
void far key_handler()
{
/* キー入力の処理がここに入る */
}
static intvector_t key_intvector;
static intvector_t key_last_intvector;
main()
{
key_intvector.callback = (void (near *)())FP_OFF(key_handler);
key_intvector.cs = _asm_inline("\tmov\tax,cs");
key_intvector.ds = _asm_inline("\tmov\tax,ds");
sys_interrupt_set_hook(SYS_INT_KEY, &key_intvector, &key_last_intvector);
while (1) {
/*
* キー入力割り込み待ちの状態なのにkey_press_check() でキー入力状態の
* 検査も行う
*/
key = key_press_check();
/* なんか適当な処理をこのへんで行ったりする */
}
}
キー入力割り込みを待ちながらkey_press_check() でキーの入力状態を
別個に検査する,ということをやると,割り込みのとりこぼしが起きる可能性が
あります.
(ただし,キー入力割り込みによって呼び出される割り込みハンドラ内で
key_press_check() を使用することは問題ありません.(でないと割り込みの
意味が無くなってしまうしね) あくまで,同じループ内で併用すると問題が
発生する可能性がある,ということです)
でも,こんなへんなプログラムあまり書くこと無いだろうし,いいかなと思ってます.
(これを直そうとすると,とてもたいへんなので)
このことは,シリアル受信割り込みに関しても,同様です.
[キー入力について]
キー入力は,キー入力用関数が呼ばれたときのみ感知するので,長めに押してないと
反応しないことがあります.
反応しないからといってなんども押すのでなく,1回を長く確実に押すように
してください.
[MS-DOS 形式ファイルの扱い]
MS-DOS 形式ファイルは,行末の改行コードが UNIX のテキストファイルと
異なるので,注意してください.*.[ch] ファイルの場合は問題無いのですが,
makefile は注意してください.
(UNIX のテキストファイルでは,改行は \n ですがMS-DOS では \r\n です)
例えばmakefile 中に,
gcc -g -o smac $(OBJS) -L. -L/usr/X11R6/lib -lwonx -lX11 -lXt
のような行があったとして,これが MS-DOS のテキスト形式のファイルだと,
-lXt のあとに余分な改行コード(\r)が付加されてしまうためUNIX 上で make
しても,「-lXt に相当するライブラリが無い」と怒られてしまいます.
(実際にはコンパイラは,-lXt\r だと思ってしまってlibXt\r.a というライブラリを
探してしまうのです)
(しかも,ファイルを emacs や less などで参照しても,改行コードは表示されない
ため,原因がとってもわかりにくい)
また,
gcc -g -o smac $(OBJS) -lwonx -lX11 -lXt -L. -L/usr/X11R6/lib
のようにしていると,/usr/X11R6/lib を指定したつもりなのに,実際には
/usr/X11R6/lib\r というディレクトリが指定されたことになってしまい,
-lX11, -lXt の検索に失敗し,やはり make に失敗します.
漢字コードに関しても同じことがいえますUNIX での漢字コードは EUC なので,
ソースコード中に SJIS の漢字が入っていると,うまくコンパイルできなかったり,
make がうまく動作しなかったり,コンパイルできてもプログラム自体が
誤動作してしまい,しかも原因に気づきにくくなってしまう可能性があります.
makefile やソースコードは必ず,
> cat makefile | qkc -e -u > makefile.tmp
> mv makefile.tmp makefile
などを通してUNIXのテキストファイルに変換しましょう
[ファイル名の問題]
MS-DOS ではファイル名はすべて大文字ですがgcc では *.C のような
ファイル名のファイルは C++ で書かれていると判断されるため,
SAMPLE.C のような名前のファイルをコンパイルすると,うまくリンクできない
ことがあります.
このような場合はsample.c にリネームしてコンパイルしてください.
[シリアル通信について]
シリアル通信の受信用関数(comm_receive_char()等)はfgetc(stdin) から
入力文字を取得して,\n は \r に変換して返します.これは,一般的な通信回線上の
端末をエミュレートするためです.
またcomm_send_char() に渡した文字は,標準出力に出力されますが,
タブや改行コードは,"\t" "\n" のような文字列に変換されて出力されます.
添付の sout2str.pl を通すことにより,シリアル通信への出力のみ抽出して,
端末への出力のイメージで表示させることができます.
sout2str.pl は以下のようにして利用します.
(terminal という WonderWitch 用プログラムをWonX を利用して UNIX 上で
コンパイルしてsout2str.pl を通してシリアルへの出力のイメージを見たい場合)
> ./terminal | ./sout2str.pl
■ 割り込みについて
キー入力割り込みやシリアル受信割り込みなどはUNIXのアラームシグナルを
利用して実装しています.(一定時間おきにポーリングしている)
したがって,以下のようなプログラムもコンパイルして正常に動作させる
ことができます.
void far key_handler()
{
int key;
key = key_press_check();
/* キー入力の処理がここに入る */
}
/* シリアル受信の割り込みハンドラ */
void far com_handler()
{
int c;
c = comm_receive_char();
/* シリアル受信の処理がここに入る */
}
static intvector_t key_intvector;
static intvector_t key_last_intvector;
static intvector_t com_intvector;
static intvector_t com_last_intvector;
main()
{
key_intvector.callback = (void (near *)())FP_OFF(key_handler);
com_intvector.callback = (void (near *)())FP_OFF(com_handler);
key_intvector.cs = _asm_inline("\tmov\tax,cs");
key_intvector.ds = _asm_inline("\tmov\tax,ds");
com_intvector.cs = _asm_inline("\tmov\tax,cs");
com_intvector.ds = _asm_inline("\tmov\tax,ds");
sys_interrupt_set_hook(SYS_INT_KEY,
&key_intvector, &key_last_intvector);
sys_interrupt_set_hook(SYS_INT_RECEIVEREADY,
&com_intvector, &com_last_intvector);
while (1) {
/* 無限ループ.割り込みが入ったら,そのハンドラに飛ぶ */
}
}
_asm_inline() は常に0を返すダミー関数として定義されています
またFP_OFF(), FP_SEG() は,
#define FP_OFF(p) (p)
#define FP_SEG(p) (0)
のように定義されています.よって,上記のようなプログラムも WonX で
コンパイルして実行することができます.
このようにwhile (1) {} で無限ループを回して,割り込みがあったときだけ
処理するようなプログラムを書いても,正常に動作します.
しかし,キー入力はポーリングされているときしか感知されないので,
キー入力割り込みをかけるには,長めにキーを押してやる必要があります.
(キーは基本的に鈍いので,反応するまで長めに押してください)
■ ソース中の WonX 依存部分のくくりかた
WonderWitch 用のプログラムを開発していく際にWonX の場合のみ組み込みたくて,
WonderSwan 上で実行するときには取り除きたいコードがあったとします.
(例えば,デバッグ情報の出力のために printf() を入れる場合など)
このようなときのためにwonx/types.h で
#define _WONX_
してあるので,そのような場所は #ifdef _WONX_ でくくってください.
■ WonX が提供するサービス関数
WonX は以下の関数をデバッグ用のサービス関数として提供しています.
以下の関数を実行することにより,デバッグ情報を stdout に出力します.
#include "wonx/wonx.h"
/* カラーマップ情報の出力 */
void wonx_print_colormap_data(void);
/* パレット情報の出力 */
void wonx_print_palette_data(int n);
/* すべてのパレット情報を出力 */
void wonx_print_all_palette_data(void);
/* キャラクタ情報の出力 */
void wonx_print_character_data(int n);
/* すべてのキャラクタ情報を出力 */
void wonx_print_all_character_data(void);
/* スプライト情報の出力 */
void wonx_print_sprite_data(int n);
/* すべてのスプライト情報を出力 */
void wonx_print_all_sprite_data(void);
たとえばソース中に不安な場所があったら,
#ifdef _WONX_
#include "wonx/wonx.h"
#endif
void func(void)
{
...(中略)...
#ifdef _WONX_
wonx_print_sprite_data(0);
#endif
/* ここにスプライトの設定についての不安なコードがある */
#ifdef _WONX_
wonx_print_sprite_data(0);
#endif
...(以下略)...
のようにして不安なコードの前後でダンプデータを取ると,デバッグに役立つ
でしょう.#ifdef _WONX_ でくくっておけば,デバッグコードをソース中に残した
ままで WonderWitch でもコンパイルが可能なので便利です.
またWonX では画面の描画に時間がかかるのに加えて,画面の描画は画面関連の
システムコール(パレットの変更なども含む)が呼ばれるたびに行われるため,
for (y = 0; y < TEXT_SCREEN_HEIGHT; y++) {
for (x = 0; x < TEXT_SCREEN_WIDTH; x++) {
text_put_char(x, y, ' ');
}
}
のようなコードがあるとtext_put_char() の呼び出しのたびに画面描画が行われる
ため,動作が非常に遅くなります.
これの対策としてF9, F10 を押して画面の表示レベルを変化させることで
画面の表示/非表示を切替えられるようにしてあるのですが,以下のサービス関数を
利用することで,プログラム中から画面の表示レベルを制御できます.
表示レベルはデフォルトでは 1 になっており,表示レベルが 1 以上のときのみ
描画が行われます.
とくに gdb などを使ってデバッグする場合にはF9, F10 の反応が鈍くなったり
するおそれがあるため,重宝するでしょう.
#include "wonx/wonx.h"
/* 現在の表示/非表示のレベルの取得.(1以上で表示0以下で非表示) */
int wonx_get_lcddraw_level(void);
/* 現在の表示/非表示のレベルの設定 */
int wonx_set_lcddraw_level(int level);
/* 表示レベルを下げる */
int wonx_lcddraw_level_down(void);
/* 表示レベルを上げる */
int wonx_lcddraw_level_up(void);
実際のプログラム中では,以下のようにして利用します.
#ifdef _WONX_
#include "wonx/wonx.h"
#endif
void func(void)
{
...(中略)...
#ifdef _WONX_
wonx_lcddraw_level_down();
#endif
for (y = 0; y < TEXT_SCREEN_HEIGHT; y++) {
for (x = 0; x < TEXT_SCREEN_WIDTH; x++) {
text_put_char(x, y, ' ');
}
}
#ifdef _WONX_
wonx_lcddraw_level_up();
#endif
...(以下略)...
このように書くことによりWonX でのコンパイル時には text_put_char() 実行時の
画面描画を抑止して,高速化することができます.
(#ifdef _WONX_ でくくるのを忘れないようにしましょう)
■ 画面の表示レベルについて
WonX-2.2 から,画面の表示レベルというものを導入しました.
(WonX-2.1 まではF10 による画面描画の ON/OFF の切替えのみだった)
これの理由は,プログラム中から
(wonx_lcddraw_level_up(), wonx_lcddraw_level_down() などによって)画面の描画を
制御する際にON/OFF しかできないと,関数の中から関数を呼ぶような場合に
期待通りに動作しないからです.たとえば以下のような場合です.
void sample1(void)
{
wonx_lcddraw_draw_off();
/* 処理2 */
wonx_lcddraw_draw_on();
}
void sample2(void)
{
wonx_lcddraw_draw_off();
/* 処理1 */
sample1();
/* 処理3 */
wonx_lcddraw_draw_on();
}
処理処理の位置では画面描画はOFFになっているのですが処理の部分では
期待に反して画面の描画は ON になってしまいます.これではどこの関数で
ON/OFF しているのかを常に注意しなければならなくなりOFF にしているつもりでも
どこかで ON になってしまっていたりと,何のデバッグをしているのがわからなく
なってしまいます.
この対策として,表示レベルを定めて,以下のように書けるようにしました.
void sample1(void)
{
wonx_lcddraw_level_down();
/* 処理2 */
wonx_lcddraw_level_up();
}
void sample2(void)
{
wonx_lcddraw_level_down();
/* 処理1 */
sample1();
/* 処理3 */
wonx_lcddraw_level_up();
}
これだと処理2のところでは表示レベルは -1処理処理のところでは
表示レベルは 0 となるため,期待通りに動作してくれます.
■ mmap() について
WonX の設計思想では「UNIX側にも存在するサービス関数はUNIXにまかせる」
と考えているためfopen() などは WonX では用意していません.
しかし mmap() に関してはUNIX と WonderWitch で動作がかなり違うのと,
WonderWitch のプログラム中で実際に mmap() を使用しているものが多いという
実情があったのでWonX-2.2 で mmap() システムコールの実装を行いました.
ただし実装上の問題があってUNIX 側では mmap() は,/usr/include/stdio.h で,
void * mmap(void * addr, size_t len, int prot, int flags, int fd, off_t offset);
のように定義されています.(FreeBSD の例)
これに対して WonderWitch ではinclude/sys/fcntl.h で,
void * mmap(char * filename);
のような形でに定義されています.(実際にはポインタは far ポインタになっているが)
UNIX の mmap() と WonderWitch の mmap() では,引数の数も種類も違います.
このため WonderWitch に合わせて mmap() を実装するとWonX のコンパイル時や
WonX をリンクするプログラムのコンパイル時に,関数の引数がコンフリクトして
エラーとなってしまいますWonX をリンクするプログラム中ではstdio.h が
インクルードされる可能性が常に存在するので,移植性の高い方法でこの問題を
根本的に解決することはできません.
これの苦肉の対策としてWonX では mmap() は wonx_mmap() という名前で定義して,
fcntl.h では,
#define mmap wonx_mmap
することで対処していますつまりmmap() の実体は wonx_mmap() となります.
具体的には fcntl.[ch] を参照してください.
このためfcntl.h をインクルードするのを忘れて mmap() を使用すると,
UNIX の mmap() (stdio.h の mmap()) が有効になってしまうため,
「関数の引数が食い違っている」という内容のエラーが出ると思われるので,
注意してください.
また,この方法だと fcntl.h の後に stdio.h がインクルードされるような場合に,
stdio.h の中で宣言されている mmap() も wonx_mmap() に書き変わってしまい,
やはり関数の引数がコンフリクトしてしまいます対策としてfcntl.h の先頭付近で
stdio.h のインクルードを行いfcntl.h の後で stdio.h がインクルードされても,
度目のインクルードになってstdio.h の先頭で,
#ifndef _STDIO_H_
#define _STDIO_H_
などで切られるようになっています.
今後同様な関数を実装するときにも,同じような対処になるでしょう.
うーん,ほんとに苦肉の策だなあ... #define をつかうか,もしくは
void * wonx_mmap(char * filename);
void * mmap;
mmap = wonx_mmap;
のようにして代入しなおす,などの方法も検討したのですが,結局これがいちばん
確実でわかりやすい方法かなあ... と思ってます.もっといいアイディアがあったら
教えてください.
■ 実行の高速化について
WonX はデバッグ目的のライブラリであるため,あまり高速動作のことを
考えていません.そのため,遅いです.ですが,以下のことに注意することで,
かなり速く動作させることもできます.
プログラム中のホットスポットになる部分を,
wonx_lcddraw_level_down(), wonx_lcddraw_level_up()
でくくるこれによりF10 を押して画面描画を OFF にしたのと同じ効果が
得られます.
実行時には,
> ./smac > /dev/null
のようにして,出力メッセージを /dev/null に捨てる.
WonX は大量のメッセージを出力しますがkterm 上などで動作させている場合には,
このメッセージの処理が大きな負荷になります.このため,メッセージを
/dev/null に捨ててしまうことで,高速に動作させることができるようになります.
これらのことに気をつければ,かなり高速に動かすことが可能になります.
■ 添付のツールについて
perl スクリプト(*.pl)は make することにより,*.perl から自動生成されます.
このときperl のある場所を自動検索して,スクリプトの先頭行に
#!/usr/bin/perl のような行を追加してくれます.
[sys2wonx.pl]
#include <sys/disp.h>
を,
#include "wonx/disp.h"
のように変換するフィルタです.
[int2sint.pl]
short か long か明示されていない int をshort int に変換します.
sizeof(int) や uint* もsizeof(short int), unsigned short int* に
変換されます.
ただ,ひょっとしたらおかしな変換をしてしまうかも... でもたぶんそのときには
コンパイル時にエラーが出るだろうから,いいか.
そうだperl は行単位に処理するので,
long
int a;
とか,
void func(long
int a)
のような変な書き方をしていると,
long
short int a;
とか,
void func(long
short int a)
に変換されてしまって,きっとエラーになることでしょう.気をつけてください.
[filters.pl]
複数のフィルタをまとめて通すための perl スクリプトです.
書式は,
filters.pl [filters...] -f [files...]
です.例えば,
> filters.pl sort head -f file1 file2 file3
は,
> cat file1 | sort | head > file1.tmp
> mv file1.tmp file1
> cat file2 | sort | head > file2.tmp
> mv file2.tmp file2
> cat file3 | sort | head > file3.tmp
> mv file3.tmp file3
をすることと等価です.
[challsrc.sh]
WonderWitch用ソース → wonx用ソース への変換をするためのシェルスクリプトです.
内容は,単に,
./filters.pl "qkc -e -u" ./sys2wonx.pl ./int2sint.pl -f [files]
するだけです.
日本語 perl を使用する場合には,漢字コードは EUC でないと正常に動作しないので,
"qkc -e -u" を通してから ./sys2wonx.pl と ./int2sint.pl を
通すような順番になっています.
[sout2str.pl]
wonx は,シリアルポートへの出力は,
output to serial port : "A"
とか,
output to serial port : "\n"
のように標準出力に出力しますsout2str.pl は,この "" でくくられた部分
のみを抽出して,\n や \t を適切なコードに変換して出力するフィルタです.
シリアルポートを使用するプログラム(例: wwterm)を起動するときには,
> wwterm | ./sout2str.pl
のようにしてsout2str.pl を通して起動することにより,実際のシリアルポート
への出力をモニタすることができます.
■ 作者
WonX は,坂井弘亮がその大部分を往復3時間の通勤電車の中で Libretto で書いた,
「電車ソフトウエア」ですGPLで配布します
作者については,添付の OMAKE.jpn を参照してください.
坂井弘亮の連絡先のメールアドレスは,
hsakai@m8.people.or.jp
です.また,本ソフトウエアの最新版を,
http://www.seki.ee.kagu.sut.ac.jp/~sakai/WonderWitch/index.html
で配布しています.
以下はミラーサイトです.
http://hp.vector.co.jp/authors/VA014157/index.html
http://www.people.or.jp/~hsakai/index.html
ミラーサイトは,坂井が気が向いたときにアップデートするので,常に最新,
というわけではありません.あくまでバックアップ用です.
■ このファイルはここまで