OSECPU-ASKA入門 #0011

  • (by K, 2013.06.20)

(0) はじめに

  • 以下の記事はosecpu111dのWindows版を前提にしています。他の版を使っている場合は適宜読み替えてください。
    • ちなみにpage0074を読めばrev2の最新版が見つかります。


(1) drawPointとfillOvalとdrawLine(ついでにmodeについて)

  • api_drawPoint(mode, color, x, y); :
    • 画面に点を打ちます。xとyは座標です。colorは色です。modeの意味はfillRectと同じです。画面からはみ出しちゃいけないというルールも同じです。
    • 点の大きさを指定するパラメータはありません。大きな点を描きたいときは、fillOvalやfillRectで代用してください。
  • api_fillOval(mode, color, xsiz, ysiz, x0, y0); :
    • 画面に円もしくは楕円(だえん)を描きます。このパラメータ、実はfillRectと全く同じです。ではどういう円が描かれるかですが、このパラメータで指定される長方形を想像して、そこから角を削って丸くしてください。そのような円もしくは楕円が描画されます。
    • ということで、 x0, y0 は円の中心ではなく、円の端(はし)でもなく、仮想的な長方形の左上の座標です。分かりにくくてすみません!
  • api_drawLine(mode, color, x0, y0, x1, y1); :
    • 画面に線を引きます。 x0, y0 が始点で、 x1, y1 が終点です。水平な線、垂直な線ももちろんかけますが、斜めもOKです。
    • 線の太さなどを指定するパラメータはありません。太い線が引きたいときは、ずらしながら何本も引きましょう。
  • modeについて:
    • グラフィックス系命令の最初にいつも付いてくるmodeパラメータですが、MODE_COL24とMODE_COL3以外にどんな意味があるかを紹介します。
    • MODE_PSET: PSET描画モード: もとの画素の色が何色であるかに関係なく、上書きします(デフォルト)。
    • MODE_OR: OR描画モード: たとえば赤の上に緑で描画すると、黄色になります(0xff0000と0x00ff00のOR演算の結果が0xffff00になるから)。
    • MODE_XOR: XOR描画モード
    • MODE_AND: AND描画モード
    • MODE_COL3: 色指定方法を8色モードに
    • MODE_COL24: 色指定方法をフルカラーモードに
    • 16: 画面外への描画をエラーにしないで無視させる(2014.06.20時点では未実装)

(2) とりあえずここまでで

  • とりあえずここまでで、日本の国旗を描いたこのプログラムについてはほぼ分かったと思います。
       api_fillRect(MODE_COL3, 7, 640, 480, 0, 0);
       api_fillOval(MODE_COL3, 1, 300, 0, 320-150, 240-150);
  • ちなみに引き算しているのは、円の中心を(320,240)にしたくて、そこから円の半径を引いて左上の座標を計算しているのです。引き算などしないで、170や90と直接書いても全く同じ結果になります。
  • ここまでの説明だけで、この絵の色を変えることも中心の丸の大きさを変えることも、楕円(だえん)にすることも、きっとできるでしょう。
  • さらには円を何個も重ねてダーツの的(まと)みたいな絵も描けるでしょうし、楕円の中に楕円を書いて、眼みたいなものだって描けるでしょう。アイデア次第で何でもできます。
  • 点も描けますし線も引けます。
  • 分からないのは変数の使い方だけです。


  • どのプログラムに共通している最初の行の #include "osecpu_ask.h" は決まり文句みたいなものだと思ってください。

(3) 整数型変数

  • C言語やそのほかの言語では整数型にたくさんの種類がありますが、OSECPU-ASKAは単純化されていて一種類しかありません。Int32sというものだけです。これで21億くらいまでの整数を表現できます。マイナスの数もOKです。
  • OSECPU-ASKAでは原則として変数をメモリに割り当てることはしません(ここが他の言語とは違う!)。必ずレジスタに割り当てます。レジスタというのはCPUが持っている演算用の記憶域のことで、DRAMとかにあるメモリとは違うものです。このような仕様なので、変数のアドレスという概念はありません(メモリ上にないものはポインタで指し示すことができない)。
  • 以下のような構文で変数を宣言することができます。
    Int32s i:R00;
  • これはiという変数を宣言しており、R00というレジスタに割り当てられます。要するに、iはR00の別名でしかないのです。
  • 変数名は大文字小文字を区別しますので、iとIを使い分けることができます。
  • レジスタ名はR00~R3Fまでが有効ですが(後ろの2桁は16進数になっている)、とりあえずR00~R1Fまでを自由に使うのがいいと思います。・・・これは言い換えれば32個しかないということでもあります。変数は最大で32個しか作れないのです!これはつらい!!
    • でもx86のアセンブラの32bitモードとかだと8個しかなかったんです、だからOSECPUはこれでも相当に「リッチ」なのです。
    • はい、そこの人、少ないとか嘆いていてはいけませんよ。page0035をよく読んでください。あなたのやりたいことのためには32個では不十分かもしれませんが、まずは32個で何か面白いことはできないかなと考えるのです。
    • もちろんもっとたくさん使う方法はちゃんとありますが、いきなりそれを説明すると理解できないこと間違いなしので、まずは32個のレジスタを使いこなせるようになってからです。
  • レジスタ名は必ず大文字でお願いします。r00では未定義の変数名だと思われてエラーになります。R0aもだめです。R0Aでお願いします。
  • 変数宣言ですが、コンマで区切って一文で複数を宣言することもできます。
    Int32s i:R00, j:R01, xyz:R02;
  • なお、同じレジスタを割り当ててしまうというひどい(?)こともできます。
    Int32s i:R00, j:R00, k:R00;
  • この場合、iに代入したらjやkの値も変わってしまうことになります。というかR00に3つの別名を与えているだけなんですけどね。


  • 変数には整数を代入することができます。簡単な計算もできます。
    i = 10;
    i = j + k;
    i *= -1;
  • 基本的にC言語でかかれるような演算式はたいてい受け付けます。?演算子みたいな凝ったものはありません。割り算は、整数の割り算しかないので、答えは切り捨てになります。ゼロで割ってはいけません。
  • 関数の値を代入する、ということは現状ではできません。
    i = api_openWin(...); // こういうことはできない.
    • (将来的にはできるようにしたいと思っていて構文も設計したのですが、2014年内の実装予定はありません)
  • なお変数を使わずにいきなりレジスタ名を書いてしまうこともできますし、混在させることもできます。
    R04++;
    R03 = i + 1;
  • まあなんというか、いろいろやっていると、あれ?これがうまく行かないんだけど・・・という例が出てくると思います。そういう時は迷わずこのwikiのimpressionsあたりで聞いてみてください。きっと未サポートか、バグです。バグだった場合は、貴重なバグ報告ですので、直したいと思います。
    • なお報告の際は、長いプログラムを見せられても困ってしまいますので、再現に必要な最低限度のプログラムを用意してもらえると助かります。再現コードを作る過程は、報告者の勘違いだった、というケースを排除するためにも非常に有用です。


  • そうやって変数に狙った値が入れられるようになったら、それをAPIの呼び出しの際に利用することができます。
    api_drawPoint(MODE_COL24, c, x, y);
  • ええとここで注意なのですが、APIの呼び出しの際に変数を使うときは、できれば数式にならないようにしてほしいです。
    api_drawPoint(0, x - 1, y, c); // こういうのはつらい.
  • なんかもしかしたら数式入れても平気だったりするかもしれませんが、しかしそこはあまり得意じゃないことにかわりはないので、数式を入れる代わりに結果を一度別の変数に入れて、その変数を指定してもらえると助かります。

つづく

こめんと欄


コメントお名前NameLink

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2014-06-20 (金) 16:04:21 (2896d)