Browse Source

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
Hiroaki Sakai 23 years ago
parent
commit
103ffe29f1
74 changed files with 2406 additions and 262 deletions
  1. 7 3
      COPYRIGHT
  2. 43 0
      HISTORY
  3. 60 24
      Makefile
  4. 952 30
      OMAKE.jpn
  5. 2 2
      Obj.c
  6. 2 2
      Obj.h
  7. 321 74
      README
  8. 3 1
      UNIXSerialPort.c
  9. 9 3
      UNIXTimer.c
  10. 1 1
      WWCharacter.c
  11. 1 1
      WWCharacter.h
  12. 2 1
      WWColorMap.c
  13. 2 1
      WWCursor.c
  14. 5 4
      WWDisplay.c
  15. 1 1
      WWInterrupt.h
  16. 6 1
      WWLCDPanel.c
  17. 2 1
      WWPalette.c
  18. 4 2
      WWScreen.c
  19. 2 0
      WWSerialPort.c
  20. 1 1
      WWSerialPort.h
  21. 2 1
      WWSprite.c
  22. 2 1
      WWText.c
  23. 2 0
      WWTimer.c
  24. 1 1
      WWTimer.h
  25. 65 4
      WonX.c
  26. 1 0
      WonX.h
  27. 39 13
      WonXDisplay.c
  28. 2 0
      WonXDisplay.h
  29. 3 3
      WonXSystem.c
  30. 195 43
      XDisplay.c
  31. 7 2
      XDisplay.h
  32. 9 2
      XDisplayP.h
  33. 1 1
      bank.c
  34. 5 2
      challsrc.sh
  35. 1 1
      comm.c
  36. 1 1
      disp.c
  37. 105 0
      fcntl.c
  38. 9 5
      filters.perl
  39. 26 0
      findperl.sh
  40. 3 1
      int2sint.perl
  41. 19 7
      key.c
  42. 1 1
      libwwc.c
  43. 3 3
      sample1.c
  44. 2 2
      sample2.c
  45. 35 0
      sample3.c
  46. 2 1
      service.c
  47. 1 1
      sound.c
  48. 2 2
      sout2str.perl
  49. 8 0
      sys2wonx.perl
  50. 0 6
      sys2wonx.pl
  51. 1 1
      system.c
  52. 1 1
      text.c
  53. 1 1
      timer.c
  54. 366 0
      wonx.c
  55. 0 0
      wonx/bank.h
  56. 0 0
      wonx/bios.h
  57. 0 0
      wonx/comm.h
  58. 0 0
      wonx/disp.h
  59. 11 1
      wonx/fcntl.h
  60. 0 0
      wonx/filesys.h
  61. 0 0
      wonx/indirect.h
  62. 0 0
      wonx/key.h
  63. 0 0
      wonx/libwwc.h
  64. 0 0
      wonx/oswork.h
  65. 0 0
      wonx/process.h
  66. 0 0
      wonx/service.h
  67. 0 0
      wonx/sound.h
  68. 0 0
      wonx/system.h
  69. 0 0
      wonx/system_configure.h
  70. 0 0
      wonx/text.h
  71. 0 0
      wonx/timer.h
  72. 0 0
      wonx/types.h
  73. 43 0
      wonx/wonx.h
  74. 5 1
      wonx_configure.h

+ 7 - 3
COPYRIGHT

@@ -1,7 +1,7 @@
 /*****************************************************************************/
 /* WonX - WonderWitch on X.                                                  */
 /*                                                                           */
-/* WonX Copyright (c) 2000-2001 Sakai Hiroaki.                               */
+/* WonX Copyright (c) 2000-2002 Sakai Hiroaki.                               */
 /* All Rights Reserved.                                                      */
 /*===========================================================================*/
 /* This program is free software; you can redistribute it and/or modify      */
@@ -37,10 +37,14 @@
 /* あるものとします.                                                        */
 /*===========================================================================*/
 /* 坂井弘亮の連絡先のメールアドレスは,                                      */
-/* sakai@seki.ee.kagu.sut.ac.jp                                              */
-/* hsakai@pfu.co.jp                                                          */
+/* 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                                */
+/* ミラーサイトは,坂井が気が向いたときにアップデートするので,常に最新,    */
+/* というわけではありません.あくまでバックアップ用です.                    */
 /* ご意見,ご感想がありましたら,ぜひ連絡ください.                          */
 /*****************************************************************************/

+ 43 - 0
HISTORY

@@ -1,3 +1,46 @@
+2002/2/4(月)
+
+wonx-2.2 公開
+
+mmap() を実装した.具体的には README 参照.
+
+サービス関数を追加.(デバッグ用の情報をダンプするサービス関数と,
+画面描画ON/OFF制御用のサービス関数を追加) 具体的には README 参照.
+
+bios_exit() からオブジェクトのデストラクタが呼ばれるようにして,
+各オブジェクトに適切な Destroy 関数を追加.オブジェクトの削除が適切に
+行われるように,終了処理を全般的にチェックした.
+
+key_wait() 中にも割り込みを受け付けるように修正.
+(以前はキー入力しか受け付けていなかった)
+
+タイマ割り込みを一部改良.(UNIXTimer.c)
+
+wonx_include ディレクトリを wonx に名前を変更.
+
+perl へのフルパスを自動で検索して perl スクリプトの先頭に挿入するように変更.
+
+Makefile 見直し,改良.
+
+画面描画の ON/OFF を,表示レベルによって切替えるように変更.
+(詳しくは README 参照)
+また,F9 で表示レベルを下げ,F10 で表示レベルを上げるように変更.
+それにあわせて,描画のON/OFF部分とキー入力イベント処理の一部見直しをした.
+
+キーの押下時にメッセージを表示するように修正.
+
+Obj ObjListData_GetPrev(ObjListData data)
+Obj ObjListData_GetNext(ObjListData data)
+を
+ObjListData ObjListData_GetPrev(ObjListData data)
+ObjListData ObjListData_GetNext(ObjListData data)
+に修正.
+
+Makefile に install, uninstall ターゲットを追加.challsrc.sh 修正.
+
+
+
+
 2001/1/13(土)
 
 wonx-2.1 公開

+ 60 - 24
Makefile

@@ -2,29 +2,40 @@ XINCLUDEDIR = /usr/X11R6/include
 INCLUDEDIR = .
 XLIBDIR = /usr/X11R6/lib
 
-VERSION = WonX-2.1
-PKGNAME = wonx-2.1
+VERSION = WonX-2.2
+PKGNAME = wonx-2.2
 
 SMAC = smac-b02
 WWTERM = wwterm-b05
 
-OBJS = WWCharacter.o WWColorMap.o WWDisplay.o WWLCDPanel.o WWPalette.o WWScreen.o WWSprite.o WWCursor.o WWText.o WWInterrupt.o WWTimer.o WWSerialPort.o WonX.o WonXDisplay.o WonXSystem.o WonXSerialPort.o XDisplay.o XColorGC.o UNIXTimer.o UNIXSerialPort.o Obj.o bank.o comm.o disp.o text.o key.o sound.o system.o timer.o libwwc.o service.o etc.o
+OBJS = WWCharacter.o WWColorMap.o WWDisplay.o WWLCDPanel.o WWPalette.o WWScreen.o WWSprite.o WWCursor.o WWText.o WWInterrupt.o WWTimer.o WWSerialPort.o WonX.o WonXDisplay.o WonXSystem.o WonXSerialPort.o XDisplay.o XColorGC.o UNIXTimer.o UNIXSerialPort.o Obj.o bank.o comm.o disp.o text.o key.o sound.o system.o timer.o libwwc.o service.o fcntl.o etc.o wonx.o
 
-CC = gcc
+PERLS = filters.pl int2sint.pl sout2str.pl sys2wonx.pl
+#PERL = /usr/bin/perl
+
+CC ?= gcc
+AR ?= ar
+RANLIB ?= ranlib
+CFLAGS += -O
+#CFLAGS += -g
+CFLAGS += -Wall
+
+PREFIX ?= /usr/local
 
 .SUFFIXES: .c .o
+.SUFFIXES: .perl .pl
 
-all :		libwonx.a
+all :		libwonx.a $(PERLS)
 
 libwonx.a :	$(OBJS)
-		ar ruc libwonx.a $(OBJS)
-#		ranlib libwonx.a
+		$(AR) ruc libwonx.a $(OBJS)
+#		$(RANLIB) libwonx.a
 
 .c.o :		$*.c
-		$(CC) -c $*.c -O -Wall -I$(INCLUDEDIR) -I$(XINCLUDEDIR)
+		$(CC) -c $*.c $(CFLAGS) -I$(INCLUDEDIR) -I$(XINCLUDEDIR)
 
 clean :
-		rm -f libwonx.a sample1 sample2 *.o
+		rm -f libwonx.a sample1 sample2 sample3 *.o *.pl
 		rm -fR $(SMAC) $(WWTERM)
 
 sample1 :	libwonx.a sample1.o
@@ -35,38 +46,63 @@ sample2 :	libwonx.a sample2.o
 		$(CC) sample2.o -o sample2 \
 			-L. -L/usr/X11R6/lib -lwonx -lX11 -lXt
 
-smac :		libwonx.a
+sample3 :	libwonx.a sample3.o
+		$(CC) sample3.o -o sample3 \
+			-L. -L/usr/X11R6/lib -lwonx -lX11 -lXt
+
+smac :		libwonx.a $(SMAC)
+		cd $(SMAC) ; $(MAKE)
+
+$(SMAC) :	$(SMAC).zip $(PERLS)
 		unzip $(SMAC).zip
-		cp -R wonx_include $(SMAC)
+		mkdir -p $(SMAC)/wonx
+		cp wonx/*.h $(SMAC)/wonx
 		cp libwonx.a $(SMAC)
 		mv $(SMAC)/makefile $(SMAC)/makefile.orig
 		cp makefile_for_smac $(SMAC)/makefile
-		cp challsrc.sh filters.pl sys2wonx.pl int2sint.pl $(SMAC)
-		# ここで止まったときは,filters.pl, sys2wonx.pl, int2sint.pl の
-		# 1行目に適切なperlを指定してください"
+		cp challsrc.sh $(PERLS) $(SMAC)
 		cd $(SMAC) ; ./challsrc.sh *.[ch] makefile
-		cd $(SMAC) ; $(MAKE)
 
-wwterm :	libwonx.a
+wwterm :	libwonx.a $(WWTERM)
+		cd $(WWTERM) ; $(MAKE)
+
+$(WWTERM) :	$(WWTERM).zip $(PERLS)
 		unzip $(WWTERM).zip
-		cp -R wonx_include $(WWTERM)
+		mkdir -p $(WWTERM)/wonx
+		cp wonx/*.h $(WWTERM)/wonx
 		cp libwonx.a $(WWTERM)
 		mv $(WWTERM)/makefile $(WWTERM)/makefile.orig
 		cp makefile_for_wwterm $(WWTERM)/makefile
-		cp challsrc.sh filters.pl sys2wonx.pl int2sint.pl $(WWTERM)
-		# ここで止まったときは,filters.pl, sys2wonx.pl, int2sint.pl の
-		# 1行目に適切なperlを指定してください"
+		cp challsrc.sh $(PERLS) $(WWTERM)
 		cd $(WWTERM) ; ./challsrc.sh *.[ch] makefile
-		cd $(WWTERM) ; $(MAKE)
+
+.perl.pl :	$*.perl
+		./findperl.sh $(PERL) | cat - $*.perl > $*.pl
+		chmod +x $*.pl
+
+install :	libwonx.a $(PERLS)
+		mkdir -p $(PREFIX)/include/wonx
+		cp wonx/*.h $(PREFIX)/include/wonx
+		cp libwonx.a $(PREFIX)/lib
+		cp challsrc.sh $(PERLS) $(PREFIX)/bin
+
+uninstall :
+		rm -fR $(PREFIX)/include/wonx
+		rm -f $(PREFIX)/lib/libwonx.a
+		rm -f $(PREFIX)/bin/challsrc.sh
+		rm -f $(PREFIX)/bin/filters.pl
+		rm -f $(PREFIX)/bin/int2sint.pl
+		rm -f $(PREFIX)/bin/sout2str.pl
+		rm -f $(PREFIX)/bin/sys2wonx.pl
 
 package :
 		mkdir -p $(PKGNAME)
 		rm -fR $(PKGNAME)/*
-		mkdir -p $(PKGNAME)/wonx_include
+		mkdir -p $(PKGNAME)/wonx
 		cp COPYING COPYRIGHT HISTORY README MANUAL OMAKE.jpn Makefile \
-			makefile_for_smac makefile_for_wwterm *.sh *.pl \
+			makefile_for_smac makefile_for_wwterm *.sh *.perl \
 			*.h *.c $(SMAC).zip $(WWTERM).zip $(PKGNAME)
-		cp wonx_include/*.h $(PKGNAME)/wonx_include
+		cp wonx/*.h $(PKGNAME)/wonx
 		tar cvzf $(PKGNAME).tar.gz $(PKGNAME)
 
 # End of Makefile.

+ 952 - 30
OMAKE.jpn

@@ -1,5 +1,139 @@
+2002.2 update
+
 この文書は,おまけ,ていうか,暇なときに気が向いたまま書き貯めたものです.
 
+■■ XFireworks 開発秘話
+
+XFireworks は X 上で動作する花火プログラムである.そもそもなんで XFireworks を
+作ったかというと,単なる思いつきである.nadar-b05 を作り上げ,しばらく
+ぼーっとしていた時期に,なにかまた作りたいなーと思っているとき,
+電車の中で思いついた.
+XFireworks を作りはじめたのは 2000 年の7月初旬だったのだが,nadar-b05 を
+作ったときの教訓で,
+
+	とりあえず動くものを作って公開しちまえ
+
+というのがあったので,かなり早い段階でβ版を公開して linux-users-ML などで
+広報し,あとは3日に1回ほど最新版をアップデートしながら作成していった.
+
+結局それから1ヵ月くらいで書き上げ,8月のはじめに最終版をリリースしたので,
+XFireworks は
+
+	まさに季節もの
+
+となり,なかなか評判がよかったようだ.雑誌にもいくつか取り上げられた.
+XFireworks ができたのはちょうど花火大会まっさかりの時期だったので,
+忙しくて花火大会に行かなかった友人に紹介したりしたのだが,
+
+	夜に見てるとさみしい気分になる
+
+と言われてしまったのがかなしいところだ.作者自身,よく電車の中や昼休みに
+ぼーっと見ていたりしたのだが,はたから見たら,
+
+	ちょっとノイローゼ気味なのだろうか
+
+などと心配されてしまいそうである.単に作者自身は自分で作ったものを見て,
+
+	悦に入っているだけ
+
+だったのだが.
+
+この文書はあまり技術的なことは書いてないのだけれど,たまには技術的なことでも
+書こう.
+
+XFireworks はC言語でのオブジェクト指向な書き方が自分なりに身についてきた頃に
+書いた作品なので,ソースはとても(不満な点もいくつか残ってはいるが,
+それはそれとして,他のぼくのプログラムに比べたらはるかに)すっきりしている.
+X でのプログラミングがだいたいわかってきたころに書いたというのも
+よかったのだろう.おかげで他のぼくのプログラムにはありがちな,
+
+	「これはいつか直さなきゃならんなあ」
+
+とかならまだましだが,
+
+	「これはひどい,ひどすぎる」
+
+とか,とんでもないのになると,
+
+	「ちょっとこれは正視に耐えない」
+
+といったようなところもあまりないのがお気に入りの1作である.ちなみに正視に
+耐えないのは xstarroll である.次が xmangekyou かな.
+
+XFireworks は作りはじめて,1週間くらいでとりあえず動作するプロトタイプが
+できあがった.が,とにかく遅かった.花火が爆発するのが,
+
+	しゅわしゅわしゅわ...
+
+というように見えてしまうくらい遅かったのである.そこで,考えつく限りの
+チューニングを行なっていくことになる.
+
+原因は花火のカケラをひとつひとつ描画していたために X サーバに出すリクエストが
+ボトルネックになっていたためだった.これを解決するために,描画をまとめて行なう
+ようにリクエストを変更した.しかしまだ遅い.どうやら描画のたびに色を
+確保していて,これもまた X サーバにリクエストを出すためにボトルネックに
+なっているらしい.そこで,起動時に前もって色をすべて確保するようにした.
+これでだいぶ速くなったのだが,今度は起動に時間がかかるようになってしまった.
+Libretto で起動すると,起動に1分以上かかってしまうのである.原因は起動時の
+色の確保で,毎回 X サーバに色を確保しにいってしまうことにあったので,
+独自の色のデータベースを作成し,一度確保した色は使いまわすようにした.これで
+まただいぶ速くなったがまだ遅い.データベース作成時に,すでに確保している
+色かどうかのデータベースの検索に時間がかかっていたのだ.そこで検索処理に
+キャッシュやハッシュを使うようにした.これで多少速くなったのだが
+まだ遅いのである.と,一気に書いてしまったが,ここまでたどり着くのに
+くりかえし何度も何度も試行錯誤した.
+
+実際のプログラミングはほとんど Libretto で行なっている.ぼくの使っている
+Libretto は Libretto SS1000 というやつで,片道1時間半の電車通勤中に
+
+	電車の中でプログラムを書いて過ごすために
+
+入社直前に購入したものだ.しかし,買ったときに
+
+	すでにオールドモデルだった
+
+このため,XFireworks を書いていた時点ではかなり遅いマシンだったのだが,
+そのような遅いマシン(ちなみにこの文章を書いている2002年1月現在で,
+まだ現役まる3年である)でもちゃんと動作するようにしたかったため,可能な限り
+速くしたかったのだ.
+
+調べてみると,ハッシュ関数があまり乱数的でないために1部分に集中してしまい,
+
+	ぜんぜんハッシュになっていなかった
+
+という恥ずかしいバグがあったことがわかったので,ハッシュ関数を書き直した.
+さらに,ハッシュのチューニングを行なった.ハッシュの良いところは,サイズを
+自由に調整することによって,メモリサイズと速度のトレードオフを自由に調整
+できるところだ.これでだいぶ速くなった.
+
+この他にも,sin(), cos() をデータベース化してしまうとか,一度使った
+オブジェクトを削除せずにフリーリストにつないでおいて再利用することで
+malloc() の回数を減らすとか,配列はまとめて確保して malloc() の回数を減らす
+とか,など,考えつくかぎりのチューニングを行なった.
+このように考えつく高速化をすべて行なった結果,XFireworks はかなり速く
+動作するようになった.現在の速いマシンでは十分すぎるくらい速く動作するため,
+今となってはそれほどありがたみも無いのだが,やはり
+
+	高速化は,男の夢
+
+とでもいうのだろうか.しかし,最近の速いマシンで動かすとさくさく動きすぎて,
+
+	情緒もへったくれもない
+
+といったところがかなしいところではある.
+
+ただ,まだチューニングできる部分もある.そのうちのひとつとして,
+起動時の色確保で,色のデータベースはハッシュ&キャッシュ化しているために
+高速なのだが,色の名前の文字列のデータベースはふつうの線形検索になっている.
+ハッシュ&キャッシュ用のクラスをもっと一般化して,一般的なオブジェクトを
+扱えるようにして,色の名前もハッシュ&キャッシュ化すれば,起動がもうちょっと
+速くなるかもしれない.でもめんどくさいのでいいや.
+
+うーん,ひさびさに技術的なことを書いてしまった.
+
+2002/1
+(次回作の OMAKE.jpn に続く)
+
 ■■ WonX 開発秘話
 
 そもそもなんで WonderWitch をはじめたかというと,会社の先輩に紹介されたのだ.
@@ -31,10 +165,12 @@ WonderSwan 
 ものではない.画面まわりやキー入力用の独自のサービス関数がいっぱい用意
 されていて,それを使って書くことになるのだが,WonderSwan のハードウエアは
 さすがゲーム機,というか,スプライト機能やパレット機能を持っているので,
-昔のMSXの時代は普通だったのだが,今となっては特殊なハードウエアである.
-つまり,スプライトとかパレットとかをちゃんと理解できてないと,
-プログラムは書けないし,メモリの制限もあるし,プログラムサイズの制限もあるし,
-言語がCになったというだけで,実はその中身は,
+
+	昔のMSXの時代は普通だったが,今となっては特殊な
+
+ハードウエアである.つまり,スプライトとかパレットとかをちゃんと理解
+できてないと,プログラムは書けないし,メモリの制限もあるし,
+プログラムサイズの制限もあるし,言語がCになったというだけで,実はその中身は,
 
 	昔の MSX とかでの BASIC プログラミングによく似てる
 
@@ -72,6 +208,36 @@ FreeBSD 
 
 で,WonX 作るのが目的になってしまった.
 
+WonX 作っていて一番困ったのはなにかというと,技術的にどうとか
+MS-DOS と UNIX の差がどうとかではない.ホントに一番困ったのは,
+WonXってどんなものなのかを
+
+	人に説明すること
+
+である.
+わかる人には,
+
+	WonderWitch 用のプログラムを UNIX 上でコンパイル・リンクして,
+	X 上で実行できる実行形式を作成するための互換ライブラリ
+
+といっただけで,どんなものかだいたい理解してもらえる.しかし,わからない
+人には,いくら説明してもわからないものだ.
+
+2000年末から2001年初頭にかけて開催された,WonderWitch プログラミング
+コンテスト(WWGP)に出品して,見事予選を通過して,本選に出場してきたのだが,
+友人にそのことを説明(自慢)しようにも,
+
+「こんど,プログラムコンテストで予選通過したので,発表してくるんよ」
+「へー.なにを作ったの?」
+「えーと,WonderSwan のプログラムを作るための WonderWitch っていうキットが
+  あって,WonderWitch用のプログラムを...」(以下,必死に説明)
+「???」
+「うーん,つまり,プログラムを書くのを手伝うプログラム」
+
+こんな説明しかできないのは,うーん,残念である.
+
+(次回作の OMAKE.jpn に続く)
+
 ■■ N.A.D.A.R. 開発秘話
 
 N.A.D.A.R. は,そもそもは中学生のときに,「TANK」という名前で作った,
@@ -161,7 +327,7 @@ String 
 
 というようにはまってしまい,あげくのはてには,
 
-	整数までも,Integer クラスで管理しそうな勢い
+	単なる整数までも,Integer クラスで管理しそうな勢い
 
 になって,収拾がつかなくなってしまう.
 また,クライアントが複数になったときには,サーバ側では fork() して通信の
@@ -225,6 +391,10 @@ N.A.D.A.R. 
 
 	「TANK」はやめよう
 
+ということになった.また,
+
+	「エックスなんちゃら」という名前もやめよう
+
 ということになった.
 
 戦車の重みを表現したいので,「グロブダー」のように,濁音のある名前にしたい.
@@ -248,7 +418,7 @@ N.A.D.A.R. 
 
 このときは,あまり深く考えてなくって,けっきょくこの日には決まらなかった
 のだが,このときにしっかり決めなかったのがよくなかった.
-そのうち開発を進めるうちに,ファイル名とかも整理しだして,
+そのうち開発を進めるうちに,ファイル名とかドキュメントとかも整理しだして,
 
 	ほんとにもういいかげん名前を決めたい
 
@@ -265,6 +435,8 @@ N.A.D.A.R. 
 
 だめだ,Dのあたりでなんにもおもいつかん.
 
+(次回作の OMAKE.jpn に続く)
+
 ■■ EyeClock 開発秘話
 
 そもそもなんで EyeClock を作り出したかってはなし.
@@ -528,13 +700,20 @@ EmiClock 
 
 のために,家計簿だとか,社員の定期券の期限の計算用プログラムとかの
 プログラミングをしていく,という内容だった.
+しかし,なんというか,今思うと,
+
+	すごい名前だ
+
 ちなみにアイコさんはマイコさんの妹で,アイコさんはショートカットの OL で,
 ロムさんはマイコさんが好きで,ラムさんはアイコさんが好き,という設定だった.
-しかし,
+ぼくは,長女系のマイコさんより,次女系のアイコさんのほうが好きだったなあ.
+
+この本で気になったのは,キーボードを叩くときの効果音が,
 
-	今思うと,すごい名前だ
+	ピッピッ
 
-ちなみにぼくは,長女系のマイコさんより,次女系のアイコさんのほうが好きだった.
+なのである.キーボードを叩いたときに,ピッピッなんて音がするパソコンなんて
+ないよなあ,と子供ながらに思ったことを記憶している.
 
 この本は BASIC をあるていど知っていることを前提にしていて,
 実際にプログラムを書いていく,という内容だったので,まったくの初心者の
@@ -550,6 +729,12 @@ EmiClock 
 
 が,名機 PC-8001 を使って,「先生」と「ネコちゃん」といっしょに,
 コンピュータの仕組みや,プログラムの書き方を勉強していく,という内容だった.
+しかし,なんというか,この本の登場人物も,
+
+	コテコテの名前
+
+で,苦笑してしまう(だって「マイちゃん」と「コンちゃん」だよ).
+昔はこういうのが多かったもんだ.
 この本はとてもわかりやすくて,
 
 	データバスやアドレスバスやコントロールバスや ROM や RAM や
@@ -622,7 +807,7 @@ Syntax Error 
 この苦労(?)のおかげで,いま思えば,フリーソフトウエアプログラマにとって
 もっとも重要な力である,
 
-	どんなエラーが出ても,自力でなんとかする気力
+	どんな問題が起きても,自力でなんとかする気力
 
 が身についたと思う.
 
@@ -633,11 +818,8 @@ Syntax Error 
 
 という本だった.この本は残念ながら,どこかへいってしまった.
 うーん,もう一度,読んでみたいものである.
-「あるけあるけゲーム」(tron のようなゲーム)とか,
-「スクロールジャンプ」とか,
-「ビルディングクラッシュ」とか,
-「地底探検ゲーム」とか,
-ペンゴもどきとか,
+「あるけあるけゲーム」(tron のようなゲーム)とか,「スクロールジャンプ」とか,
+「ビルディングクラッシュ」とか,「地底探検ゲーム」とか,ペンゴもどきとか,
 月面着陸とかを打ち込んでは遊んでた.
 この本は当時はやりの,
 
@@ -660,7 +842,7 @@ Syntax Error 
 そのうち打ち込んだゲームを適当に改良したりするようになる.
 
 やがて,自分でもゲームを作り出すようになる.
-はじめて作ったゲームは,いまでも覚えているが,
+はじめて作った記念すべき1作目のゲームは,いまでも覚えているが,
 
 	「レーザーパックマン」
 
@@ -701,7 +883,8 @@ Syntax Error 
 170 LOCATE 10,0:PRINT S
 180 GOTO 20
 
-たしか,こんなんだったとおもう.(なにしろ,はじめて書いたプログラムですから)
+なにしろはじめて書いたプログラムなので,相当無駄な書き方がされていたはずで
+ある.そのへんも極力再現してみたが,こんなんだっただろうか.
 確率的に,敵が左上のほうに行きやすくなってしまったというのをおぼえている.
 
 	こんなんおもしろいのか?
@@ -748,7 +931,7 @@ Syntax Error 
 
 	円周率を10万桁まで計算するプログラム
 
-を作った記憶がある.しかも,
+を作って提出した記憶がある.しかも,
 
 	計算の途中経過をセーブすることができる
 
@@ -847,7 +1030,16 @@ X 
 
 に,すっごく影響を受けている.
 
-■ そのほか
+■ プログラミング
+
+「GNU ソフトウエアプログラミング」
+
+プログラミングに emacs, gcc, make, gdb を使うときの一連の流れが
+わかるので,とってもいい本だと思う.
+個々のアプリケーションをひとつひとつ詳しく解説してある本はたくさん
+あるのだが,開発の一連の流れとして解説してある本は,なかなか少ない.
+
+■ システム管理
 
 「スーパーユーザの日々」
 「UNIX ネットワークの日々」
@@ -871,20 +1063,20 @@ X 
 
 	セリフ付
 
-ということをしていて,朝,研究室に入ってくる卒研生とかが,
+ということをしていた.
 
-	スーパーユーザーが,学芸会のセリフの練習でもしているかのような姿
+	「え,こうすればいいんじゃないんですか? 中村さん」
+	「それは違うよ,K君.これはこれこれこうだから,こうするんだよ」
+	「なーんだ,同じUNIXでも,HPとSUNではずいぶん違うんですね」
 
-をまのあたりにして,ギョッとしていた.
+というようなセリフを言い合うわけである.(実話)
+て,朝,研究室に入ってくる卒研生とかが,
 
-「セキュリティの日々」とかも,出してほしいもんだ.
+	スーパーユーザーが,学芸会のセリフの練習でもしているかのような姿
 
-「GNU ソフトウエアプログラミング」
+をまのあたりにして,ギョッとしていた.(これも実話)
 
-プログラミングに emacs, gcc, make, gdb を使うときの一連の流れが
-わかるので,とってもいい本だと思う.
-個々のアプリケーションをひとつひとつ詳しく解説してある本はたくさん
-あるのだが,開発の一連の流れとして解説してある本は,なかなか少ない.
+「セキュリティの日々」とかも,出してほしいもんだ.
 
 「よしだともこのルート訪問記」
 
@@ -898,8 +1090,10 @@ X 
 非常に幅広く紹介されていて,とてもためになる.
 というのは,コンピュータやネットワークのシステムの構成など
 (こういったことも非常にためになるが)が書いてあるだけでなく,
-「管理者の人材確保」や「管理者の育成・教育態勢」がどのようになって
-いるかなどが書かれているからだ.
+
+	「管理者の人材確保」や「管理者の育成・教育態勢」
+
+がどのようになっているかなどが書かれているからだ.
 やはり,「人材の確保」と「教育」がいちばん大変で重要なことであって,
 こういったことが,システム管理の実態だと思う.
 
@@ -994,4 +1188,732 @@ X 
 書き出してしまうような人間はともかく,普通の人は,やはり人目は気になる
 (のだと思う)からだ.
 
+(次回作の OMAKE.jpn に続く)
+
+■■ 電車で書くプログラム
+
+ぼくは通勤に片道1時間半かかるのだが,この時間は貴重なプログラミングの
+時間になっている.もともと就職するときに,ずいぶん遠くにある会社だけど,
+まあ,混まない方向だし,ずっとプログラム書いてればいいか,とおもって就職を
+決め,就職前の2月に Libretto SS1000 を購入し,ほんとに車内で書くようになった.
+
+東急田園都市線の反対方向に乗っているので,行きも帰りも必ず座れる.天気の
+いい日は通勤中にもかかわらず,
+
+	玉川でついつい降りたくなってしまう
+
+一応,降りたことはないけどね.
+
+帰りは渋谷乗り換えなのだが,調子に乗って書いてると,ノリにノッてきて
+
+	渋谷をそのまま乗り過ごした
+
+ということが何度かある.また,あまりにノッていると,渋谷で乗り換えた後も,
+続きを書きたいという欲求を抑えることができずに,
+
+	山手線の中で,立ってプログラムを書いた
+
+ということも何度かある.XFireworks の一部分のコードは,山手線で立って書かれた.
+
+EyeClock や N.A.D.A.R. や XFireworks や WonX のコードの大部分は,こうやって
+電車の中で書かれた.今思えば,
+
+	ずいぶん書いたものだ
+
+田園都市線の車両は,何種類かある.その中でも旧式なのだろうか,車両の端の席に,
+肘をかけられるくらいの出っぱりがある車両がある.これは,いい.出っぱりの
+上に Libretto と飲物を置いて,優雅に書くことができる.出っぱりがない車両だと,
+膝の上に Libretto を乗せて書くことになる.
+
+(次回作の OMAKE.jpn に続く)
+
+■■ モバイルについて
+
+ノートパソコンやモバイルについて思うことなんだけど,もしもモバイルと
+いうならば,やはり,
+
+	本当に持ち歩けること
+
+というのが,絶対条件だと思う.のだが,
+
+	本当に持ち歩けるの?
+
+と疑問になってしまうような製品が多々あると思う.
+たとえば,いくら軽くて小さくて高性能だとしても,22万円もするようなノートPCを
+そのまま,
+
+	無造作にバッグにぽんと入れて
+
+気軽に持ち歩くことができるだろうか.(ぼくはできない)
+だから,高価な製品は,それだけで(モバイルとしては)ダメだと思う.
+もっと安っちくて,落としても無くしても置き忘れても,(それほど)ショックが
+少なくて,古くてぼろくて傷だらけで,
+
+	だれも盗もうなどと思わないくらいのマシン
+
+が,モバイルとしては最適だと思う.
+
+重量は,可能な限り軽いほうがいい.1kgを超えると常に持ち運ぶのが苦痛になる.
+また,電源アダプタも小さいほうがよい.実際に持ち歩くと,大きさよりも
+重さのほうが気になるので,小さいことよりも軽いことのほうが重要た.
+
+インターフェースは,PCカードスロットが1つあれば十分である.データのやりとりを
+するのは,LANカードかコンパクトフラッシュが現実的である.USBはあるにこした
+ことはないが,それによって高価になったり重くなったりするくらいなら,
+無くてよい.そもそもUSBがあったとしても,どうせつなぐのは
+
+	キーボードかマウス
+
+くらいのものである.そもそもモバイルでマウスを使いたいなんて欲張っても
+しょうがない.
+もしかしたら,
+
+	フロッピードライブか CD-ROM ドライブ
+
+をつなぎたいかもしれない.
+しかし,モバイルの場合には,このような,
+
+	ふだん絶対に持ち歩かないもの
+
+のことを考えてはいけない.機能を限定して,軽く,持ち運びやすく,
+いつでもどこでもがモバイルのウリなのだから,あれも使いたいこれも使いたいと
+言い出したら,なんのためにモバイルを使うのか,本末転倒になってしまう.
+だから,
+
+	PCカードスロットだけで十分
+
+なのである.
+
+モバイルでいちばん気になるのは,結局のところ,
+
+	1に値段,2に重量,3にバッテリのもつ時間
+
+である.値段というのは買うときに高い安いということではなく,
+前述したように,高価なものは気軽に持ち歩けないという意味である.
+
+OS に関しては,(ひいき目なしで)FreeBSD か Linux が最適だと思う.
+
+たとえば Windows だと,出先でちょっと PC カードタイプの LAN カードを
+借りて使いたいというときに,ドライバが入っていないとどうしようもない
+ということにおちいりがちである.たぶんインターネットに接続できるパソコンを
+借りて,ドライバをダウンロードして,コンパクトフラッシュ経由でモバイル側に
+もってってインストール,という,まあ,あまり考えたくないような,
+
+	とても面倒なこと
+
+になる.
+インターネットにつながってるPCやコンパクトフラッシュやコンパクトフラッシュが
+使えるノートパソコンがなかったときのことなど,もう,
+
+	想像もしたくない
+
+出先で借りものの LAN カードを使うこともできないなんて,これでモバイルと
+言えるのか? ぜんぜん実用的じゃないじゃん,と思う.
+
+FreeBSD や Linux なら,はじめから GENERIC なカーネルを作っておけば,
+たいていのPCカードは指しただけでそのまま使える.指しただけで使えなかったと
+しても,カーネルをコンパイルしなおせば,ほとんどのカードがまず使える.
+
+モバイルでは,出先にもっていって使うことが多いので,出先でPCカードを
+ちょっと借りる,ということはとても多い.逆にいえば,もしも出先で借りることが
+できるなら,余分な PC カードを常に持ち歩かなくてもよい,ということになる.
+
+また,FreeBSD や Linux では,X のデスクトップ環境をカスタマイズすることで,
+マウスをほとんど使わないようにカスタマイズすることができる.
+Libretto では,液晶ディスプレイのとなりについてるぐりぐりしたやつで
+マウスを操作することになる.しかしぼくの場合,Window Manager をカスタマイズ
+することによって,ほとんどマウスを使わずに作業できている.
+Windows で使用することなど,想像もしたくないものである.
+
+さらに,OS やアプリケーションの軽さの問題がある.前述したように,
+モバイルはできる限り安っちくてロースペックなマシンのほうがよい.
+だから,マシンは,Pentium MMX 166MHz の RAM 32MB とかでもいいし,
+もっとロースペックでもいい.しかし,たとえこれでも,アプリケーションは
+あまり問題なく動いてくれないと困る.(モバイルなので,サクサクと動けとは
+言わないけど,不安定で落ちまくったりするのは困る)
+あるアプリケーションを動かすためだけに,高価なメモリを32MBも追加増設する
+なんて,非常に無駄なことである.こんなことをしていたら,けっきょくどんどん
+高価になっていってしまう.とにかく高価なものは持ち歩きたくないというのが
+ぼくの信条だ.値段が高いものを買うのが嫌というよりも,持ち歩くのが嫌なのだ.
+
+あとは,インストールのしやすさの問題だ.モバイルだとCD-ROMドライブが無い
+(あっても別売り)とか,フロッピードライブが無いということが多いので,
+インストールが困難な場合が多い.FreeBSD や Linux ならば,ネットワーク
+インストールや Windows 側にファイルを置いておいてインストールなど,
+多彩な方法をとることができる.
+
+最後に意外に重要なのが安定性の問題だ.というのは,プレゼンに使用することが
+あるからだ.(プレゼンをやらないならばあまり関係ないけど)
+いざプレゼンをやろうとしたら真っ青な画面になってしまい,結局資料無しで
+プレゼンを進める,というのを何度か見たことがある.
+なんというか,悲しいというか,せっかく昨日徹夜して資料作ったのだろうに,
+と思う.
+(プレゼンに資料をまったく作って来なかったのと同じだと個人的には思っている)
+こんなことで10分間のプレゼン中に,再起動に(ロースペックだし,ファイルシステムの
+チェックもするので)3分間もかかっていてはかなわない.
+UNIX には満足のいくプレゼンツールが無いと言われるかもしれないが,
+きれいな画面でちょこまかした(たいていあまり意味の無い)アニメーションを
+見せたり,プレゼン画面にきれいな背景があったりすることのほうが,
+いざプレゼンというときに,OSがまったく動かないことがあるということよりも
+重要なのだろうか,と思う.説明したいことをテキストファイルに書いておいて,
+less でテキストファイル見せながらしゃべればいいんじゃないの? と思う.
+X を起動する必要すらあまり無いと思う.
+図を見せたいならばXの仮想画面を何枚か用意しておいて,別の仮想画面に
+適当な画像ビューワで画像を開いておいて,仮想画面を切替えるのがいちばん確実だ.
+字が小さければ,でかいフォントを使えばいい.
+ブラウザの不安定さがちょっと心配だが,HTML で書いておいてブラウザで見る,
+という方法もある.これだと資料をそのままホームページに張り付けることも
+できるし,画像も使えるし,フォントのサイズも自由に選べる.
+
+ぼくの経験だと,いっしょうけんめい文字をスライドさせたりフェードインさせたり
+箇条書の項目が順番に出てきたり,意味もなく凝ったアニメーションとかやっている
+プレゼンほど,あまり内容が無かったりするものだ.(これは,ほんとうにそうだと
+思うね)
+シミュレーションの結果の発表とかで,ほんとに動くものを見せようとして,
+アニメーションをやっているのならいい(そういうアニメーションは,むしろ歓迎)
+のだけれど.まったく意味の無いアニメーションってホント,多い.(しかもそれを
+見てプレゼンがうまいとかきれいとか,(たとえ社交辞令にしても)褒める人が
+いるのだから困ったものだ.内容はどうだったんじゃいと突っ込みたくなる)
+ほんとにプレゼンのうまい人や経験のある人は,でかい字でキーワードだけ
+箇条書にして映し出させて,あとはそのキーワードを見て思い出しながら
+しゃべったりする.プレゼンって,自分が今までやってきた,自分が一番よくわかって
+いることを発表するのであるから,これがあたりまえであるとも思う.
+(長々とした文章が小さい字で画面いっぱいに映し出されたと思ったら,発表者は
+ その文章を読むだけ,というプレゼンがたまにあるけど,なんというか,経験を
+ つんでくれ,と思う)
+だから,プレゼンなんて,less と xv が使えれば十分である.なんかプレゼンの
+話,というか,愚痴になってしまったなあ.
+でもせっかく書いたのを消すのももったいないし,まあいいか.
+
+(次回作の OMAKE.jpn に続く)
+
+■■ ゼビウスについて
+
+いきなりだが,ゲームの話である.
+
+むかしむかし大昔,ゲームセンターのゲーム(いわゆるアーケードゲーム)の黎明期に,
+
+	XEVIOUS
+
+というゲームがあった.「ゼビウス」と読む.
+縦スクロールタイプのシューティングゲーム,というと説明は簡単なのだが,
+その斬新な構図と演出で,一世を風靡したゲームである.レバーで自機を操作して,
+空中攻撃弾(ザッパー)と地上攻撃弾(ブラスター)で敵を攻撃しつつ,エリアをクリア
+していく,というゲームである.エリアは16エリアまであって,16エリアをクリア
+すると,7エリアに戻る.全機がやられない限りは,延々とループするわけだ.つまり,
+
+	ゲームクリアというものが無い
+
+というゲームである.
+
+XEVIOUS には,カウンターストップというひとつのステータスがある.
+カウンターストップ,通称「カンスト」とは,
+
+	9999990点
+
+のことである.ここまでいくと,これ以上点数が上がらなくなるのだ.これが
+「カンスト」である.これができるプレイヤーのことを,「カンストプレイヤー」
+とか,「1000万点プレイヤー」とか言ったりする.
+と,口で言うのは簡単だが,カウンターストッププレイヤーがどれくらいの
+ものかというと,
+
+	ゲームをしている後ろに人だかりができてしまう
+
+というくらいのものすごい実力なのである.(ちょっと言いすぎ)
+
+XEVIOUS は標準の設定だと,60000点で1機増える.カウンターストップさせるくらいの
+実力になると,画面最下に,
+
+	自機の残りがずら~~~っと並んでいる
+
+ということになる.そういえば,むかしそんな状態になっていたときに,
+後ろを通り過ぎていった人が,「すげえうまいよこの人」と言ったあと,
+
+	「あんなにボムが残ってる」
+
+と言ってたことがある.ボムではなくて自機なんだけどなあ.
+
+1000万点までいくのにどれくらい時間がかかるかというと,
+ぼくがはじめてカウンターストップさせたときは,午後の1時半から始めて,
+
+	7時間半かかった
+
+夜の9時までやっていたわけである.目安としてははじめのうちは1時間で
+100万点なのだが,だんだんステージを過ぎていくと,点数が上がってくる
+ようなので,少しずつ効率がよくなってくるのである.
+XEVIOUS は昔のゲームなので,当然,continue などは無いわけである.だから,
+
+	100円玉一枚で
+
+これだけ粘らなければならない.
+このあいだ,食事もとらず,トイレにもいかず,である.昼間のゲームセンターは
+学生が多いのだが,だんだん社会人が増えてきて,
+
+	客層が移り変わっていくのがわかってしまう
+
+1時間くらいの時間がちょっとできたとき,暇つぶしにプレイすることがたまにある.
+こんなときはカウンターストップさせるほどの時間は無いわけであるから,
+適当な時間でわざとやられて GAME OVER にするわけであるが,このようなときは
+そのまま GAME OVER にしてはいけない.そこで力尽きたと思われてしまうからである.
+必ず,
+
+	100万点
+
+とか,
+
+	99万9990点
+
+にそろえなければならない.これもカウンターストッププレイヤーのひとつの
+プライドである.このように点数をそろえることによって,ネームエントリーに,
+
+	おれはほんとはもっと先までいけたんだけど,わざとここでやめたんだぞ
+
+というメッセージを残しておくわけだ.
+このためには,トーロイドは30点,ゾルバグは100点,テラジは600点,
+ギドスパリオは10点,ザガートは150点,流れザガートは100点,などというように,
+敵機や地上物の点数まで正確に把握しておいて,
+
+	点数を調整しながらプレイする
+
+というくらいの実力が必要である.
+だから,XEVIOUS のハイスコアランキングを見たときに,
+
+	1234560点
+
+とかになっていたとしたら,ああ,さっきまですごいプレイヤーがプレイして
+いたんだな,と理解しなければいけないのである.
+
+慣れてくると,1000万点いくのにかかる時間もだんだん短縮されてくる.
+機数に余裕があれば,
+
+	得点の高いエリアでわざとなんどもやられる
+
+(9エリアとかだ)とか,ジェミニ誘導という高等技術を使って,短時間で得点を
+かせぐことができるようになるからだ.エリアの途中でやられると,エリアの先頭に
+戻るので,同じエリアをなんども繰り返せるのだ.
+
+しかし,それでも最低4時間くらいはかかる.そこで,XEVIOUS をやるとき,
+100円玉を入れる前には,
+
+	それなりの心構えが必要になる
+
+ここでその心構えについて書こう.
+
+まず,重要なのは椅子だ.ゲームセンターの椅子は座りごごちがあまりよくない
+ものが多いが,2種類の椅子があるゲームセンターは多い.できるだけ座りごごちの
+良い椅子を持ってきて使う.背もたれつきのものがあれば,なるべくそれを使う.
+ここで,
+
+	椅子を持ってくるのなんて恥ずかしい
+
+とか,
+
+	椅子なんてなんでもいいや
+
+などと思ってはいけない.これからその椅子に何時間も座るわけであるから,
+椅子は重要な要素なのだ.
+
+飲物は,必ず用意したほうがよい.プレイ前にどんなに喉が渇いていなくても,
+
+	3時間もやっていれば必ずなにか飲みたくなってくる
+
+しかし,飲物は大量に飲んではいけない.トイレが近くなるからだ.
+
+	ちょっと唇を濡らす程度に
+
+ちびりちびりと飲むようにする.
+プレイ中には甘いものが欲しくなってくるので,オレンジジュースなど,なるべく
+あまったるい飲物を選んだほうがよい.コーラなどの炭酸飲料は
+
+	気が抜けてしまうことも考えなければならない
+
+のである.
+
+食糧も準備したほうがよい.プレイ中は甘いものが欲しくなってくるので,
+ひと粒チョコやキャンディーのように,簡単に口に入れられるものをポケットに
+大量に用意しておくようにする.ゲームセンターに灰皿があれば,持ってきておく.
+これは,チョコレートの包み紙をまとめておくためだ.
+
+問題は,トイレだ.
+プレイ前には,どんなにトイレに行く必要は無く感じても,必ず行くようにする.
+これは行かないと,ほんとうに絶対に後悔する.
+
+しかし,上級プレイヤーになってくると,
+
+	プレイ中にトイレに行くことができる
+
+ようになる(実話).機数が半減してしまうのを承知の上で,ゲーム中にトイレに行って
+しまうわけだ.
+7エリアは,はじめにバキュラの応酬があるので,ほっておいてもやられにくい.
+後ろに人だかりができているとき,プレイの合間に,悠々と
+
+	缶ジュースなどをちょっと買ってこれる
+
+ようになれば,上級プレイヤーといえるだろう.(これも実話)
+
+だれも信じてくれないのだが,両腕を交差させてプレイしたことがある.
+XEVIOUS はあまり点数をとりすぎると,それ以上プレイできなくするように,
+レバーやボタンが突然入れ替わったりすることがある.(そういう設定ができるらしい)
+以前,あるゲームセンターでやっていたところ,400万点ほどのところで,
+
+	いきなり操作不能になった
+
+これは噂のボタン入れ替わりかとおもっていろいろいじってみると,
+
+	レバーが1プレイヤーと2プレイヤーで入れ替わり,
+	空中弾(ザッパー)が撃てなくなっていた
+
+昔のテーブルタイプの匡体だったら,プレイを続行するのは難しかっただろう.
+たとえ反対側に行って2プレイヤー用のレバーで操作したとしても,
+画面は1プレイヤーのほうを向いているわけだから,動きが逆向きになるからである.
+ところが,この時代の匡体は,ストリートファイター2が既にあった時代で,
+2人が並んで対戦プレイできるタイプの匡体であった.
+匡体の操作パネルは,こんなかんじだ.
+
+	1Pレバー               1P START   2Pレバー
+	  ●    1P地上攻撃ボタン  ○        ●    2P地上攻撃ボタン
+	    \        ○          ○          \        ○
+	          ○           2P START             ○
+	    1P空中攻撃ボタン                  2P空中攻撃ボタン
+
+つまり,2プレイヤー用のレバーはすぐとなりにあるわけだ.しかし,地上攻撃
+(ブラスター)の発射ボタンは1プレイヤーのままで変わっていない.
+そこで,
+
+	左右の腕を交差させて,左手で2Pレバーを操作して,右手で1P用の
+	地上攻撃ボタンを押す
+
+ということになった.しかも,ザッパーが発射できないので,
+
+	空中の敵は,撃てない
+
+という苛酷な状況である.
+しかし,こんな状況でも,なんとか1時間くらい粘って,最終的には600万点くらい
+までいった.しかしこれを後輩に話したら,
+
+	話作んないでくださいよ
+
+とつっこまれてしまった.実話なんだけどなあ.
+
+うーん,マニアックなネタになってしまった.
+
+(次回作の OMAKE.jpn に続く)
+
+■■ テトリスについて
+
+テトリスにもカウンターストップがある.レベル99,ライン999,スコア999990点,
+というのが,それである.ぼくは,1度だけ,テトリスをカウンターストップ
+させたことがある.もちろん,
+
+	100円玉1枚
+
+でだ.
+テトリスのカウンターストップは,だいたい1時間半くらいでできる.しかし,
+XEVIOUSに比べて,はるかに難しいと思う.というのは,テトリスというのは
+いちばん上まで積まれたらそれで終わりなわけであるから,プレイ中にちょっとでも
+気を抜こうものなら,
+
+	その瞬間にゲームオーバーになってしまう
+
+つまり,1時間半という時間の間,集中力を切らさずに持続させる必要があるのだ.
+XEVIOUS では,7エリアのバキュラの応酬や,9エリアのシオナイト,
+11エリアの先頭付近など,気を抜ける場所が何箇所かある.ちょっと息抜きに
+なにか食べようかとも思うものである.しかし,テトリスでは,
+
+	プレイ中にキャンディーの包みをほどく,なんて暇はない
+
+まあそこまでいうと大げさで,実際にはチョコレートの包みをほどいたり,
+飲物をちょっと飲むくらいできるが,基本的には腹が空こうが喉が渇こうが,
+
+	1時間半我慢する
+
+というプレイを要求されるわけである.
+
+テトリスも,上級レベルになるといろいろな技を使えるようになってくる.
+階段状になっている一番高いところにブロックをいったん置いて,徐々に落として
+時間を稼ぐ「階段落とし」とか,一見スキマができてしまうような置きかたに
+見えるのだが,実はラインがうまく消えてくれて,スキマは無くなる「入れ消し」,
+などというのがよく使われるテクニックである.しかし,これぞ上級者のテクニックと
+いうならば,それはやはり「回転入れ」だ.
+
+	      □□□
+	        □
+	
+	■■■■    ■■■■
+	■■■■    ■■■■
+	■■■      ■■■■
+	■  ■■■■■■■■
+
+とか,
+
+	        □□
+	      □□
+	
+	■■■    ■■■■■
+	■■■      ■■■■
+	■■■    ■■■■■
+	■■■■■■■  ■■
+
+とか,
+
+	        □
+	        □
+	        □□
+	
+	■■■■    ■■■■
+	■■■■      ■■■
+	■■■■      ■■■
+	■■  ■■■■■■■
+
+とかを入れてしまうテクニックだ.
+レベル99でブロックがガンガン落ちてきている状態で,
+
+	      □□□□
+	
+	■■■■    ■■■■
+	■■■        ■■■
+	■■■■    ■■■■
+	■■■■■  ■■■■
+	■  ■■■■■■■■
+
+のようなのを「回転入れ」と「入れ消し」でうまく入れたりすると,
+
+	ギャラリーが寄ってくる
+
+かもしれない.
+
+うーん,これもマニアックなネタになってしまった.
+
+(次回作の OMAKE.jpn に続く)
+
+■■ ソースコードを公開することについて
+
+Windows のフリーソフトとかで思うことなのだが,ソースが添付されてないものが
+多い.というか,添付されてないのが普通である.これがぼくには不思議で
+たまらない.なぜソースコードを添付しないのだろうか,と,ついつい理由を聞きたく
+なってしまう.
+もしもそれが,「どうせソースコードを添付したって,だれも見ないだろう」とか,
+「普通の人はコンパイラなんてもってないから,ソースを添付する意味は無い」
+などという理由なのだとしたら,それは大きな間違いだ.
+
+まず,ソースが添付されていた場合に,それを見るか見ないかという話であるが,
+実際のところ,見る人は少ないだろう.しかし,見る人は見る.見る人は必ずいる.
+
+(次回作の OMAKE.jpn に続く)
+
+■■ FreeBSD について
+
+ぼくのいままでのコンピュータ歴の中で一番大きかったことは,FreeBSD との出会い
+だったと思う.FreeBSD のなにが素晴らしいかと言うと,一言で言うならばそれは,
+
+	開発環境がある
+
+ということだ.これは
+
+	作ることができるOS
+
+ということである.いろいろな意味で,である.
+
+Cコンパイラは標準で(正確には GNU の成果物である)ついてくる.emacs や make,
+gdb などの素晴らしい開発環境もついてくる.動作するアプリケーションは,
+たいていソースコードフリー(自由,という意味のフリーである)のものである.
+これはぼくのような,
+
+	まさに作ることがだいすきな人間
+
+には,たまらない素材だ.「作る」ための材料や道具,資料がそこらじゅうに
+いっぱいなのである.
+いちばんうれしいのは,作るためのネタというか,「きっかけ」に満ちあふれて
+いることだ.だから,目の前に FreeBSD マシンが1台あるだけで,まったく飽きない.
+ネタはいくらでもあるので,1日中ずっと調べ,試して,作ることができる.
+(ちょっといいすぎか?)
+
+とはいっても,はじめからそこまでわかってて使いはじめたわけではない.
+使っているうちに,そういったことがだんだんとわかるようになり,それが自分に
+マッチしていたためにさらに深く使うという好循環(悪循環?)で,どんどん深みに
+はまっていったわけである.自分がモノ作りが好きだということをわからせてくれた
+OS でもある.(それまでもいろいろと作っていたが,無意識で作っていたと思う)
+
+FreeBSD が無かったら,今こんなにコードを書いてはいないだろう.カーネルや
+デバイスドライバに興味を持つことも無かったかもしれない.しかし,FreeBSD なら
+いくらでも自分で作ることができるわけだから,モノ作り大好き人間にとって,
+こんなに興味をそそり,刺激を受ける素材はない.
+
+実際のところ,FreeBSD はいい OS であり,いい開発環境である.そして僕自身にも
+合っている.今後もずっと使い続けていくだろう.
+
+しかし最近,ぼくの中ではその対抗馬が出てきている.それは NetBSD だ.
+
+FreeBSD と比べて NetBSD は何が違うのかというと,ぼくにとっては,
+
+	おもしろいOSである
+
+ということである.それは NetBSD のソースの sys/arch の下で ls をするとわかる.
+NetBSD が移植されたマシンのディレクトリが延々と出てくるのだ.
+
+NetBSD が面白いと思いはじめたきっかけは,カーネルを見たりいじったりするように
+なってからだ.パームコンピュータやモバイルなどを見たとき,FreeBSD は
+(移植すれば別であるが,今のところはまだ)動かないだろうと思う.しかし,
+NetBSD は動くことが多い.たとえ動かなくても,誰かが移植するかもしれない.
+たとえ誰も移植しなくとも,自分ももっと勉強して力をつければ,将来は自分で移植
+できるかもしれないという夢がある.携帯電話やカーナビだってそうだ.
+だから,ぼくにとって NetBSD は「夢のあるOS」だ.
+
+そういう意味で,Linux も夢がある.ぼくが Linux をあまり使わない(カーネルの
+ソースを読むことはあるが)のは,単にはじめに FreeBSD から入って,その流れで
+NetBSD を読んでいるからだが,あまり使ってないのはちょっと残念な気もする.
+
+NetBSD にも弱点はある.NetBSD の場合だと,使う人 = 作る人 という意味あいが
+強いので,ユーザ環境は FreeBSD や Linux ほどには整備されていないように感じる.
+そんなわけで,使うには FreeBSD,作るには NetBSD が自分にとっては最適だと
+思っている.
+
+ぼくがはじめて FreeBSD と出会ったのは,大学4年で研究室に配属されたときだ.
+当時研究室には HP-UX のマシンが数台と,FreeBSD の入った AT 互換機が数台,
+MS-DOS の入った PC-9801 が数台あった.以前は HP-UX のマシンをメインとして,
+PC-9801 から telnet して計算を走らせるみたいな使いかたをしていたようだ.
+ぼくがいた部屋には FreeBSD マシンは2台しかなく,HP-UX よりも高速で軽かった
+ため人気があり,ぼく自身あまり使うことはなかった.そもそも大学4年のときは,
+C言語の勉強に注力していたため,UNIX というものをあまりしらなかった.login
+しても,
+
+	自分のホームディレクトリ以外の部分は見たことが無かった
+
+というくらいである.自宅に PC-9801 があり,当時はそちらをメインで使っていた
+ために,UNIX も C 言語を書くためのプラットホームとしてしか使っていなかった
+のだ.
+
+そんなわけで UNIX についてほとんど知らないまま修士1年となった4月のこと,
+当時の研究室のシステム管理者だった N さんに言われた.
+
+	坂井君,スーパーユーザーをやってくれない?
+
+UNIX をまったく使えない人間としては「スーパーユーザー」なんていう,
+
+	いかにも特権階級のような
+
+言葉の響きは魅力的であり,なにも考えずに引き受けた.そして初めての仕事が,
+
+	とりあえずこのマシン好きにしていいから,
+	FreeBSD を入れてみてくれない?
+
+である.UNIX のことは login の仕方しか知らず,AT 互換機のことはほとんど知らず,
+ネットワークのことは ftp と telnet と rlogin の使いかたしか知らない,という
+状態のぼくに,http://www.jp.freebsd.org のアドレスだけ教えて,
+
+	インストールからネットワークの設定まで
+
+いきなりすべてやらせようというのであるから,今思うと,
+
+	なんて無茶な方法だ
+
+と思ってしまう.
+
+こうして初めての FreeBSD との取っ組み合いが始まったわけである.
+
+2002/1
+(次回作の OMAKE.jpn に続く)
+
+■■ カーネルについて
+
+カーネルのソースを読むことは楽しい.最近は PowerPC のアセンブラが(少しだけ)
+わかるようになってきたので,さらに楽しくなった.
+
+カーネルの勉強をしてみたいんだけど,
+
+	なにから手をつければ良いかわからない
+
+という人は多いと思う.実際,ぼく自身もそういう時期があった.ここで,ぼくなりの
+カーネルの読みかたを,無謀にも書いてみようと思う.とはいってもぼく自身,
+それほどよく読んでいるというわけでもないし,まだまだ入門者の域を出ていない.
+しかもぼくの場合,読むのはブートローダー,ブートストラップ(それも一番はじめの
+ほう)とデバイスドライバが主(ていうかそれ以外はあまり読んだことが無い)で
+あるので,偏った話になると思う.参考までに読んでもらえればと思う.
+
+カーネルにしてもブートローダーにしても,まず,どこからはじまるのかを
+知りたい人は多いだろう.カーネルやブートローダーの場合には,main() 関数から
+始まるというわけではない.だから,
+
+	grep main *
+
+とかしても無駄である.多くのばあい,アセンブラのコードのどこかに
+startup: のようなラベルがあり,そこから始まるようになっているのである.
+これは NetBSD だと sys/arch/[アーキ名]/[アーキ名]/locore.s にあるのだが,
+これを探すにはどうするか.それは,Makefile を読むのだ.
+
+Makefile を読むと,リンカを使ってカーネルモジュールの最終リンクを行ない,
+最終的なカーネルオブジェクトを作成する部分が必ずあるはずだ.このとき,
+ELF などのオブジェクト形式で作成するためには,スタート地点の指定が必要なので,
+スタート地点を指定している部分が必ず存在する.リンカは多くの場合 GNU の ld を
+使用しているであろうから,Makefile 中で,ld を使用している部分を探す.
+これはふつうのまっとうな Makefile なら,LD ?= ld というように変数に置き換えて,
+$(LD) のようにして使用しているはずである.そのような場所を探す.
+(ひょっとしたら gcc からリンカを呼び出すことで,ld を直接使ってない場合が
+ あるかもしれないので注意である)
+
+で,ld を使用している部分を見つけたら,以下のオプションに注意する.
+
+	-e [entry]		スタート位置のラベルの指定
+	-Ttext [address]	テキストセグメントのアドレスを指定
+	-c [commandfile]	LD script ファイルを指定
+	-T [commandfile]	-c と同じ
+
+-e でスタート位置を指定していたら,そのラベルの位置がテキストセグメントの
+先頭にくるということなので,まさにそのラベルの位置から実行が始まる.
+あとは grep でラベルを探すだけである.
+-c や -T で LD script ファイルを指定している場合には,その LD script ファイルの
+中で,セグメントの分割方法を細かに指定しているはずである.その中で
+テキストセグメントの先頭に配置されているラベル名を調べる.そこが,スタート地点
+である.
+
+実際には -e オプションは使われず,LD script によってセグメントが分割されて
+いることが多い.スタート位置のラベル名がわかったら,あとはおもむろに
+grep で探すだけだ.たいていは *start*.s のような名前のアセンブラファイルの
+中にある.NetBSD だと locore.s だが,Linux だと start なんちゃらとかいう
+ファイルにあるようである(と思ったたしか).また,スタート位置はアーキテクチャ
+依存なので,アーキテクチャごとにディレクトリがわかれているような場合には,
+アーキテクチャ依存の部分に入っているはずである.
+
+ブート部分を読む場合には,アセンブラの知識は必須である.C の知識だけでも
+読めなくはないが,何をやっているのか,プロセッサはどう動いているのかを
+知りたければ,アセンブラを読むしかない.しかし,アセンブラはアセンブラの
+文法だけ知っていれば読めるというわけではない.プロセッサに対する知識が絶対に
+必要だ.なぜなら,とくにブートストラップやデバイスドライバでは,CPU の
+レジスタの設定などを行なうため,
+
+	レジスタの意味がわからなければどうしようもない
+
+からである.
+
+アセンブラに関する資料は,C言語に関する資料に比べれば,残念ながら最近はあまり
+多くないように思う.これは,
+
+	本屋に通って必死に探す
+	雑誌記事をひたすら探す
+	Web 検索でひたすら探す
+
+などして勉強することになる.アセンブラは略語だらけなので,実際のソースだけ
+見て勉強するのは辛いと思う.ここで,ひとついい方法がある.クロスコンパイル
+環境を作成して,クロスコンパイラで -S オプションでサンプルプログラムを
+コンパイルしてみるのだ.このようにすると as を呼び出す直前で中止して,
+アセンブラ出力を出してくれる.これを眺めるのだ.Cでやりたいことをアセンブラで
+書くとどうなるのか教えてくれるので,実際のところこれはけっこう参考になる.
+
+と,まあ,ここまでいろいろ書いてしまって,まるでここに書いたことが
+全部できないとカーネルは読めないみたいになってしまったが,ただ思いつくままに,
+
+	そういえば,あんなこともやったなあ
+
+というレベルで書いただけなので,あまり気にしないでほしい.一番重要なことは,
+本人のやる気だ.アセンブラの勉強も含め,カーネルの勉強は短期間でできるものでは
+なく,長期的な展望が必要だとおもう.だから,
+
+	来年の今ごろには,読めるようになっているといいなあ
+
+というくらいの余裕を持って,あまり負担をかけずにちまちまとやっていくことが
+大事であると思う.
+
+2002/2
+(次回作の OMAKE.jpn に続く)
+
 このファイルはここまで.

+ 2 - 2
Obj.c

@@ -46,13 +46,13 @@ Obj ObjListData_GetObj(ObjListData data)
   return (data->obj);
 }
 
-Obj ObjListData_GetPrev(ObjListData data)
+ObjListData ObjListData_GetPrev(ObjListData data)
 {
   if (data == NULL) return (NULL);
   return (data->prev);
 }
 
-Obj ObjListData_GetNext(ObjListData data)
+ObjListData ObjListData_GetNext(ObjListData data)
 {
   if (data == NULL) return (NULL);
   return (data->next);

+ 2 - 2
Obj.h

@@ -21,8 +21,8 @@ typedef Obj (*ObjDestructor)(Obj);
 /*****************************************************************************/
 
 Obj ObjListData_GetObj(ObjListData data);
-Obj ObjListData_GetPrev(ObjListData data);
-Obj ObjListData_GetNext(ObjListData data);
+ObjListData ObjListData_GetPrev(ObjListData data);
+ObjListData ObjListData_GetNext(ObjListData data);
 int ObjList_GetLength(ObjList list);
 ObjListData ObjList_GetStartEdge(ObjList list);
 ObjListData ObjList_GetEndEdge(ObjList list);

+ 321 - 74
README

@@ -5,14 +5,18 @@ WonX - WonderWitch on X.
 ご意見,ご要望など歓迎します.どしどしお寄せください.
 バグ情報やアドバイスがあれば,作者の坂井弘亮まで,どんどんメールください.
 アドレスは,
-sakai@seki.ee.kagu.sut.ac.jp
-hsakai@pfu.co.jp
+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
+ミラーサイトは,坂井が気が向いたときにアップデートするので,常に最新,
+というわけではありません.あくまでバックアップ用です.
 
 ■ はじめに
 
@@ -48,8 +52,9 @@ WonX 
   (WonderWitch用ソースコード → WonX用ソースコードの変換用 perl スクリプトを
    添付しているので,WonderWitch用ソースコードの中に漢字が入っているのならば,
    日本語 perl が望ましい)
-  添付の perl スクリプトは,すべて #!/usr/local/bin/perl になっているので,
-  日本語 perl が別のところにあるばあいには,修正してから使用してください.
+  添付の perl スクリプトは,make 時に自動で先頭に perl へのフルパス
+  (#!/usr/bin/perl など)が付加されるので,日本語 perl が別のところにある
+  ばあいには,修正してから使用してください.
   日本語 perl が無ければ,まあ,ふつうの perl でもたぶん大丈夫でしょう.
 ・qkc
   漢字コード変換,改行コード変換に必要.
@@ -104,16 +109,17 @@ WonX 
 ~/wonx/smac>% ./smac
 
 ウインドウが開いて,標準出力にメッセージが出力されます.
-いったん F10 を押して画面描画を OFF にします.しばらくしたら
-(メッセージの内容が変わったら) F10 を押して再び画面表示を ON にすると,
-smac のタイトル画面が表示されます.
-ここでスペースを押して,さらにまた F10 で画面表示を OFF にして,
+いったん F9 を押して画面描画を OFF にします.(何度も押すと表示レベルが
+下がってしまうので,1回だけ長めに押してください)
+しばらくしたら(メッセージの内容が変わったら) F10 を(長めに1回だけ)押して
+再び画面表示を ON にすると,smac のタイトル画面が表示されます.
+ここでスペースを押して,さらにまた F9 で画面表示を OFF にして,
 しばらくしたら(メッセージの内容が変わったら) F10 で画面表示を ON にします.
 どうですか? SpeedMac のゲーム画面が表示されているでしょうか?
 カーソルキーで移動,スペースキーで射撃です.
 ただし,キー入力はキー入力用関数が呼ばれたときしか有効ではないので,
 キーは反応するまで長めに押してください.
-F10 を押して頻繁に描画の ON, OFF を切替えるのは,描画が非常に遅いため,
+F9, F10 を押して頻繁に描画の ON, OFF を切替えるのは,描画が非常に遅いため,
 ONのままだと画面クリアとかに異常に時間がかかるからです.
 
 最後に,WonderWitch 用の端末エミュレータ "WWTerm" をコンパイル・実行
@@ -130,7 +136,8 @@ ON
 コンパイル・リンクして,X Window System 上で動作するような実行形式を
 作ってみましょう.
 
-まず,WonX を展開して,make してください.libwonx.a ができあがります.
+まず,WonX を展開して,make してください.libwonx.a と各種 perl スクリプトが
+できあがります.
 
 ~>% tar xvzf wonx-x.x.tar.gz
 (中略)
@@ -141,11 +148,11 @@ ON
 libwonx.a
 ~/wonx>% 
 
-次に,libwonx.a と,wonx_include ディレクトリと,
+次に,libwonx.a と,wonx ディレクトリと,
 challsrc.sh, filters.pl, sys2wonx.pl, int2sint.pl をあなたの作ったプログラムの
 ディレクトリ(ここでは例として,yoursample とします)にコピーします.
 
-~/wonx>% cp -R libwonx.a wonx_include ../yoursample
+~/wonx>% cp -R libwonx.a wonx ../yoursample
 ~/wonx>% cp challsrc.sh filters.pl sys2wonx.pl int2sint.pl ../yoursample
 ~/wonx>% cd ../yoursample
 ~/yoursample>% 
@@ -160,8 +167,9 @@ challsrc.sh, filters.pl, sys2wonx.pl, int2sint.pl 
   (つまり,改行コードを \r\n から \n に変換して,漢字コードを SJIS から
    EUC に変換します)
 ・プログラム中の #include <sys/disp.h> のようなのを,
-  #include "wonx_include/disp.h" に変更する.(sys2wonx.pl を通す)
-・デフォルトの int を,short int に変換する.(int2sint.pl を通す)
+  #include "wonx/disp.h" に変更する.(sys2wonx.pl を通すことで変換してくれる)
+・デフォルトの int を,short int に変換する.
+  (int2sint.pl を通すことで変換してくれる)
 これらのフィルタをまとめて通してくれる filters.pl というスクリプトを
 添付してあるので,以下のようにして,すべてのソースファイルに対して,
 必要なフィルタを通してください.
@@ -172,7 +180,7 @@ challsrc.sh, filters.pl, sys2wonx.pl, int2sint.pl 
 
 ~/yoursample>% ./challsrc.sh *.[ch] [Mm]akefile* MAKEFILE*
 
-(注意! filters.pl や challsrc.sh は,ファイルの本体を書き換えてしまうので,
+(注意! filters.pl や challsrc.sh は,*ファイルの本体を書き換えてしまう*ので,
  変更されると困るようなファイルは必ずバックアップしてください)
 
 makefile を以下のように修正する.
@@ -198,8 +206,8 @@ makefile 
 
 ■ WonX 概要
 
-WonX は,WonderWitch の display_control() とか display_status() といった
-関数(BIOS に対するシステムコール)と代替の関数を持っています.
+WonX は,WonderWitch の display_control() とか display_status() といった関数
+(BIOS に対するシステムコール)と代替の関数を持っています.
 これらの関数は,X上にウインドウを開いて,そこで WonderWitch と互換の動作を
 するように書いてあります.
 
@@ -211,39 +219,41 @@ WonderWitch 
 ■ ヘッダファイルについて
 
 WonX は,UNIXシステム上にある libc を使用します.つまり,/usr/include の
-下を include します.
+下を include します.(このため strlen(), fopen() などの標準ライブラリは
+UNIX 付属のものが使用可能)
 また,WonderWitch には,sys/types.h などといったヘッダファイルがあります.
 よって,WonderWitch のヘッダファイル構成をそのまま WonX に引き継ぐと,
 WonX のヘッダファイルと UNIX のヘッダファイルがコンフリクトする
 可能性が出てきます.
-(たとえば,WonderWitch の sys/types.h と /usr/include/sys/types が
+(たとえば,WonderWitch の sys/types.h と UNIX の /usr/include/sys/types.h
  コンフリクトする,などです)
 これは,WonderWitch用のアプリケーションをコンパイルするときに,要注意です.
 コンパイルがうまくとおらないという障害の原因は,ほとんどがこのような,
 「ヘッダファイルのコンフリクトもしくは誤認」に起因しています.
 
-対策として,WonX では wonx_include というディレクトリの下にヘッダファイルを
+対策として,WonX では wonx というディレクトリの下にヘッダファイルを
 格納してあります.(本当は sys というディレクトリにしたかったが,
 上記の対策のため,このようにした)
 WonderWitch 用プログラム中の,
 #include <sys/types.h>
 のような部分は,すべて,
-#include <wonx_include/types.h>
+#include "wonx/types.h"
 のように修正する必要があります.
 (stdio.h や stdlib.h は,UNIX システム付属のものを使用するので,
  そのままでかまいません)
 (ただし,コンフリクトしないという絶対の自信があるなら,この限りではありません)
 WonderWitch のプログラムの,#include <sys/*.h> は,すべて
-#include <wonx_include/*.h> に修正する必要がある,ということです.
+#include "wonx/*.h" に修正する必要がある,ということです.
 (これをまとめて行うための sys2wonx.pl という perl スクリプトを添付して
  あります../filters.pl ./sys2wonx.pl -f *.[ch] を実行すると,ごっそりと
  書き換えてくれます)
 
 また,UNIXシステムによっては,/usr/include/sys/types.h で ushort, ulong を
 定義しているものといないものがあります.よって,コンパイル中に
-ulong が2重定義されているとおこられる場合があります.
-このあたりの微調整には,wonx_include 以下のファイルを直接修正して
-調整してください.wonx_include/system_configure.h を修正することにより,
+ulong が2重定義されているとおこられる場合があります.(Linux ではそのように
+なるようである)
+このあたりの微調整には,wonx ディレクトリ以下のファイルを直接修正して
+調整してください.wonx/system_configure.h を修正することにより,
 調整できるようになってます.
 
 ■ WonX のコンパイル
@@ -269,6 +279,15 @@ ar ruc libwonx.a WWCharacter.o WWColorMap.o WWDisplay.o WWLCDPanel.o WWPalette.o
 libwonx.a
 ~/wonx>% 
 
+このとき,各種 perl スクリプトも同時に作成されます.
+必要があれば make install すると,各種ヘッダファイル,ライブラリ,
+perl スクリプトがインストールされます.(インストールしなくても構いません.
+以降はインストールしなかったものとして説明します)
+
+~/wonx>% su
+Password:
+# make install
+
 ここまでで,ライブラリの作成は終りです.
 
 ■ WonderWitch 用アプリケーションのコンパイル
@@ -290,7 +309,7 @@ SpeedMac 
 
 2. ヘッダファイルと libwonx.a をコピーする.
 
-~/wonx/smac-b02>% cp -R ../wonx_include .
+~/wonx/smac-b02>% cp -R ../wonx .
 ~/wonx/smac-b02>% cp ../libwonx.a .
 ~/wonx/smac-b02>% 
 
@@ -313,8 +332,8 @@ qkc 
 #include <sys/disp.h>
 #include <sys/key.h>
 のような部分を,
-#include "wonx_include/disp.h"
-#include "wonx_include/key.h"
+#include "wonx/disp.h"
+#include "wonx/key.h"
 のように修正します.
 
 これをまとめてやるための perl スクリプト (sys2wonx.pl) を添付してあるので,
@@ -401,8 +420,10 @@ smac 
 ・F2 を押すと,パレットのデータをダンプ出力する.
 ・F3 を押すと,キャラクターのデータをダンプ出力する.
 ・F4 を押すと,スプライトのデータをダンプ出力する.
-・F10 を押すと,表示/非表示モードを切替える.
-  (非表示だと画面への描画を行わないが高速)
+・F9 を押すと,画面の表示レベルを下げる.
+・F10 を押すと,画面の表示レベルを上げる.
+  表示レベルはデフォルトで 1 になっており,現在のレベルが 1 以上の場合のみ
+  画面の描画を行う.0 以下の場合には,画面への描画を行わないがそのぶん高速.
 ・F11 で10秒間停止.(画面写真をとるときなどに利用できる)
   (F11は短めに押してください.長めに押すと,復帰しなくなるようです)
 ・q もしくは Ctrl-c もしくは F12 で強制終了.
@@ -419,8 +440,9 @@ for (y = 0; y < 32; y++)
   }
 }
 
-このような場合は,F10 を押して非表示モードにして,ループ処理が終ったら
-再び F10 を押して表示モードに戻してください.
+このような場合は,F9 を押して表示レベルを下げて,ループ処理が終ったら
+再び F10 を押して表示レベルを上げてください.(何度も押すと表示レベルが
+どんどん下がって(もしくは上がって)しまうので,長めに1回だけ押してください)
 
 F1 や F2 を押すと,データをダンプ出力するのですが,標準ではその他にも
 メッセージが大量に出力されているので,ふつうに F1 を押しただけでは,
@@ -450,7 +472,7 @@ WonX 
 
 > smac > /dev/null
 
-だと,文字列を kterm などに表示しないぶん,高速になります.
+だと,文字列を kterm などに表示しないぶん,(かなり)高速になります.
 
 ■ 足りないもの
 
@@ -486,7 +508,7 @@ WonX 
 ヘッダファイルのコンフリクトです.とくに,WonderWitch で sys 以下の
 ファイルをインクルードしている場合は注意してください.
 ushort, ulong などは,sys/types.h で定義されているシステムもあるし,
-そうでないシステムもあります.このへんは,wonx_include/system_configure.h で
+そうでないシステムもあります.このへんは,wonx/system_configure.h で
 調整してください.
 (FreeBSD では ushort のみ定義されているが,RedHat Linux では,
  uchort, ulong ともに定義されているので,そのままだとコンパイル中に
@@ -530,7 +552,7 @@ WonderWitch 
 バグなど)を発見できることがあるので,なるべくなら int2sint.pl で int を
 ごっそり short int にしてしまうことをおすすめします.
 
-[エンディアンの問題]
+[バイトエンディアンの問題]
 
 WonderWitch の CPU は x86系です.SPARC などで使用する場合には,
 エンディアンに注意する必要があります.
@@ -543,7 +565,9 @@ WonX-2.1 
 修正しました.i386 と SPARC でエンディアンに依存しないことを動作確認
 しています.しかしそれでも,キャラクタデータを unsigned char * で定義して,
 ビットマップ読み込み用の関数にキャラクタデータを渡すときに short int * に
-キャストして渡すような書き方をしていると,依存してしまいます.
+キャストして渡すような書き方をしていると,依存してしまいます.つまり,
+WonX 自体はエンディアンに依存していないが,WonX を利用するプログラムが
+エンディアン依存に書いてあっては,どうしようもないということです.
 
 キャラクタデータのビットマップ読み込み用の関数には,適切な型のデータを
 渡すようにしてください.short int * を渡すべきところに,unsigned char * を
@@ -631,14 +655,14 @@ gcc -g -o smac $(OBJS) -L. -L/usr/X11R6/lib -lwonx -lX11 -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 の検索に失敗します.
+-lX11, -lXt の検索に失敗し,やはり make に失敗します.
 
 漢字コードに関しても,同じことがいえます.UNIX での漢字コードは EUC なので,
 ソースコード中に SJIS の漢字が入っていると,うまくコンパイルできなかったり,
@@ -667,6 +691,11 @@ SAMPLE.C 
 タブや改行コードは,"\t" "\n" のような文字列に変換されて出力されます.
 添付の sout2str.pl を通すことにより,シリアル通信への出力のみ抽出して,
 端末への出力のイメージで表示させることができます.
+sout2str.pl は以下のようにして利用します.
+(terminal という WonderWitch 用プログラムを,WonX を利用して UNIX 上で
+ コンパイルして,sout2str.pl を通してシリアルへの出力のイメージを見たい場合)
+
+> ./terminal | ./sout2str.pl
 
 ■ 割り込みについて
 
@@ -732,66 +761,285 @@ _asm_inline() 
 WonderWitch 用のプログラムを開発していく際に,WonX の場合のみ組み込みたくて,
 WonderSwan 上で実行するときには取り除きたいコードがあったとします.
 (例えば,デバッグ情報の出力のために printf() を入れる場合など)
-このようなときのために,wonx_include/types.h で
+このようなときのために,wonx/types.h で
 #define _WONX_
 してあるので,そのような場所は #ifdef _WONX_ でくくってください.
 
-■ ダンプデータの取りかた
+■ WonX が提供するサービス関数
 
-ソース中に,
+WonX は以下の関数をデバッグ用のサービス関数として提供しています.
+以下の関数を実行することにより,デバッグ情報を stdout に出力します.
 
-#include "WonX.h"
-#include "WonXDisplay.h"
-#include "WWDisplay.h"
-#include "WWColorMap.h"
-#include "WWPalette.h"
-#include "WWCharacter.h"
-#include "WWSprite.h"
+#include "wonx/wonx.h"
 
-int i;
-WWDisplay ww_display;
+/* カラーマップ情報の出力 */
+void wonx_print_colormap_data(void);
 
-ww_display = WonXDisplay_GetWWDisplay(WonX_GetWonXDisplay());
+/* パレット情報の出力 */
+void wonx_print_palette_data(int n);
 
-WWColorMap_PrintData(WWDisplay_GetColorMap(ww_display), stdout);
+/* すべてのパレット情報を出力 */
+void wonx_print_all_palette_data(void);
 
-for (i = 0; i < 16; i++)
-  WWPalette_PrintData(WWDisplay_GetPalette(ww_display, i), stdout);
+/* キャラクタ情報の出力 */
+void wonx_print_character_data(int n);
 
-for (i = 0; i < 512; i++)
-  WWCharacter_PrintData(WWDisplay_GetCharacter(ww_display, i), stdout);
+/* すべてのキャラクタ情報を出力 */
+void wonx_print_all_character_data(void);
 
-for (i = 0; i < 128; i++)
-  WWSprite_PrintData(WWDisplay_GetSprite(ww_display, i), stdout);
+/* スプライト情報の出力 */
+void wonx_print_sprite_data(int n);
 
-のようなコードを挿入することにより,任意の場所でキャラクタやパレットの
-ダンプデータを出力させることができます.
+/* すべてのスプライト情報を出力 */
+void wonx_print_all_sprite_data(void);
 
-プログラム中に,不安な場所があったら,
+たとえばソース中に不安な場所があったら,
 
 #ifdef _WONX_
-ww_display = WonXDisplay_GetWWDisplay(WonX_GetWonXDisplay());
-printf("Before setting:\n");
-WWSprite_PrintData(WWDisplay_GetSprite(ww_display, 0), stdout);
-#endif /* _WONX_ */
+#include "wonx/wonx.h"
+#endif
 
-/* ここにスプライトの設定についての不安なコードがある */
+void func(void)
+{
+
+  ...(中略)...
+
+#ifdef _WONX_
+  wonx_print_sprite_data(0);
+#endif
+
+  /* ここにスプライトの設定についての不安なコードがある */
 
 #ifdef _WONX_
-printf("After setting:\n");
-WWSprite_PrintData(WWDisplay_GetSprite(ww_display, 0), stdout);
-#endif /* _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();
+}
+
+処理1,処理2の位置では画面描画はOFFになっているのですが,処理3の部分では
+期待に反して画面の描画は 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,処理1,処理3のところでは
+表示レベルは 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 がインクルードされても,
+2度目のインクルードになって,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_include/disp.h"
+#include "wonx/disp.h"
 のように変換するフィルタです.
 
 [int2sint.pl]
@@ -861,8 +1109,7 @@ WonX 
 作者については,添付の OMAKE.jpn を参照してください.
 
 坂井弘亮の連絡先のメールアドレスは,
-sakai@seki.ee.kagu.sut.ac.jp
-hsakai@pfu.co.jp
+hsakai@m8.people.or.jp
 です.また,本ソフトウエアの最新版を,
 http://www.seki.ee.kagu.sut.ac.jp/~sakai/WonderWitch/index.html
 で配布しています.

+ 3 - 1
UNIXSerialPort.c

@@ -163,8 +163,10 @@ UNIXSerialPort UNIXSerialPort_Destroy(UNIXSerialPort unix_serial_port)
   if (unix_serial_port == NULL)
     WonX_Error("UNIXSerialPort_Destroy", "Object is not created.");
 
-  if (UNIXSerialPort_IsOpened(unix_serial_port))
+  if (UNIXSerialPort_IsOpened(unix_serial_port)) {
     UNIXSerialPort_Close(unix_serial_port);
+    unix_serial_port->opened = 0;
+  }
 
   free(unix_serial_port);
 

+ 9 - 3
UNIXTimer.c

@@ -23,6 +23,7 @@ volatile static UNIXTimer pointed_unix_timer = NULL;
 static void UNIXTimer_CallBackFunction(int argument)
 {
   int ret;
+  int old;
 
   /*
    * static なフラグを立てて,コールバック関数からコールバック関数が
@@ -34,6 +35,9 @@ static void UNIXTimer_CallBackFunction(int argument)
 
   if (pointed_unix_timer->pause) {
     pointed_unix_timer->interrupt_in_pause++;
+    if (pointed_unix_timer->interrupt_in_pause > 1000) {
+      WonX_Error("UNIXTimer_CallBackFunction", "interrupt count is too much.");
+    }
   } else {
     if (pointed_unix_timer->interrupt_in_pause == 0)
       pointed_unix_timer->interrupt_in_pause = 1;
@@ -44,13 +48,15 @@ static void UNIXTimer_CallBackFunction(int argument)
 	/*
 	 * コールバック関数の中から UNIXTimer_Unpause() などが呼ばれて,
 	 * そこからさらにコールバック関数が呼ばれたりしたときのために,
-	 * ポーズする.
+	 * ポーズする.またこのとき,interrupt_in_pause がインクリメント
+	 * されると無限ループに陥ってしまう可能性がある(?)ので,
+	 * interrupt_in_pause を保存してコールバック関数の実行後に元に戻す.
 	 */
 	pointed_unix_timer->pause++;
-
+	old = pointed_unix_timer->interrupt_in_pause;
 	ret = (*pointed_unix_timer->callback)(pointed_unix_timer->parameter);
-
 	pointed_unix_timer->pause--;
+	pointed_unix_timer->interrupt_in_pause = old;
 
 	/*
 	 * コールバック関数の中で UNIXTimer_* 関連の関数が呼び出されると,

+ 1 - 1
WWCharacter.c

@@ -139,7 +139,7 @@ WWCharacter WWCharacter_Create(int number)
 WWCharacter WWCharacter_Destroy(WWCharacter character)
 {
   if (character == NULL)
-    WonX_Error("WWCharacter_Destroy", "WWCharacter is NULL.");
+    WonX_Error("WWCharacter_Destroy", "Object is not created.");
   free(character);
   return (NULL);
 }

+ 1 - 1
WWCharacter.h

@@ -19,7 +19,7 @@ typedef struct _WWCharacter * WWCharacter;
 #include <stdlib.h>
 
 #include "WWDisplay.h"
-#include "wonx_include/libwwc.h"
+#include "wonx/libwwc.h"
 
 /*****************************************************************************/
 /* ¥á¥ó¥Ð´Ø¿ô¤ÎÀë¸À                                                          */

+ 2 - 1
WWColorMap.c

@@ -24,7 +24,8 @@ WWColorMap WWColorMap_Create(int * lcd_colors)
 
 WWColorMap WWColorMap_Destroy(WWColorMap color_map)
 {
-  if (color_map == NULL) return (NULL);
+  if (color_map == NULL)
+    WonX_Error("WWColorMap_Destroy", "Object is not created.");
   free(color_map);
   return (NULL);
 }

+ 2 - 1
WWCursor.c

@@ -53,7 +53,8 @@ WWCursor WWCursor_Create(WWPalette palette)
 
 WWCursor WWCursor_Destroy(WWCursor cursor)
 {
-  if (cursor == NULL) return (NULL);
+  if (cursor == NULL)
+    WonX_Error("WWCursor_Destroy", "Object is not created.");
   free(cursor);
   return (NULL);
 }

+ 5 - 4
WWDisplay.c

@@ -2,9 +2,9 @@
 /* ¤³¤³¤«¤é                                                                  */
 /*****************************************************************************/
 
-#include "wonx_include/disp.h"
-#include "wonx_include/text.h"
-#include "wonx_include/libwwc.h"
+#include "wonx/disp.h"
+#include "wonx/text.h"
+#include "wonx/libwwc.h"
 
 #include "WWDisplayP.h"
 #include "WonX.h"
@@ -214,7 +214,8 @@ WWDisplay WWDisplay_Destroy(WWDisplay display)
 {
   int i;
 
-  if (display == NULL) return (NULL);
+  if (display == NULL)
+    WonX_Error("WWDisplay_Destroy", "Object is not created.");
 
   if (WWDisplay_GetColorMap(display) != NULL)
     WWDisplay_SetColorMap(display,

+ 1 - 1
WWInterrupt.h

@@ -19,7 +19,7 @@ typedef void (*WWInterruptCallback)();
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "wonx_include/system.h"
+#include "wonx/system.h"
 
 /*****************************************************************************/
 /* ¥á¥ó¥Ð´Ø¿ô¤ÎÀë¸À                                                          */

+ 6 - 1
WWLCDPanel.c

@@ -125,11 +125,16 @@ WWLCDPanel WWLCDPanel_Create(int width, int height)
 WWLCDPanel WWLCDPanel_Destroy(WWLCDPanel lcd_panel)
 {
   int i;
-  if (lcd_panel == NULL) return (NULL);
+
+  if (lcd_panel == NULL)
+    WonX_Error("WWLCDPanel_Destroy", "Object is not created.");
+
   for (i = 0; i < 2; i++) {
     if (lcd_panel->pixel[i]) free(lcd_panel->pixel[i]);
   }
+
   free(lcd_panel);
+
   return (NULL);
 }
 

+ 2 - 1
WWPalette.c

@@ -71,7 +71,8 @@ WWPalette WWPalette_Create(int number, int * mapped_colors)
 
 WWPalette WWPalette_Destroy(WWPalette palette)
 {
-  if (palette == NULL) return (NULL);
+  if (palette == NULL)
+    WonX_Error("WWPalette_Destroy", "Object is not created.");
   free(palette);
   return (NULL);
 }

+ 4 - 2
WWScreen.c

@@ -54,7 +54,8 @@ static WWScreenCharacter WWScreenCharacter_Create(int horizontal, int vertical,
 static WWScreenCharacter WWScreenCharacter_Destroy(WWScreenCharacter
 						   screen_character)
 {
-  if (screen_character == NULL) return (NULL);
+  if (screen_character == NULL)
+    WonX_Error("WWScreenCharacter_Destroy", "Object is not created.");
   free(screen_character);
   return (NULL);
 }
@@ -272,7 +273,8 @@ WWScreen WWScreen_Destroy(WWScreen screen)
   int x, y;
   WWScreenCharacter sc;
 
-  if (screen == NULL) return (NULL);
+  if (screen == NULL)
+    WonX_Error("WWScreen_Destroy", "Object is not created.");
 
   for (y = 0; y < screen->height; y++) {
     for (x = 0; x < screen->width; x++) {

+ 2 - 0
WWSerialPort.c

@@ -70,6 +70,8 @@ WWSerialPort WWSerialPort_Destroy(WWSerialPort ww_serial_port)
   if (ww_serial_port == NULL)
     WonX_Error("WWSerialPort_Destroy", "Object is not created.");
 
+  WWSerialPort_Close(ww_serial_port);
+
   free(ww_serial_port);
 
   return (NULL);

+ 1 - 1
WWSerialPort.h

@@ -18,7 +18,7 @@ typedef struct _WWSerialPort * WWSerialPort;
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "wonx_include/comm.h"
+#include "wonx/comm.h"
 
 /*****************************************************************************/
 /* Äê¿ô¤ÎÄêµÁ                                                                */

+ 2 - 1
WWSprite.c

@@ -107,7 +107,8 @@ WWSprite WWSprite_Create(int number, int x, int y,
 
 WWSprite WWSprite_Destroy(WWSprite sprite)
 {
-  if (sprite == NULL) return (NULL);
+  if (sprite == NULL)
+    WonX_Error("WWSprite_Destroy", "Object is not created.");
   free(sprite);
   return (NULL);
 }

+ 2 - 1
WWText.c

@@ -198,7 +198,8 @@ WWText WWText_Destroy(WWText ww_text)
 {
   int i;
 
-  if (ww_text == NULL) WonX_Error("WWText_Destroy", "Object is not created.");
+  if (ww_text == NULL)
+    WonX_Error("WWText_Destroy", "Object is not created.");
 
   for (i = 0; i < 128; i++) {
     if (WWText_GetFont(ww_text, i))

+ 2 - 0
WWTimer.c

@@ -100,6 +100,8 @@ WWTimer WWTimer_Destroy(WWTimer ww_timer)
   if (ww_timer == NULL)
     WonX_Error("WWTimer_Destroy", "Object is not created.");
 
+  WWTimer_OFF(ww_timer);
+
   free(ww_timer);
 
   return (NULL);

+ 1 - 1
WWTimer.h

@@ -18,7 +18,7 @@ typedef struct _WWTimer * WWTimer;
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "wonx_include/timer.h"
+#include "wonx/timer.h"
 
 /*****************************************************************************/
 /* ¥á¥ó¥Ð´Ø¿ô¤ÎÀë¸À                                                          */

+ 65 - 4
WonX.c

@@ -1,9 +1,9 @@
 #include "WonXP.h"
 #include "etc.h"
 
-#include "wonx_include/disp.h"
-#include "wonx_include/system.h"
-#include "wonx_include/comm.h"
+#include "wonx/disp.h"
+#include "wonx/system.h"
+#include "wonx/comm.h"
 
 static WonX wonx = NULL;
 
@@ -14,17 +14,78 @@ int WonX_IsCreated(void)
 
 void WonX_Create(void)
 {
+  if (WonX_IsCreated())
+    WonX_Error("WonX_Create", "WonX has been already created.");
+
   wonx = (WonX)malloc(sizeof(_WonX));
   if (wonx == NULL) WonX_Error("WonX_Create", "Cannot allocate memory.");
 
+  /*
+   * WonX のタイマからはディスプレイのリフレッシュなどの関数を呼び出すため,
+   * WonXSystem_Create() でタイマをスタートさせる前に WonXDisplay_Create() で
+   * WonXDisplay オブジェクトを作成しておく必要がある.このため
+   * WonXDisplay_Create() を WonXSystem_Create() の後に持っていってはいけない.
+   */
   wonx->wonx_display =
     WonXDisplay_Create(LCD_PIXEL_WIDTH * 2, LCD_PIXEL_HEIGHT * 2,
                        LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT,
 		       SCREEN_CHAR_WIDTH, SCREEN_CHAR_HEIGHT);
 
+  /*
+   * WonXDisplay と同様のことが WonXSerialPort でも将来的に起きる可能性が
+   * あるかもしれないので, WonXSerialPort_Create() もいちおう
+   * WonXSystem_Create() の前に置いておく.
+   */
+  wonx->wonx_serial_port = WonXSerialPort_Create();
+
+  /*
+   * WonXSystem_Create() ではタイマを作成するが,タイマからはいろいろな
+   * オブジェクトが呼ばれる可能性があるため,タイマの作成は一番最後に行う
+   * べきである.このため,WonXSystem_Create() は一番最後に行う.
+   * (他のオブジェクトの作成中等にタイマがかかった場合,おかしなことに
+   *  なってしまう)
+   */
   wonx->wonx_system = WonXSystem_Create();
 
-  wonx->wonx_serial_port = WonXSerialPort_Create();
+  return;
+}
+
+void WonX_Destroy(void)
+{
+  if (!WonX_IsCreated())
+    WonX_Error("WonX_Destroy", "WonX has not been created yet.");
+
+  /*
+   * WonXSystem はタイマを持つが,タイマからはいろいろなオブジェクトが
+   * 呼ばれる可能性があるため,一番最初にタイマを停止する必要がある.
+   * このため,WonXSystem_Destroy() は一番最初に行う.
+   * (他のオブジェクトの削除中等にタイマがかかった場合,おかしなことに
+   *  なってしまう)
+   */
+  if (wonx->wonx_system)
+    wonx->wonx_system = WonXSystem_Destroy(wonx->wonx_system);
+
+  /*
+   * WonXDisplay と同様のことが WonXSerialPort でも将来的に起きる可能性が
+   * あるかもしれないので, WonXSerialPort_Destroy() もいちおう
+   * WonXSystem_Destroy() の後に置いておく.
+   */
+  if (wonx->wonx_serial_port)
+    wonx->wonx_serial_port = WonXSerialPort_Destroy(wonx->wonx_serial_port);
+
+  /*
+   * WonX のタイマからはディスプレイのリフレッシュなどの関数を呼び出すため,
+   * WonXDisplay を消去する前に WonXSystem を消去して,タイマを停止する
+   * 必要がある.(でないと WonXDisplay_Destroy() の実行中にタイマがかかった
+   * ときに,おかしなことになる)
+   * このため,WonXDisplay_Destroy() を WonXSystem_Destroy() の前に
+   * 持っていってはいけない.
+   */
+  if (wonx->wonx_display)
+    wonx->wonx_display = WonXDisplay_Destroy(wonx->wonx_display);
+
+  free(wonx);
+  wonx = NULL;
 
   return;
 }

+ 1 - 0
WonX.h

@@ -7,6 +7,7 @@
 
 int WonX_IsCreated(void);
 void WonX_Create(void);
+void WonX_Destroy(void);
 WonXDisplay WonX_GetWonXDisplay(void);
 WonXSystem WonX_GetWonXSystem(void);
 WonXSerialPort WonX_GetWonXSerialPort(void);

+ 39 - 13
WonXDisplay.c

@@ -45,6 +45,27 @@ WonXDisplay WonXDisplay_Create(int x_width, int x_height,
   return (wonx_display);
 }
 
+WonXDisplay WonXDisplay_Destroy(WonXDisplay wonx_display)
+{
+  XDisplay x_display;
+  WWDisplay ww_display;
+
+  if (wonx_display == NULL)
+    WonX_Error("WonXDisplay_Destroy", "Object is not created.");
+
+  x_display = WonXDisplay_GetXDisplay(wonx_display);
+  if (x_display)
+    WonXDisplay_SetXDisplay(wonx_display, XDisplay_Destroy(x_display));
+
+  ww_display = WonXDisplay_GetWWDisplay(wonx_display);
+  if (ww_display)
+    WonXDisplay_SetWWDisplay(wonx_display, WWDisplay_Destroy(ww_display));
+
+  free(wonx_display);
+
+  return (NULL);
+}
+
 int WonXDisplay_PrintData(WonXDisplay wonx_display)
 {
   int i;
@@ -89,34 +110,39 @@ int WonXDisplay_PrintData(WonXDisplay wonx_display)
   return (0);
 }
 
-int WonXDisplay_Sync(WonXDisplay wonx_display)
+int WonXDisplay_DrawLCDWindow(WonXDisplay wonx_display)
 {
   XDisplay x_display;
-
-  WonXDisplay_PrintData(wonx_display);
+  WWDisplay ww_display;
+  WWLCDPanel ww_lcd_panel;
 
   x_display = WonXDisplay_GetXDisplay(wonx_display);
+  ww_display = WonXDisplay_GetWWDisplay(wonx_display);
 
-  XDisplay_Sync(x_display);
+  /* 表示レベルが1以上のときだけ描画する */
+  if (XDisplay_GetLCDDrawLevel(x_display) > 0) {
+    WWDisplay_DrawLCDPanel(ww_display);
+    ww_lcd_panel = WWDisplay_GetLCDPanel(ww_display);
+    XDisplay_DrawLCDWindow(x_display, ww_display, ww_lcd_panel);
+  }
 
   return (0);
 }
 
-int WonXDisplay_Flush(WonXDisplay wonx_display)
+int WonXDisplay_Sync(WonXDisplay wonx_display)
 {
   XDisplay x_display;
-  WWDisplay ww_display;
-  WWLCDPanel ww_lcd_panel;
 
+  WonXDisplay_PrintData(wonx_display);
   x_display = WonXDisplay_GetXDisplay(wonx_display);
-  ww_display = WonXDisplay_GetWWDisplay(wonx_display);
+  XDisplay_Flush(x_display);
 
-  if (XDisplay_GetLCDDraw(x_display)) {
-    WWDisplay_DrawLCDPanel(ww_display);
-    ww_lcd_panel = WWDisplay_GetLCDPanel(ww_display);
-    XDisplay_DrawLCDWindow(x_display, ww_display, ww_lcd_panel);
-  }
+  return (0);
+}
 
+int WonXDisplay_Flush(WonXDisplay wonx_display)
+{
+  WonXDisplay_DrawLCDWindow(wonx_display);
   WonXDisplay_Sync(wonx_display);
 
   return (0);

+ 2 - 0
WonXDisplay.h

@@ -27,7 +27,9 @@ WWDisplay WonXDisplay_GetWWDisplay(WonXDisplay wonx_display);
 WonXDisplay WonXDisplay_Create(int x_width, int x_height,
 			       int ww_lcd_panel_width, int ww_lcd_panel_height,
 			       int ww_screen_width, int ww_screen_height);
+WonXDisplay WonXDisplay_Destroy(WonXDisplay wonx_display);
 int WonXDisplay_PrintData(WonXDisplay wonx_display);
+int WonXDisplay_DrawLCDWindow(WonXDisplay wonx_display);
 int WonXDisplay_Sync(WonXDisplay wonx_display);
 int WonXDisplay_Flush(WonXDisplay wonx_display);
 

+ 3 - 3
WonXSystem.c

@@ -85,15 +85,15 @@ static int WonXTimer_Callback(WonXSystem wonx_system)
 
   /* キー入力割り込み */
   /*
-   * XDisplay_Sync() が他のところから呼ばれた場合に割り込みをとり
+   * XDisplay_Flush() が他のところから呼ばれた場合に割り込みをとり
    * こぼしてしまうので,XDisplay クラスのほうで割り込みの処理をするか,
    * フラグを立てるように改良する必要が有るかも.
-   * (別の場所で頻繁に XDisplay_Sync() が呼ばれていると,キー割り込みが
+   * (別の場所で頻繁に XDisplay_Flush() が呼ばれていると,キー割り込みが
    *  発生しなくなってしまう)
    * とりあえずは簡易的にこのような実装にしておいて問題無いだろう.
    */
   old_key = XDisplay_GetKeyPress(x_display);
-  XDisplay_Sync(x_display);
+  XDisplay_Flush(x_display);
   new_key = XDisplay_GetKeyPress(x_display);
   /* 新しいキーが押された場合 */
   /*

+ 195 - 43
XDisplay.c

@@ -9,6 +9,7 @@
 
 #include "XDisplayP.h"
 #include "WonX.h"
+#include "WonXDisplay.h"
 #include "etc.h"
 
 /*****************************************************************************/
@@ -22,7 +23,18 @@ XColorGCDatabase XDisplay_GetColorGCDatabase(XDisplay x_display)
 { return (x_display->color_gc_database); }
 
 unsigned int XDisplay_GetKeyPress(XDisplay d) { return (d->key_press); }
-int XDisplay_GetLCDDraw(XDisplay d) { return (d->lcd_draw); }
+
+int XDisplay_GetLCDDrawLevel(XDisplay d) { return (d->lcd_draw_level); }
+int XDisplay_SetLCDDrawLevel(XDisplay d, int level)
+{
+  d->lcd_draw_level = level;
+  WonXDisplay_Flush(WonX_GetWonXDisplay());
+  return (d->lcd_draw_level);
+}
+int XDisplay_LCDDrawLevelDown(XDisplay d)
+{ return (XDisplay_SetLCDDrawLevel(d, d->lcd_draw_level - 1)); }
+int XDisplay_LCDDrawLevelUp(  XDisplay d)
+{ return (XDisplay_SetLCDDrawLevel(d, d->lcd_draw_level + 1)); }
 
 int XDisplay_GetColorMapPrint(XDisplay d) {return (d->color_map_print); }
 int XDisplay_GetPalettePrint(XDisplay d) {return (d->palette_print); }
@@ -111,6 +123,7 @@ static char * translations =
 /* 色名からピクセル値を取得する                                              */
 /*===========================================================================*/
 
+#ifdef USE_X_FONT
 static unsigned long XDisplay_GetPixelFromColorName(XDisplay x_display,
 						    char * color_name)
 {
@@ -119,6 +132,7 @@ static unsigned long XDisplay_GetPixelFromColorName(XDisplay x_display,
 		   &c0, &c1);
   return (c0.pixel);
 }
+#endif
 
 /*===========================================================================*/
 /* イベントハンドラ                                                          */
@@ -157,31 +171,72 @@ static void KeyHandler(Widget w, XtPointer p, XEvent * event,
     switch (key_sym) {
 
       /* WonderSwan用 */
-    case XK_Up      : press = KEY_UP1;    break;
-    case XK_Right   : press = KEY_RIGHT1; break;
-    case XK_Down    : press = KEY_DOWN1;  break;
-    case XK_Left    : press = KEY_LEFT1;  break;
-    case XK_i       : press = KEY_UP2;    break;
-    case XK_l       : press = KEY_RIGHT2; break;
-    case XK_k       : press = KEY_DOWN2;  break;
-    case XK_j       : press = KEY_LEFT2;  break;
-    case XK_s       : press = KEY_START;  break;
-    case XK_space   : press = KEY_A;      break;
-    case XK_Shift_L : press = KEY_B;      break;
+    case XK_Up      : press = KEY_UP1;    printf("key : Up1 "   ); break;
+    case XK_Right   : press = KEY_RIGHT1; printf("key : Right1 "); break;
+    case XK_Down    : press = KEY_DOWN1;  printf("key : Down1 " ); break;
+    case XK_Left    : press = KEY_LEFT1;  printf("key : Left1 " ); break;
+    case XK_i       : press = KEY_UP2;    printf("key : Up2 "   ); break;
+    case XK_l       : press = KEY_RIGHT2; printf("key : Right2 "); break;
+    case XK_k       : press = KEY_DOWN2;  printf("key : Down2 " ); break;
+    case XK_j       : press = KEY_LEFT2;  printf("key : Left2 " ); break;
+    case XK_s       : press = KEY_START;  printf("key : Start " ); break;
+    case XK_space   : press = KEY_A;      printf("key : A "     ); break;
+    case XK_Shift_L : press = KEY_B;      printf("key : B "     ); break;
     default         : press = 0;          break;
     }
 
+    if (press) {
+      if (event->type == KeyPress) {
+	x_display->key_press |=  press;
+	printf("Pressed\n");
+      } else {
+	x_display->key_press &= ~press;
+	printf("Released\n");
+      }
+    }
+
     /* WonX 操作用 */
     if (event->type == KeyPress) {
 
       switch (key_sym) {
 
 	/* 表示モード変更 */
+      case XK_F9        :
       case XK_F10       :
-	x_display->lcd_draw = !(x_display->lcd_draw);
 
-	if (x_display->lcd_draw) {
+	if (key_sym == XK_F9) {
+	  printf("key : F9 Pressed\n");
+	  printf("lcd_draw_level : down (%d", x_display->lcd_draw_level);
+	  (x_display->lcd_draw_level)--;
+	  printf(" -> %d)\n", x_display->lcd_draw_level);
+	} else {
+	  printf("key : F10 Pressed\n");
+	  printf("lcd_draw_level : up (%d", x_display->lcd_draw_level);
+	  (x_display->lcd_draw_level)++;
+	  printf(" -> %d)\n", x_display->lcd_draw_level);
+	}
+
+	if (x_display->lcd_draw_level > 0) {
 #if 1
+	  /*
+	   * WonXDisplay_Flush() を実行すると,XDisplay_Flush() が呼ばれて
+	   * イベントのディスパッチが行われてしまうため,イベントの処理中に
+	   * 別のイベントのディスパッチを行うことになってしまう.
+	   * X サーバが,XtDispatchEvent() によるイベントのディスパッチ時に,
+	   * イベントキューからイベントを出してからイベントの処理をするような
+	   * 実装になっている場合には問題ないが,イベントの処理をした後に
+	   * キューからイベントを取り除くような実装になっている場合には,
+	   * XtDispatchEvent() によるイベントのディスパッチ中に再び
+	   * XtDispatchEvent() が呼ばれたときに,イベントがキューから
+	   * 取り除かれることがなく,イベント処理の無限ループに陥ってしまう
+	   * 可能性があるかもしれない.
+	   * (ちなみに XFree86 では大丈夫なようであるが,いちおう)
+	   * このため WonXDisplay_Flush() は呼び出さずに,
+	   * WonXDisplay_DrawLCDWindow() でウインドウの描画のみを行うように
+	   * WonX-2.2 で修正した.
+	   */
+	  WonXDisplay_DrawLCDWindow(WonX_GetWonXDisplay());
+#elif 1
 	  WonXDisplay_Flush(WonX_GetWonXDisplay());
 #else
 	  ExposeHandler(w, p, event, dispatch);
@@ -190,17 +245,28 @@ static void KeyHandler(Widget w, XtPointer p, XEvent * event,
 	break;
 
 	/* データのダンプ操作 */
-      case XK_F1       : x_display->color_map_print = 1; break;
-      case XK_F2       : x_display->palette_print = 1; break;
-      case XK_F3       : x_display->character_print = 1; break;
-      case XK_F4       : x_display->sprite_print = 1; break;
+      case XK_F1       :
+	printf("key : F1 Pressed\n");
+	x_display->color_map_print = 1;
+	printf("dump : color_map\n");
+	break;
+      case XK_F2       :
+	printf("key : F2 Pressed\n");
+	x_display->palette_print   = 1;
+	printf("dump : palette\n");
+	break;
+      case XK_F3       :
+	printf("key : F3 Pressed\n");
+	x_display->character_print = 1;
+	printf("dump : character\n");
+	break;
+      case XK_F4       :
+	printf("key : F4 Pressed\n");
+	x_display->sprite_print    = 1;
+	printf("dump : sprite\n");
+	break;
       }
     }
-
-    if (press) {
-      if (event->type == KeyPress) x_display->key_press |=  press;
-      else                         x_display->key_press &= ~press;
-    }
   }
 
   return;
@@ -259,7 +325,7 @@ XDisplay XDisplay_Create(int width, int height)
   XtVaSetValues(x_display->toplevel, XtNmaxHeight, x_display->height, NULL);
 
   x_display->key_press = 0;
-  x_display->lcd_draw = 1;
+  x_display->lcd_draw_level = 1;
 
   XtRealizeWidget(x_display->toplevel);
   while (!XtIsRealized(x_display->toplevel)) { /* None */ }
@@ -293,16 +359,7 @@ XDisplay XDisplay_Create(int width, int height)
     XSetFunction(x_display->display, x_display->color_gc[i], GXcopy);
   }
 
-  /* GCのデータベース初期化 */
-  x_display->color_gc_database =
-    XColorGCDatabase_Create(x_display,
-			    0,       /* studying_flag */
-			    1,       /* cache_flag */
-			    3,       /* cache_size */
-			    256,     /* hash_number */
-			    "black", /* background_color */
-			    16       /* gradation */);
-
+#ifdef USE_X_FONT
   /* フォントの確保 */
   x_display->font = XLoadFont(x_display->display, "8x16");
   x_display->font_gc = XCreateGC(x_display->display,
@@ -313,6 +370,24 @@ XDisplay XDisplay_Create(int width, int height)
 		 XDisplay_GetPixelFromColorName(x_display, "white"));
   XSetBackground(x_display->display, x_display->font_gc,
 		 XDisplay_GetPixelFromColorName(x_display, "black"));
+#endif
+
+  /* GCのデータベース初期化 */
+  /*
+   * XColorGCDatabase_Create() の後に XCreateGC() で他の GC の生成を行うと,
+   * なぜか XFreeGC() するときに Segmentation Fault を起こす
+   * (FreeBSD の場合の話.原因不明.他の OS (ていうか正確にはXライブラリ)
+   *  では試してない)ので,XColorGCDatabase_Create() はすべての GC を
+   * 作成した後に行う必要がある.
+   */
+  x_display->color_gc_database =
+    XColorGCDatabase_Create(x_display,
+			    0,       /* studying_flag */
+			    1,       /* cache_flag */
+			    3,       /* cache_size */
+			    256,     /* hash_number */
+			    "black", /* background_color */
+			    16       /* gradation */);
 
   XFillRectangle(x_display->display, x_display->lcd_window,
 		 x_display->color_gc[0],
@@ -362,17 +437,87 @@ XDisplay XDisplay_Destroy(XDisplay x_display)
 {
   int i;
 
-  if (x_display == NULL) return (NULL);
+  if (x_display == NULL)
+    WonX_Error("XDisplay_Destroy", "Object is not created.");
 
-  /* あとでリソースの解放を追加すること */
-  if (x_display->color_gc != NULL) {
-    for (i = 0; i < 16; i++) {
-      if (x_display->color_gc[i])
-	XFreeGC(x_display->display, x_display->color_gc[i]);
+  /* Xサーバと同期をとる */
+  /* True だと,イベントキュー内のイベントを廃棄する */
+  XSync(x_display->display, True);
+
+  /* トランスレーションのアンインストール */
+  XtUninstallTranslations(x_display->toplevel);
+
+  /* アクションの削除 */
+#if 0
+  /*
+   * 一度登録したアクションを削除することはできない.
+   * (同じアクション名で新しいアクションを登録して,上書きすることはできる)
+   */
+#endif
+
+  /* アイコンの削除 */
+#if 0
+  /* アイコンの削除処理が必要な場合にはここに書く.現状では必要無し */
+#endif
+
+  /* イベントハンドラの削除 */
+  XtRemoveEventHandler(x_display->toplevel, KeyPressMask | KeyReleaseMask,
+		       False, KeyHandler, x_display);
+  XtRemoveEventHandler(x_display->toplevel, ExposureMask,
+		       False, ExposeHandler, x_display);
+  XtRemoveEventHandler(x_display->toplevel, LeaveWindowMask | FocusChangeMask,
+		       False, LeaveWindowHandler, x_display);
+
+  /* GCのデータベース終了処理 */
+  if (x_display->color_gc_database) {
+    x_display->color_gc_database =
+      XColorGCDatabase_Destroy(x_display->color_gc_database);
+  }
+
+#ifdef USE_X_FONT
+  /* フォントの解放 */
+  if (x_display->font_gc) {
+    XFreeGC(x_display->display, x_display->font_gc);
+    x_display->font_gc = 0;
+  }
+  if (x_display->font) {
+    XUnloadFont(x_display->display, x_display->font);
+    x_display->font = 0;
+  }
+#endif
+
+  for (i = 0; i < 16; i++) {
+    if (x_display->color_gc[i]) {
+      XFreeGC(x_display->display, x_display->color_gc[i]);
       x_display->color_gc[i] = 0;
     }
   }
 
+  if (x_display->copy_gc) {
+    XFreeGC(x_display->display, x_display->copy_gc);
+    x_display->copy_gc = 0;
+  }
+
+  if (x_display->lcd_pixmap) {
+    XFreePixmap(x_display->display, x_display->lcd_pixmap);
+    x_display->lcd_pixmap = 0;
+  }
+
+  x_display->key_press = 0;
+  x_display->lcd_draw_level = 0;
+
+#if 0
+  if (x_display->app_context) {
+    XtDestroyApplicationContext(x_display->app_context);
+    x_display->app_context = 0;
+  }
+#endif
+
+  if (x_display->toplevel) {
+    XtDestroyWidget(x_display->toplevel);
+    x_display->toplevel = 0;
+  }
+
   free(x_display);
 
   return (NULL);
@@ -384,14 +529,21 @@ XDisplay XDisplay_Destroy(XDisplay x_display)
 
 int XDisplay_Sync(XDisplay x_display)
 {
-  XEvent event;
-
   XFlush(x_display->display);
 
   /* Xサーバと同期をとる */
   /* False だと,イベントキュー内のイベントを廃棄しない */
   XSync(x_display->display, False);
 
+  return (0);
+}
+
+int XDisplay_Flush(XDisplay x_display)
+{
+  XEvent event;
+
+  XDisplay_Sync(x_display);
+
   /* イベントの処理 */
   while (XtAppPending(x_display->app_context)) {
     XtAppNextEvent(x_display->app_context, &event);
@@ -570,7 +722,7 @@ int XDisplay_DrawLCDWindow(XDisplay x_display, WWDisplay ww_display,
 GC XDisplay_CreateGC(XDisplay x_display)
 {
   GC gc;
-  gc = XCreateGC(x_display->display, x_display->root_window, 0, 0);
+  gc = XCreateGC(x_display->display, x_display->lcd_window, 0, 0);
   return (gc);
 }
 

+ 7 - 2
XDisplay.h

@@ -17,7 +17,7 @@ typedef struct _XDisplay * XDisplay;
 
 #include <X11/Xlib.h>
 
-#include "wonx_include/key.h"
+#include "wonx/key.h"
 
 #include "WWDisplay.h"
 #include "WWLCDPanel.h"
@@ -33,7 +33,11 @@ Colormap XDisplay_GetColormap(XDisplay x_display);
 XColorGCDatabase XDisplay_GetColorGCDatabase(XDisplay x_display);
 
 unsigned int XDisplay_GetKeyPress(XDisplay x_display);
-int XDisplay_GetLCDDraw(XDisplay x_display);
+
+int XDisplay_GetLCDDrawLevel(XDisplay d);
+int XDisplay_SetLCDDrawLevel(XDisplay d, int level);
+int XDisplay_LCDDrawLevelDown(XDisplay d);
+int XDisplay_LCDDrawLevelUp(  XDisplay d);
 
 int XDisplay_GetColorMapPrint(XDisplay d);
 int XDisplay_GetPalettePrint(XDisplay d);
@@ -66,6 +70,7 @@ XDisplay XDisplay_Destroy(XDisplay x_display);
 /*---------------------------------------------------------------------------*/
 
 int XDisplay_Sync(XDisplay x_display);
+int XDisplay_Flush(XDisplay x_display);
 
 /*---------------------------------------------------------------------------*/
 /* ÉÁ²è                                                                      */

+ 9 - 2
XDisplayP.h

@@ -15,6 +15,11 @@
 #include <X11/Xatom.h>
 #include <X11/keysym.h>
 
+/*
+ * X のフォントを利用する.
+ */
+#define USE_X_FONT
+
 /*****************************************************************************/
 /* クラスの定義                                                              */
 /*****************************************************************************/
@@ -41,15 +46,17 @@ typedef struct _XDisplay {
   /* 4096色表示用のGCのデータベース(XFireworks から流用) */
   XColorGCDatabase color_gc_database;
 
+#ifdef USE_X_FONT
   /* テキストスクリーンへの文字表示用のフォント */
   Font font;
   GC font_gc;
+#endif
 
   /* キーの状態 */
   unsigned int key_press;
 
-  /* LCD描画のフラグ */
-  int lcd_draw;
+  /* LCD描画のレベル */
+  int lcd_draw_level;
 
   /* ダンプ出力のフラグ */
   int color_map_print;

+ 1 - 1
bank.c

@@ -5,7 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "wonx_include/bank.h"
+#include "wonx/bank.h"
 
 #include "WonX.h"
 

+ 5 - 2
challsrc.sh

@@ -1,4 +1,7 @@
 #!/bin/sh
 
-./filters.pl "qkc -e -u" ./sys2wonx.pl ./int2sint.pl -f $*
-
+if [ -x ./filters.pl ] ; then
+	./filters.pl "qkc -e -u" ./sys2wonx.pl ./int2sint.pl -f $*
+else
+	filters.pl "qkc -e -u" sys2wonx.pl int2sint.pl -f $*
+fi

+ 1 - 1
comm.c

@@ -10,7 +10,7 @@
 #include <sys/types.h>
 #include <sys/time.h>
 
-#include "wonx_include/comm.h"
+#include "wonx/comm.h"
 
 #include "wonx_configure.h"
 #include "WonX.h"

+ 1 - 1
disp.c

@@ -5,7 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "wonx_include/disp.h"
+#include "wonx/disp.h"
 
 #include "WonX.h"
 

+ 105 - 0
fcntl.c

@@ -0,0 +1,105 @@
+/*****************************************************************************/
+/* ここから                                                                  */
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "wonx_configure.h"
+
+#include "wonx/fcntl.h"
+
+#include "WonX.h"
+
+/*****************************************************************************/
+/* 互換関数の定義                                                            */
+/*****************************************************************************/
+
+/*
+ * void * でデータを渡す関数は,型を間違えるバグが入る可能性があるので,
+ * void * を適切な型に置き換えてある.
+ */
+
+/*
+ * Xサーバとの同期の整合性がとれなくなるなどの問題が考えられるので,
+ * 互換関数の内部は UNIXTimer_Pause(), UNIXTimer_Unpause() でくくり,
+ * タイマ割り込みを一時停止して処理を行う.また,unpause するまえに,
+ * かならず sync するようにする.
+ */
+
+/*
+ * タイマの一時停止の2重解除の問題が出てくるので,
+ * 互換関数から互換関数を呼んではいけない.
+ * (一時停止はネストされるが,いちおう)
+ * 似たような処理をする関数の場合は,必ず static な別関数に処理をまとめ,
+ * そっちを呼び出すようにすること.
+ * 引数の表示の問題もあるしね.
+ */
+
+/*
+ * mmap() が UNIX 標準のものと WonderWitch のものでコンフリクトしてしまうことの
+ * 対策.具体的な内容や理由は README を参照してください.
+ */
+#if 0
+void * wonx_mmap(char * filename);
+void * mmap = wonx_mmap;
+#endif
+#if 0
+#ifdef wonx_mmap
+#undef wonx_mmap
+#endif
+#endif
+
+void * wonx_mmap(char * filename)
+{
+  int size = 10;
+  FILE * fp;
+  int i, c;
+  char * p;
+  void * ret;
+
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : mmap() : filename = %s\n", filename);
+  fflush(stdout);
+
+  p = (char *)malloc(size);
+  if (p == NULL) WonX_Error("mmap", "cannot allocate memory.");
+
+  fp = fopen(filename, "rb");
+  if (fp == NULL) WonX_Error("mmap", "cannot open file.");
+
+  i = 0;
+  while ((c = fgetc(fp)) != EOF) {
+    if (i > size - 1) {
+      p = (char *)realloc(p, size);
+      if (p == NULL) WonX_Error("mmap", "cannot reallocate memory.");
+    }
+    p[i] = c;
+    i++;
+  }
+
+  fclose(fp);
+  ret = p;
+
+  WonXDisplay_Sync(WonX_GetWonXDisplay());
+
+  printf("call : mmap() : return value = 0x%p\n", ret);
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return (ret);
+}
+
+/*****************************************************************************/
+/* ここまで                                                                  */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* End of File.                                                              */
+/*****************************************************************************/

+ 9 - 5
filters.pl → filters.perl

@@ -1,4 +1,4 @@
-#!/usr/local/bin/perl
+#!PATH_TO_PERL
 
 while ($_ = shift(@ARGV)) {
 	if ($_ eq "-f"   ) { last; }
@@ -8,9 +8,13 @@ while ($_ = shift(@ARGV)) {
 
 while ($filename = shift(@ARGV)) {
 	$command = "cat $filename$filters > $filename.tmp";
-	print "$command\n";
-	system($command);
+	print STDERR "$command\n";
+	$ret = system($command);
+	if ($ret != 0) { die "Command not found. Install perl scripts.\n"; }
 	$command = "mv $filename.tmp $filename";
-	print "$command\n";
-	system($command);
+	print STDERR "$command\n";
+	$ret = system($command);
+	if ($ret != 0) { die "Command not found.\n"; }
 }
+
+exit (0);

+ 26 - 0
findperl.sh

@@ -0,0 +1,26 @@
+#!/bin/sh
+
+arg=${1}
+
+if   [ -n "${arg}" -a -x "${arg}" ]; then
+	whereperl="${1}"
+elif [ -x /usr/local/bin/perl ]; then
+	whereperl="/usr/local/bin/perl"
+elif [ -x /usr/pkg/bin/perl ]; then
+	whereperl="/usr/pkg/bin/perl"
+elif [ -x /usr/bin/perl ]; then
+	whereperl="/usr/bin/perl"
+elif which -s perl; then
+	whereperl=`which perl`
+else
+	echo "Cannot find perl." 1>&2
+	echo -n "Input path to perl as full path (Ex. /usr/bin/perl): " 1>&2
+	read whereperl
+	if [ ! -x $whereperl ]; then
+		echo "Error: cannot find perl." 1>&2
+		exit 1
+	fi
+fi
+
+echo "#!$whereperl"
+exit 0

+ 3 - 1
int2sint.pl → int2sint.perl

@@ -1,4 +1,4 @@
-#!/usr/local/bin/perl
+#!PATH_TO_PERL
 
 while (<STDIN>) {
 	s/([\s;\}\/])uint(\s)/$1unsigned int$2/g;
@@ -17,3 +17,5 @@ while (<STDIN>) {
 	s/_WONX_INT_/int/g;
 	print $_;
 }
+
+exit (0);

+ 19 - 7
key.c

@@ -5,7 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "wonx_include/key.h"
+#include "wonx/key.h"
 
 #include "WonX.h"
 
@@ -42,7 +42,7 @@ int key_press_check(void)
   printf("call : key_press_check() : \n"); fflush(stdout);
 
   x_display = WonXDisplay_GetXDisplay(WonX_GetWonXDisplay());
-  XDisplay_Sync(x_display);
+  XDisplay_Flush(x_display);
 
   ret = XDisplay_GetKeyPress(x_display);
 
@@ -70,7 +70,7 @@ int key_hit_check(void)
   printf("call : key_hit_check() : \n"); fflush(stdout);
 
   x_display = WonXDisplay_GetXDisplay(WonX_GetWonXDisplay());
-  XDisplay_Sync(x_display);
+  XDisplay_Flush(x_display);
 
   ret = XDisplay_GetKeyPress(x_display);
 
@@ -88,7 +88,7 @@ int key_hit_check(void)
 int key_wait(void)
 {
   XDisplay x_display;
-  int ret;
+  volatile int ret;
 
   if (!WonX_IsCreated()) WonX_Create();
 
@@ -101,13 +101,25 @@ int key_wait(void)
 
   /*
    * 以下はホットスポットになり得るので注意!
+   * key_wait() 中に割り込みを受け付けるために一時的にタイマを Unpause する.
+   * タイマ割り込みのコールバック関数中でキー入力の割り込み処理も行われるため,
+   * do~while ループ中での XDisplay_Flush() は必要無し.
+   */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+  /*
+   * タイマ割り込みによるキー入力処理に期待していったん Unpause するため,
+   * 再び Pause するまでは XDisplay の描画関連の関数などを呼び出しては
+   * いけないので注意.
+   * (XDisplay_GetKeyPress() は単に変数の値を返すだけなので問題無い)
    */
-
   ret = 0;
   do {
-    XDisplay_Sync(x_display);
+#if 0 /* タイマを Unpause しない場合には必要 */
+    XDisplay_Flush(x_display);
+#endif
     ret = XDisplay_GetKeyPress(x_display);
   } while (ret == 0);
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
 
   WonXDisplay_Sync(WonX_GetWonXDisplay());
 
@@ -177,7 +189,7 @@ int key_hit_check_with_repeat(void)
   printf("call : key_hit_check_with_repeat() : \n"); fflush(stdout);
 
   x_display = WonXDisplay_GetXDisplay(WonX_GetWonXDisplay());
-  XDisplay_Sync(x_display);
+  XDisplay_Flush(x_display);
 
   ret = XDisplay_GetKeyPress(x_display);
 

+ 1 - 1
libwwc.c

@@ -7,7 +7,7 @@
 
 #include "wonx_configure.h"
 
-#include "wonx_include/libwwc.h"
+#include "wonx/libwwc.h"
 
 #include "WonX.h"
 

+ 3 - 3
sample1.c

@@ -1,5 +1,5 @@
-#include "wonx_include/text.h"
-#include "wonx_include/key.h"
+#include "wonx/text.h"
+#include "wonx/key.h"
 
 main()
 {
@@ -12,7 +12,7 @@ main()
   text_put_string(0,  8, "   linked to program for    ");
   text_put_string(0,  9, "  WonderWitch and behave as ");
   text_put_string(0, 10, "        WonderWitch.        ");
-  text_put_string(0, 12, "WonX Copyright (c) 2000-2001");
+  text_put_string(0, 12, "WonX Copyright (c) 2000-2002");
   text_put_string(0, 13, "       Sakai Hiroaki.       ");
   text_put_string(0, 14, "    All Rights Reserved.    ");
   text_put_string(0, 16, "   Hit space key to exit.   ");

+ 2 - 2
sample2.c

@@ -1,5 +1,5 @@
-#include "wonx_include/disp.h"
-#include "wonx_include/key.h"
+#include "wonx/disp.h"
+#include "wonx/key.h"
 
 static unsigned char clear[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 static unsigned char block[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

+ 35 - 0
sample3.c

@@ -0,0 +1,35 @@
+#include "wonx/text.h"
+#include "wonx/fcntl.h"
+#include "wonx/key.h"
+
+#ifdef _WONX_
+#include "wonx/wonx.h"
+#endif
+
+main()
+{
+  char * p;
+  int x, y, i;
+
+  text_screen_init();
+  p = mmap("COPYING");
+
+#ifdef _WONX_
+  wonx_lcddraw_level_down();
+#endif
+
+  i = 0;
+  for (y = 0; y < TEXT_SCREEN_HEIGHT; y++) {
+    for (x = 0; x < TEXT_SCREEN_WIDTH; x++) {
+      text_put_char(x, y, p[i++]);
+    }
+  }
+
+#ifdef _WONX_
+  wonx_lcddraw_level_up();
+#endif
+
+  key_wait();
+
+  bios_exit();
+}

+ 2 - 1
service.c

@@ -4,7 +4,7 @@
 
 #include <stdio.h>
 
-#include "wonx_include/service.h"
+#include "wonx/service.h"
 
 #include "WonX.h"
 
@@ -40,6 +40,7 @@ void bios_exit()
 {
   printf("call : bios_exit() : \n");
   fflush(stdout);
+  if (WonX_IsCreated()) WonX_Destroy();
   exit (0);
 }
 

+ 1 - 1
sound.c

@@ -5,7 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "wonx_include/sound.h"
+#include "wonx/sound.h"
 
 #include "WonX.h"
 

+ 2 - 2
sout2str.pl → sout2str.perl

@@ -1,4 +1,4 @@
-#!/usr/local/bin/perl
+#!PATH_TO_PERL
 
 use FileHandle;
 
@@ -17,4 +17,4 @@ while (<STDIN>) {
 	}
 }
 
-# End of program
+exit (0);

+ 8 - 0
sys2wonx.perl

@@ -0,0 +1,8 @@
+#!PATH_TO_PERL
+
+while (<STDIN>) {
+	s/^(\s*\#\s*include\s*)[\<\"]sys\/(.+\.h)[\>\"]/$1\"wonx\/$2\"/i;
+	print $_;
+}
+
+exit (0);

+ 0 - 6
sys2wonx.pl

@@ -1,6 +0,0 @@
-#!/usr/local/bin/perl
-
-while (<STDIN>) {
-	s/^(\s*\#\s*include\s*)[\<\"]sys\/(.+\.h)[\>\"]/$1\"wonx_include\/$2\"/i;
-	print $_;
-}

+ 1 - 1
system.c

@@ -5,7 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "wonx_include/system.h"
+#include "wonx/system.h"
 
 #include "WonX.h"
 

+ 1 - 1
text.c

@@ -6,7 +6,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "wonx_include/text.h"
+#include "wonx/text.h"
 
 #include "WonX.h"
 #include "WWText.h"

+ 1 - 1
timer.c

@@ -6,7 +6,7 @@
 #include <stdlib.h>
 #include <time.h>
 
-#include "wonx_include/timer.h"
+#include "wonx/timer.h"
 
 #include "wonx_configure.h"
 #include "WonX.h"

+ 366 - 0
wonx.c

@@ -0,0 +1,366 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "wonx/wonx.h"
+
+#include "WonX.h"
+#include "WonXDisplay.h"
+#include "WWDisplay.h"
+#include "XDisplay.h"
+
+#include "WWColorMap.h"
+#include "WWPalette.h"
+#include "WWCharacter.h"
+#include "WWSprite.h"
+
+/*****************************************************************************/
+/* 外部に公開する WonX のサービス関数                                        */
+/*****************************************************************************/
+
+/*
+ * Xサーバとの同期の整合性がとれなくなるなどの問題が考えられるので,
+ * 互換関数の内部は UNIXTimer_Pause(), UNIXTimer_Unpause() でくくり,
+ * タイマ割り込みを一時停止して処理を行う.また,unpause するまえに,
+ * かならず sync するようにする.
+ */
+
+/*
+ * タイマの一時停止の2重解除の問題が出てくるので,
+ * 互換関数から互換関数を呼んではいけない.
+ * (一時停止はネストされるが,いちおう)
+ * 似たような処理をする関数の場合は,必ず static な別関数に処理をまとめ,
+ * そっちを呼び出すようにすること.
+ * 引数の表示の問題もあるしね.
+ */
+
+/* カラーマップ情報の出力 */
+void wonx_print_colormap_data(void)
+{
+  WWDisplay ww_display;
+
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_print_colormap_data() : \n");
+  fflush(stdout);
+
+  ww_display = WonXDisplay_GetWWDisplay(WonX_GetWonXDisplay());
+  WWColorMap_PrintData(WWDisplay_GetColorMap(ww_display), stdout);
+
+  WonXDisplay_Sync(WonX_GetWonXDisplay());
+
+  printf("call : wonx_print_colormap_data() : return value = none\n");
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return;
+}
+
+/* パレット情報の出力用内部関数 */
+static void _print_palette_data(int n)
+{
+  WWDisplay ww_display;
+  WWPalette ww_palette;
+  ww_display = WonXDisplay_GetWWDisplay(WonX_GetWonXDisplay());
+  ww_palette = WWDisplay_GetPalette(ww_display, n);
+  WWPalette_PrintData(ww_palette, ww_display, stdout);
+  return;
+}
+
+/* パレット情報の出力 */
+void wonx_print_palette_data(int n)
+{
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_print_palette_data() : number = %d\n", n);
+  fflush(stdout);
+
+  if ((n < 0) || (n > 16 - 1))
+    WonX_Error("wonx_print_palette_data", "number is out of range.");
+  _print_palette_data(n);
+
+  WonXDisplay_Sync(WonX_GetWonXDisplay());
+
+  printf("call : wonx_print_palette_data() : return value = none\n");
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return;
+}
+
+/* すべてのパレット情報を出力 */
+void wonx_print_all_palette_data(void)
+{
+  int n;
+
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_print_all_palette_data() : \n");
+  fflush(stdout);
+
+  for (n = 0; n < 16; n++) _print_palette_data(n);
+
+  WonXDisplay_Sync(WonX_GetWonXDisplay());
+
+  printf("call : wonx_print_all_palette_data() : return value = none\n");
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return;
+}
+
+/* キャラクタ情報の出力用内部関数 */
+static void _print_character_data(int n)
+{
+  WWDisplay ww_display;
+  WWCharacter ww_character;
+  ww_display = WonXDisplay_GetWWDisplay(WonX_GetWonXDisplay());
+  ww_character = WWDisplay_GetCharacter(ww_display, n);
+  WWCharacter_PrintData(ww_character, ww_display, stdout);
+  return;
+}
+
+/* キャラクタ情報の出力 */
+void wonx_print_character_data(int n)
+{
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_print_character_data() : number = %d\n", n);
+  fflush(stdout);
+
+  if ((n < 0) || (n > 512 - 1))
+    WonX_Error("wonx_print_character_data", "number is out of range.");
+  _print_character_data(n);
+
+  WonXDisplay_Sync(WonX_GetWonXDisplay());
+
+  printf("call : wonx_print_character_data() : return value = none\n");
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return;
+}
+
+/* すべてのキャラクタ情報を出力 */
+void wonx_print_all_character_data(void)
+{
+  int n;
+
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_print_all_character_data() : \n");
+  fflush(stdout);
+
+  for (n = 0; n < 512; n++) _print_character_data(n);
+
+  WonXDisplay_Sync(WonX_GetWonXDisplay());
+
+  printf("call : wonx_print_all_character_data() : return value = none\n");
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return;
+}
+
+/* スプライト情報の出力用内部関数 */
+static void _print_sprite_data(int n)
+{
+  WWDisplay ww_display;
+  WWSprite ww_sprite;
+  ww_display = WonXDisplay_GetWWDisplay(WonX_GetWonXDisplay());
+  ww_sprite = WWDisplay_GetSprite(ww_display, n);
+  WWSprite_PrintData(ww_sprite, stdout);
+  return;
+}
+
+/* スプライト情報の出力 */
+void wonx_print_sprite_data(int n)
+{
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_print_sprite_data() : number = %d\n", n);
+  fflush(stdout);
+
+  if ((n < 0) || (n > 128 - 1))
+    WonX_Error("wonx_print_sprite_data", "number is out of range.");
+  _print_sprite_data(n);
+
+  WonXDisplay_Sync(WonX_GetWonXDisplay());
+
+  printf("call : wonx_print_sprite_data() : return value = none\n");
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return;
+}
+
+/* すべてのスプライト情報を出力 */
+void wonx_print_all_sprite_data(void)
+{
+  int n;
+
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_print_all_sprite_data() : \n");
+  fflush(stdout);
+
+  for (n = 0; n < 128; n++) _print_sprite_data(n);
+
+  WonXDisplay_Sync(WonX_GetWonXDisplay());
+
+  printf("call : wonx_print_all_sprite_data() : return value = none\n");
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return;
+}
+
+/* 現在の表示/非表示のレベルの取得.(1以上で表示,0以下で非表示) */
+int wonx_get_lcddraw_level(void)
+{
+  XDisplay x_display;
+  int ret;
+
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_get_lcddraw_level() : \n");
+  fflush(stdout);
+
+  x_display = WonXDisplay_GetXDisplay(WonX_GetWonXDisplay());
+  ret = XDisplay_GetLCDDrawLevel(x_display);
+
+  WonXDisplay_Sync(WonX_GetWonXDisplay());
+
+  printf("call : wonx_get_lcddraw_level() : return value = %d\n", ret);
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return (ret);
+}
+
+/* 現在の表示/非表示のレベルの設定 */
+int wonx_set_lcddraw_level(int level)
+{
+  XDisplay x_display;
+  int ret;
+
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_set_lcddraw_level() : level = %d\n", level);
+  fflush(stdout);
+
+  x_display = WonXDisplay_GetXDisplay(WonX_GetWonXDisplay());
+  ret = XDisplay_SetLCDDrawLevel(x_display, level);
+
+  WonXDisplay_Flush(WonX_GetWonXDisplay());
+
+  printf("call : wonx_set_lcddraw_level() : return value = %d\n", ret);
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return (ret);
+}
+
+/* 表示レベルを下げる */
+int wonx_lcddraw_level_down(void)
+{
+  XDisplay x_display;
+  int ret;
+
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_lcddraw_level_down() : \n");
+  fflush(stdout);
+
+  x_display = WonXDisplay_GetXDisplay(WonX_GetWonXDisplay());
+  ret = XDisplay_LCDDrawLevelDown(x_display);
+
+  WonXDisplay_Flush(WonX_GetWonXDisplay());
+
+  printf("call : wonx_lcddraw_level_down() : return value = %d\n", ret);
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return (ret);
+}
+
+/* 表示レベルを上げる */
+int wonx_lcddraw_level_up(void)
+{
+  XDisplay x_display;
+  int ret;
+
+  if (!WonX_IsCreated()) WonX_Create();
+
+  /* タイマを一時停止する */
+  UNIXTimer_Pause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  printf("call : wonx_lcddraw_level_up() : \n");
+  fflush(stdout);
+
+  x_display = WonXDisplay_GetXDisplay(WonX_GetWonXDisplay());
+  ret = XDisplay_LCDDrawLevelUp(x_display);
+
+  WonXDisplay_Flush(WonX_GetWonXDisplay());
+
+  printf("call : wonx_lcddraw_level_up() : return value = %d\n", ret);
+  fflush(stdout);
+
+  /* タイマをもとに戻す */
+  UNIXTimer_Unpause(WonXSystem_GetUNIXTimer(WonX_GetWonXSystem()));
+
+  return (ret);
+}
+
+/*****************************************************************************/
+/* End of File.                                                              */
+/*****************************************************************************/

+ 0 - 0
wonx_include/bank.h → wonx/bank.h


+ 0 - 0
wonx_include/bios.h → wonx/bios.h


+ 0 - 0
wonx_include/comm.h → wonx/comm.h


+ 0 - 0
wonx_include/disp.h → wonx/disp.h


+ 11 - 1
wonx_include/fcntl.h → wonx/fcntl.h

@@ -7,7 +7,7 @@
  * fcntl.h は /usr/include/fcntl.h を読み込めばよいので,
  * 本当はこのファイルでは,
  * #include <fcntl.h>
- * するだけにしたいのだが,これだと -Iwonx_include のようにしてコンパイル
+ * するだけにしたいのだが,これだと -Iwonx のようにしてコンパイル
  * している場合に,自分自身を読み込んでしまう可能性があるので,
  * #include </usr/include/fcntl.h>
  * として,自分自身を読み込まないように,/usr/include を明示している.
@@ -29,4 +29,14 @@
 #include </usr/include/fcntl.h>
 #include </usr/include/sys/fcntl.h>
 
+/*
+ * mmap() が UNIX 標準のものと WonderWitch のものでコンフリクトしてしまうことの
+ * 対策.具体的な内容や理由は README を参照してください.
+ */
+#include </usr/include/stdio.h>
+/* void * mmap(char * filename); */
+void * wonx_mmap(char * filename);
+/* #define wonx_mmap mmap */
+#define mmap wonx_mmap
+
 #endif

+ 0 - 0
wonx_include/filesys.h → wonx/filesys.h


+ 0 - 0
wonx_include/indirect.h → wonx/indirect.h


+ 0 - 0
wonx_include/key.h → wonx/key.h


+ 0 - 0
wonx_include/libwwc.h → wonx/libwwc.h


+ 0 - 0
wonx_include/oswork.h → wonx/oswork.h


+ 0 - 0
wonx_include/process.h → wonx/process.h


+ 0 - 0
wonx_include/service.h → wonx/service.h


+ 0 - 0
wonx_include/sound.h → wonx/sound.h


+ 0 - 0
wonx_include/system.h → wonx/system.h


+ 0 - 0
wonx_include/system_configure.h → wonx/system_configure.h


+ 0 - 0
wonx_include/text.h → wonx/text.h


+ 0 - 0
wonx_include/timer.h → wonx/timer.h


+ 0 - 0
wonx_include/types.h → wonx/types.h


+ 43 - 0
wonx/wonx.h

@@ -0,0 +1,43 @@
+#ifndef _WONX_SYS_WONX_H_
+#define _WONX_SYS_WONX_H_
+
+#include "service.h"
+
+/*****************************************************************************/
+/* 外部に公開する WonX のサービス関数                                        */
+/*****************************************************************************/
+
+/* カラーマップ情報の出力 */
+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);
+
+/* 現在の表示/非表示のレベルの取得.(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);
+
+#endif

+ 5 - 1
wonx_configure.h

@@ -3,13 +3,17 @@
 #ifndef _WONX_wonx_configure_h_INCLUDED_
 #define _WONX_wonx_configure_h_INCLUDED_
 
-#include "wonx_include/libwwc.h"
+#include "wonx/libwwc.h"
 
 /* デフォルトのアーキテクチャ */
 #define WONX_DEFAULT_ARCH HARDARCH_WSC
 
 /* WonX でのタイマ割り込みの周期(単位はミリ秒) */
+#if 1
 #define WONX_TIMER_INTERVAL 100 /* 0.1 秒 */
+#else
+#define WONX_TIMER_INTERVAL 1   /* デバッグ用(0.001 秒) */
+#endif
 
 /* HBLANK, VBLANK 割り込みのデフォルトのインターバル(0.1秒単位) */
 #define WONX_HBLANK_INTERVAL ( 3 * 10) /*  3 秒毎 */