2013年6月16日日曜日

V2.1のバグとその回避方法

X-BASIC for iOS V2.1に以下のバグが発見されました。
  1. vpriority()が即時反映されない
  2. tBackgroundAlpha()/gBackgroundAlpha()/kBackgroundAlpha()が即時反映されない
  3. gTransform()で変形をかけた状態で終了した時、次回の実行時に画面サイズがおかしくなる
  4. inputで入力中の文字が表示されない
  5. dim floatに{}で初期値を指定するとエラーになる
  6. 配列を引数に持つ関数の中で、子関数にその配列を渡すときエラーが発生する
  7. 配列の2次元目以降の要素番号チェックが正しくない
  8. 外部関数内で発生したエラーのメッセージが表示されない
  9. 実行時エラーの指す行がずれている

最後の5つ以外はV2.2で修正されますが、当面の回避策は以下の通りです。
  1. vpriority()を設定した後に以下の関数を呼び出すことで即時反映されます。
    func allPageUpdate(page;int)
      print " ";:// ここはテキスト表示に問題ないように変更すること
      apage(GPAGE0):line(0,0,0,0,0)
      apage(GPAGE1):line(0,0,0,0,0)
      apage(GPAGE2):line(0,0,0,0,0)
      apage(GPAGE3):line(0,0,0,0,0)
      apage(page)
    endfunc
    例えば、vpriority(page,GPAGE0,GPAGE1,GPAGE2,TPAGE):allPageUpdate(page)
  2. 関数呼び出し後、それぞれの画面を書き換える関数を呼び出すと同時に反映されます。
    たとえば、tBackgroundAlpha():print " "など。
  3. プログラム終了時にgTransform()として変形を解除しておけば回避できます。
  4. これはV2.1で画面表示を高速化したことによるエンバグです。回避策がありません。V2.2をお待ちください。
  5. (要素番号)=で1つ1つ代入してください
  6. これは回避策がありません。V2.3をお待ちください。
  7. 要素番号チェックは自前で行ってください。
  8. これは回避策がありません。V2.3をお待ちください。
  9. ほとんどの場合、実行時エラーは1つ下の行を指しています。その下の行がコメント行の場合は、さらにその下を指します。



また、以下は仕様です。
  • 内部関数で配列を引数にする時、そのサイズ指定にenum定数を使えない
    「例」func f(masu(WW,WW);int):// エラー発生
これは、以下の理由に依ります。
  1. 内部関数の名前と引数の登録は、コンパイルの前処理で行われている
  2. enum定数の決定はコンパイル中に行われる
  3. このため、内部関数定義中は定数が未定
これを解決するのは極めて難しく、使われる頻度と実装やデバッグの労力を考えた結果、 「仕様として制限する」ことにしました。 あしからず、ご了承ください。

どうしても即値で記述するのが嫌なら、要素数そのものを省略すればいいでしょう。
   「例」func f(masu(,);int)
(次元を表す ',' は省略不可。)

2013年6月15日土曜日

V2.1での変更などに関する注意点

X-BASIC for iOS V2.1 について、いくつか補足説明をしておきます。

(1)vpage()の引数が変わっていますが、実際の動作は変わりありません。
これは、V1.0前=発売前の関数仕様の変更が、取説と引数に反映できていなかっただけです。
V1.0でも、指定したページを表示、指定されてないページは非表示にするよう動作しており、第2引数は無視されていました。

V2.1ではこの動作を取説に明記すると同時に、第2引数を省きました。
互換性維持のため、第2引数を指定していても問題なく動作します。


(2)以下の関数について、取説に重要な変更や補足をしました。
    keyRepeatTime()
    width()

(3)bitmap関数の仕様が拡張されたように見えますが、実はもともとこの仕様であり、取説が間違っていただけです(というか、作った本人が仕様を勘違いしていた^_^;)。
内蔵取説は修正されていませんが、HPでの公開版は修正済みです。

2013年6月12日水曜日

「X-BASIC for iOS」の次バージョンの開発状況(V2.2)

「X-BASIC for iOS」v2.2の開発状況などをお知らせします。

ご要望や報告は、この記事にコメントを付けて下さい。

・・・

V2.2(審査中)
・画面描画を約60%高速化
・PIC/CUT/JPEG/PNG/GIF/BMPヘッダー読み取り関数を追加
・MAGファイルローダー追加・magHeader()実装
・YES/true/NO/falseをenum定数に変更
・コントロールコード:カーソル位置から画面最後までを消す、を追加
・locate()で座標が画面内にあるかどうかをリターン値で返せるようにした
 また、座標補正を一部変更した
・tBackgroundColor()/gBackgroundColor()/sBackgroundColor()/sBorder()追加
・tBackgroundAlpha()/gBackgroundAlpha()/kBackgroundAlpha()が即時有効でなかったのを修正
・vpriority()が効いてなかったのを修正
・gTransform()をかけた状態で終了した時、次回の実行時に画面サイズがおかしくなるのを修正
・bitmapPattern()/getBitmapSize()を追加
・picLoader()/cutLoader()/magLoader()に fNoBitmapClose引数を追加
・picLoader()/cutLoader()/bitmapImageFile()で画面幅以上の画像を表示するとき、縮小して全体をいれこむようにした
・hexstrToArray()追加
・hexchr$()でセパレーターを追加
・setTouchArea()/setTouchAreaWithText()で合成RGB指定できるようにした
・devicePlatform()を追加;機種を正確に識別する
・inputで入力中の文字が表示されない(キーボードに隠れている)のを修正
・サンプルの一部をiPhone/iPod touch画面に正式に対応させた
・a_setPlayData()で同時に登録できる音声ファイルを64に拡大した
・getWidth()のwxも省略できるようにした
・bitmapを使用したあとにプログラムを終了するとメモリを確保したままになっていたのを修正
・gFileStatus()追加
・ファイル名に""を与えると落ちるのを修正(該当関数多数)
・printの"文字列"中にコントロールコードが含まれていた時の挙動がおかしいので修正
・print using "+%%"の結果がおかしいのを修正
・小バグ/サンプルバグ/取説誤記修正

スプライトの高速化中止(メモリ利用量が多すぎる)


2013年6月7日金曜日

実行時におかしい動作をする/コンパイルエラーが出る時に調べる点(随時追記)

実行時におかしい動作をした時に調べる点をあげておきます。

・表示がおかしい(1)
文字、文字列の表示そのものや、tatrb()/tcolor()で表示属性をつけた時に、おかしな表示になる時は、まずは文字コードを疑ってください。

X-BASIC for iOSの標準の文字コードはUTF-8です。
このコードはASCII範囲(&h20〜&h7e)こそ1バイトでSHIFT-JISと同じですが、半角カナや全角文字は全くコードが異なります。

このため、ASCIIにしか対応してない文字列関数やstr[i]による文字列内1バイト取り出しを使うと、予期しないコードを返すことがあり、またそれを表示しようとすると、表示そのものだけでなく属性も正常に処理されません。

どうしても内部処理を SHIFT−JISで行いたいときは、強制SHIFT-JISモードをオンにしてください。

なお、X-BASIC for iOSにはX68にあった、複数バイトコードは1バイトずつ出力しても正常表示される、という機能はありません。これは強制SHIFT-JISモードでも同じです。


・表示がおかしい(2)
タッチエリアを画面外にまたぐように設定すると、以後のテキスト表示がおかしくなることがあるようです。
タッチエリアは必ず画面内に収まるように設定してください。

・表示がおかしい(3)
画面がちらつくときは、vpriority()の引数も確認してみてください。
例えば、vpriority(TPAGE,B_SPAGE,GPAGE0,GPAGE1,GPAGE2,GPAGE3)とかすると画面がちらつく上テキスト画面が表示されなくなります。定数名が間違っている=引数の値が異常になっているのが原因です。
エラーが出ないのでわかりにくいですが、おかしい時は、まず引数を確認して下さい。

・画面が表示されない
グラフィックもしくはスプライト 画面を非透明の黒で描画していませんか?
X68では黒=透明でしたが、iOSでは黒と透明は厳密に異なります。
黒は透過しませんので、それでうめつくされた画面より優先順位が下になる画面は見えなくなります。特にBG画面は、設定によっては1スプライトの設定で全画面非透明になることがあるので要注意です。
vpriority()で優先順位を入れ替えて表示が見えるようになる場合は、100%これが原因です。

・TABをはじめコントロールコードが表示されてない
仕様書をよく読みましょう。
iOS版では高速化のため、コントロールコードはその1文字だけ表示する場合のみ処理されます。
従って、freads()などで読み込んだテキストファイル内文字列をそのままprintすると、結果が異なることになります。
内部的には、';'や','で区切った場合も別表示と見なしますので、うまく処理するとよいでしょう。

・ case 定数=値と書いていてもエラーにならない
これは、定数と値の比較式を評価した結果をcase値にしているからです。人間の理解上では間違っているように見えますが、BASICの式としては正しいのでエラーにはなりません。
すなわち、定数=値は比較式であり、このように実質上定数の比較式はコンパイル時に演算されてしまいます。
この場合、もし定数=値ならばcase -1相当で有り、定数<>値ならcase 0相当となります。
だから、エラーにならないのです。
もし、case -1またはcase 0相当式が同一swicth~endswitch内にあれば、エラーになります。

・bitmapでfdirect=YESなのに描画データが読めない
100%、apage()が描画対象のページ以外になっています。
確認してください。

・タッチキーでエリア外なのにキーコードが返ってくる
タッチエリアを、全く同じ座標域で重複設定している場合に発生します。
ループで処理を戻す場合などは、必ず、前回の設定をremoveTouchArea()で解除してから再設定してください。

・line()などでstyleを設定しても思った通りに描画されない。
styleの設定値にはiOSによる制約があります。そのためX-BASIC/68と同じ値を設定しても同じ描画になるとは限りません。
詳しくは取説をご覧ください。

・a=b=cの結果が違う
C言語ではこの式は
     b=c
     a=b
と等価で、a/b共にcの値が代入されますが、X-BASICでは
     a=(b=c)
と等価であり、(b=c)すなわち、bとcが等しいかどうかの評価結果がaに代入されます。
(その値はtrue=-1またはfalse=0です。)
Cから移植すると間違いやすいので注意してください。

・if 文でandを使う時の式評価順に注意
X-BASICのandは、C言語の&&とは意味が異なります。それは&に相当します。それぞれの意味は以下のようになります。
X-BASIC;if A and B
AとBを両方評価し、結果をandする。
だから、常にA式とB式両方が評価されます。

C ; if (A && B)
Aを評価し、成立したらBを評価する。
だから、Bは評価されないことがあります。

C ; if (A & B)
AとBを評価し、結果を&する。
だから、常にA式とB式両方が評価されます。
X-BASICのandはこちらに相当します。

ということなので、X-BASICでAが成立する時だけBが評価されることを想定するなら、
if A then {
    if B then ...
}
と記述する必要があります。

・func文の所で変数二重宣言エラーが発生する
関数の引数名が関数名と同じだったとき発生します。
関数の引数名は関数名と同じにしないでください。

なおこれはX-BASIC/68では発生しませんが、ぺけ-BASICで発生します。
両者の数少ない非互換部分です。


・落ちる/iOSに戻ってしまう
V2.4ではかなり安定しています。
この状態でも落ちるのは、再帰呼び出しが深すぎることがほとんどです。
例えば
func f()
  f()
endfunc
とすれば、確実に落ちます。再帰呼び出しでスタックを使い尽くすためです。残念ながら、iOSレベルでスタックの残り量を知るすべが無いため、安全性のチェックはなされていません。
V2.6では再帰呼び出し段数(正確には再起でなく異なる関数の呼び出し続けも同じ)に制約をつけましたので、関数内部でのローカル変数定義数にもよりますが、およそ落ちることはなくなるはずです。

あともう1つ、X-BASIC/68で書き込まれたfloatのデータを(ファイルを経由して)そのままiOS版で表示しようとすると落ちることがあります。浮動小数点数値フォーマットが異なるため、表示できずこうなります。
float6880()で変換して表示してください。


・関数呼び出しのある行で未宣言変数、関数、配列のエラーが出る
これはほぼ100%関数宣言側に問題があります。
funcがfuneになっているとか。


・X-BASIC/68作られたファイルを読むと値が異なる
この理由はメモリ上におけるデータのバイト並びの違いによります。68000はいわゆるビッグエンディアンでH→Lの順で格納されますが、iOS機器のARMはリトルエンディアンでL→H順です。
交互変換にはint6880()やfloat6880()関数を使います(V2.5以降で有効)。
なお、スプライトなどのパレットデータについては、さらに色コードの違いもあります。
x68Color2iOSColor()で変換します。

2013年6月1日土曜日

エラーメッセージ別対処法(随時追記)

X-BASIC for iOSのエラーメッセージは、残念ながらエラーの発生している場所や原因を的確に表していない場合があります。

理由の1つは、「エラーが発生したらその行の解析を飛ばし、次の行からコンパイルを継続するから」です。コンパイル時には1つのエラーでいちいち止めていては全体のデバッグに時間がかかりすぎるため、エラー発生行をなかったことにして無理やりコンパイルを継続して、全体のエラーを「制限付きながら」洗い出します。
そのためにこの現象が起きます。

このため、対となる構文がある行では、見かけ上間違いがなくても必ずエラーが発生します。例えば、switchの行でエラーが発生すれば、endswitchの行でも必ず(場合によってはcase/defaultの文でも)エラーが発生するわけです。

オリジナルのぺけ-BASICやX-BASIC/68は1つエラーが発生すればそこで止まるため、それ以降の解釈の継続という考え方がなく、故に同様なことが発生しません。

・・・

X-BASIC for iOSではできるだけエラーを細分化しましたが、解釈の都合上、エラー直接原因とは場所でエラーが発生することもあります。
この場合、発生するエラーからは原因がわかりづらいこともあります。


その例をここにまとめておきます。
(今後、発見次第随時紹介。)

・未宣言変数/Undefined variable.   (日本語/英語の順)
 
未定義関数を呼びだそうとした時もこれが発生することがあります。
関数を配列と認識してしまった場合です。
C言語と異なり、BASICでは関数も配列も()で括るため、こうなります。

・文字列が閉じてないときは、その影響で色々とエラーが発生することがあります
文字列のある行でエラーが発生している場合、まずは文字列が閉じられているか確認してください。

X-BASIC for iOSのごめんなさい(随時追記)

X-BASIC for iOSの、各種「ごめんなさい」部分を述べておきます。

関数の命名規則がバラバラ
pic_load()だったりpicLoader()だったり。前者はX68に多く、後者はApple的です。
今後、X68にない関数はApple的に統一していく予定です(V2.1でだいぶ行いました)。
すでに存在する関数名についも、互換性のためそのまま残します。
同一機能の関数に複数名称あるのは主にそのためです。


関数動作がX-BASIC/68と微妙に異なる
X-BASIC for iOS は基本的にX-BASIC/68やぺけーBASICと互換性がありますが、それは内部ステートメントと機種依存しない外部関数だけで、機種やOS依存の部分は、同名関数であっても同一動作をするとは限りません。

特に表示系はiOSや機種に強く依存するため、表示結果がX68と微妙に異なることが多々あります。おそらく特にわかりにくいのが透明の概念でしょう。

 X68では黒=透明であり、ページを重ねている場合はその部分は透けてみます。
逆に言えば、助けさせるためには黒で塗れば良いです。
ところが、iOSでは黒と透明は全く異なるものです。黒で塗った部分は、重ねあわさせても黒であり、透過しません。その上、透明度を持った色で「そのまま」描画しようとすると、元々そこにあったパターンと合成してしまいます。単純に 置き換わらないのです。
これを回避するにはblend()で合成方法を変更する必要があります。

X−BASIC for iOSはBASIC/68のプログラムをそのまま動かすことを目的としたのではなく、「iOSに比較的簡単に移植する」ことを目的としたため、必要以上にX68と動作が一緒になるようにはしていません。そのため、こういう部分があります。

もし「完全互換動作」を求める声が多ければ、それを別の外部関数として実装するという手もあるでしょうが、現在の状況では(時間的そして経済的に)不可能です。


意図しない範囲まで描画される
iOS版のグラフィック座標は実数です。これは何を意味するかというと、物理的なドットの間にも仮想的なドットが存在すると想定していると言うことです。これにより、アンチエイリアスなどを実現しています。

しかしこれがゆえに、指定した範囲よりも広く実描画されることがあります。なので、X68でドット単位で正確に領域を限定して描画していた物は、それが維持できなることがあります。具体的には、ある領域に描画して、その後そこを消そうとした場合、消したはずなのに一部残る、という現象が発生します。

残念ながら、この現象はアンチエイリアス機能をOFFにしても解消しません。描画方法をプログラム的に調整するしかありません。

一番手っ取り早いのは、描画をbitmap関数で行うことです。bitmap関数は整数座標であり、アンチエイリアスもないので、指定した座標に正確に描画されます。


fopen()のリターンが異なる
開発時に参考にしていた文献の間違いのため、X68版とリターン値の範囲が異なります。
X-BASIC/68では正常で>=0ですが、iOS版では>=1です。ただし、X68版のソースを動かす場合は範囲が広いだけなので問題にはなりません(だから余計に気がつかなかった)。
万が一、X68に移植することがあれば注意してください。

すでにiOS上の多数のサンプルで使われているため、変更できませんでした。

V2.5からfclose()/fcloseall()のリターン値の値が取説上(定数名として)変わっていますが、値そのものは同じです。


外部関数のエラーチェックが異なる
外部関数内におけるエラーチェックに関しては、重要なもの以外、ほとんど再現していません。理由は簡単で「いちいち調べるのが面倒だった」からです。
基本的には、X68版のほうがエラーチェックが厳しいので、それで動いていたものはiOS版でも大丈夫と思われます。
iOS版は引数の範囲が規定外だった時、多くの場合規定範囲内に自動的に補正するのでエラーは発生しません。
エラーが発生することを想定している場合は、呼び出し側でチェックしてください。

注意すべきはfopen()で、X68版ではファイルがオープンできない時外部関数エラーが発生して停止しますが、iOS版では標準ではリターン値としてエラーコードを返してくるだけでエラーは発生しません。
したがって、エラーで止まることを前提にして作られたプログラムは、必ずエラーチェックを追加する必要があります。
X68版iOS版
fp=fopen("file","r") fp=fopen("file","r")
if fp<=0 then print "file error":end
V2.6からはerror on2で、fopen()のファイルオープンエラーでも、エラーで停止させるように出来ます。

なお、X-BASIC/68のプログラムではfopen()のリターン値=ファイルポインタを得ずにfread()などのfp値に固定数値を与えている行儀の悪いものが散見されます(Oh!X掲載のプログラムにも結構あった)。
そういうものはすべからく誤動作しますので、必ずfopen()でfpを得てそれを与えるようにしてください(そういうプログラムはBCを通してCに変換するとほぼ確実に誤動作します)。



スプライト機能は重い
これはひとえに私の技量不足からくるものですが、X68のスプライト、特にBG画面との重ね合わせは、実現するにはかなり面倒な処理が必要です。スプライト機能をX68互換を捨てて実装すればもう少し高速化も可能だったかもしれませんが、ここだけは資産を生かすため出来るだけX68互換を維持したかったので、現在のようになっています。

BGを使わないようにすれば、多少省メモリと高速化されます。

現在のスプライトでは、iPad1においてはスプライトのみ(BGなし)を、移動せず固定的に表示するのが精一杯です。iPad2以降やiPod touch4ではCPUやGPUの性能向上や、画面サイズによりおよそ問題ない性能が出ています。

ただ、やはり重いのは重いので、電池の消耗が激しいです。

BGを使わなくても遅いです。BGとの重ね合わせは処理が重いのはわかっているのですが、スプライトのみで使っても異様に遅い原因はわかっていません。
シミュレーター上では十分な速度で動いていても、実機;特にiPad1/2ではものすごく遅いです。スプライト使わず、グラフィックで描いたほうが早いくらい。

移動せず、固定的に、重ねあわせられるもう1画面として使うのが関の山かもしれません。
現状では、限定された利用しかできないようです。ごめんなさい。
OpenGLなどで書きなおせば早くなるのかしら?
今のところ、その技量はないですが。

・・・

今後、思い出し次第追記します。

2013年5月26日日曜日

その他サンプルプログラム

その他のサンプルプログラムをまとめました。
これらは主に、各ステートメントや関数の試験用です。

Zipファイル : XBtests.zip