PSP xvi

PSPプログラミングを教えるブログ(本気で頑張る人アクセス大歓迎サイト)

PSP-X.gif

記事の間違いを報告  新アップローダー
記事修正情報 PSPプログラミング資料 自作ゲーム PSP用エミュレータ リンク

公認リンク
公式PSP専科 公式PSVita専科 はじめるPSPSDK PSP EXEC GAME M@STER PSP 猫山のYouTubeチャンネル

TAG
全記事にタグをつけています  http://nekoyama2gillien.blog36.fc2.com/?tag=タグ
PSP PSPプログラミング DXライブラリPortable OSLib ショートプログラム ハローワールド
PSP自作ゲーム PSP自作ソフト エミュレータ ゲームアーカイブス PSP動画
動画 初音ミク ミクミクダンス MMDドラマ ゲーム 魔法少女まどか☆マギカ 侵略!イカ娘
アイドルマスター

このブログについて

このブログでは、非公式のPSPソフト、いわゆる自作ソフト( PSP Homebrew )を作る事を目的とします。

著作権などの こまかい利用規約については、こちらを開いてお読み下さい

このブログについて知りたい方、初めて来訪された方はこちらを開いてお読みください
お問い合わせは 猫山猫宗(nekomune@gmail.com)までどうぞ


当ブログはリンクフリーです。ブログ名は、アルファベットで「PSP xvi」と書いて『ピーエスピー・エクシビ』とお読みください。
相互リンクを希望されるブログ運営者様は、ココで申請して下さい。


このブログで全記事から探し物の方は、ここをクリックして下さい。
http://nekoyama2gillien.blog36.fc2.com/?all

スポンサーサイト 

--/--/--
--. --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[edit]

CM: --
TB: --

page top

前回、32ビットカラーについて 詳しく解説したので、今回は V-RAM のアドレス等について詳しく書きます。
PSPの画面解像度は、横:480ピクセル×縦:272ピクセルですが、V-RAM構成横:512ピクセル×縦:272ピクセルとなっています。
中途半端な数値ですねwwwwww

でも、512(10進数)は 0x200(16進数)、272(10進数)は 0x110(16進数)なので、コンピュータにとっては都合の良い数値なのですよ。ふふふ(笑)。

で、実際に V-RAM は どういう構成か書くと、32ビットカラーモードの場合、画面左上(0,0)がV-RAM先頭で、順に右端へ+4(色のバイト数だけプラス)で座標(1,0)のV-RAMアドレスになり、1ラインは512x4(色のバイト数) = 2048バイトです、(0,1)は 先頭V-RAM に2048を足した値です、PSP の V-RAM は2メガ(2,228,224)バイトです(0x220000)、となります。

これを踏まえて、32ビットカラーモードでの、(X,Y)座標から V-RAMのアドレス(オフセット値)を求める計算式を書きます。

     こたえ = ( X + ( Y x 512 )) x 4
      展開して   Xx4 + Yx2048


Xはそのまま足して、Yは単純に512倍すれば良いのです。それらを色のバイト数(32ビットカラーは4バイト)分の数値だけ掛けてやれば良い、という事。
つまり、X を 4倍して、Y を 2048倍する。

が しかし、人間もコンピュータも、掛け算 割り算 は足し算 引き算の繰り返しで答えを求めている、という事実。文字の表示処理の度に、毎回 2048倍 などしていたら処理速度が遅くなります(2048回 足している、という罠)。

そこで、C言語 C++言語 にある シフト演算というのを使ってみます。

   書き方の例
        a=a<<n      b=b>>n

シフト演算というのは、値を 2進数で考えて上位方向(左)や下位方向(右)へ nビット ずらす(移動させる)、という演算です。
シフト演算は 演算を行なう変数のキャストにより、算術演算になったり論理演算になったりします。
下位(右)方向への算術シフト演算では符号ビットの値は複写されます。


よって、下位(右)方向への算術シフト演算の場合は、一番左(最上位ビット)が 1(マイナス)の場合は右に1ビット シフトすると、全部のビットが右に1ビットずれて 最上位ビットに 符号ビットである 1(マイナス)が複写されます。

例1:
int x = 0x80000000;
x=x>>1;

  x の値(実行結果)
   2進数:10000000 00000000 00000000 00000000 16進数:0x80000000
              ↓
       下位(右)方向に1ビット分シフト
              ↓
   2進数:11000000 00000000 00000000 00000000 16進数:0xC0000000

  ◆ x の値は 0xC0000000 になりました。

例2:
int x = 0xA0000000;
x=x>>1;

  x の値(実行結果)
   2進数:10100000 00000000 00000000 00000000 16進数:0xA0000000
              ↓
       下位(右)方向に1ビット分シフト
              ↓
   2進数:11010000 00000000 00000000 00000000 16進数:0xD0000000

  ◆ x の値は 0xd0000000 になりました。


一方、上位(左)方向へのシフト演算の場合は、符号ビットに関係なく、そのまま全部のビットがずれます。空いたビット(右側から順に、のビット)には0が入ります。符号の変化に気をつけて下さい。

例3:
int x = 0x80000000;
x=x<<1;

  x の値(実行結果)
   2進数:10000000 00000000 00000000 00000000 16進数:0x80000000
              ↓
       上位(左)方向に1ビット分シフト
              ↓
   2進数:00000000 00000000 00000000 00000000 16進数:0x00000000

  ◆ x の値は 0 になりました。これはオーバーフロー(桁あふれエラー)です。


アセンブラ言語では、左にシフトしてハミ出たビットが右から順に入る、という 輪っか みたいな概念の ローテート演算というのがありますが、シフト演算は 輪っかという概念が無く、ハミ出たらそれまで! 空いた部分は0 か符号ビットの複写を入れとけ! という演算です。

(シフト演算の演算結果同士を 論理和 でくっつけて、ローテート演算が実現できたりします)

算術シフトの場合、
上位方向(左)へ n ビットシフト演算すると、値が 2のn乗倍になります。
下位方向(右)へ n ビットシフト演算すると、値が 2のn乗分の1倍になります。

  例 1  6<<5
       6を5ビット分、左へ算術シフト演算

   (1ビット分、左へシフト)  6の 2倍 =  12
   (2ビット分、左へシフト)  6の 4倍 =  24
   (3ビット分、左へシフト)  6の 8倍 =  48
   (4ビット分、左へシフト)  6の16倍 =  96
   (5ビット分、左へシフト)  6の32倍 = 192
    答え   192

  例 2  4096>>7
       4096を7ビット分、右へ算術シフト演算

   (1ビット分、右へシフト)  4096の 2分の1 =  2048
   (2ビット分、右へシフト)  4096の 4分の1 =  1024
   (3ビット分、右へシフト)  4096の 8分の1 =  512
   (4ビット分、右へシフト)  4096の 16分の1 =  256
   (5ビット分、右へシフト)  4096の 32分の1 =  128
   (6ビット分、右へシフト)  4096の 64分の1 =  64
   (7ビット分、右へシフト)  4096の128分の1 =  32
    答え    32



そんな訳で、シフト演算を用いて、座標の計算を書くと、下記の様になります。

                 (X + ( Y x 512 )) x 4
               = ( X + ( Y<< 9 ))<<2
               = X<<2 + Y<<11

                 ↑↑ すっきりしました(笑)


PSP画面の V-RAMアドレス は、0x04000000 からで、オフセット値が 0x40000000 で、フレームサイズは 0x88000 バイト あるので、コレを考慮して V-RAMアドレス を求めると、

define FRAMESIZE 0x88000 //in byte
char *pg_vramtop=(char *)0x04000000;

pg_vramtop+(pg_drawframe?FRAMESIZE:0)+(x<<2)+(y<<11)+0x40000000


という計算でおっけーです。
途中の演算 pg_drawframe?FRAMESIZE:0 というのは、
pg_drawframeなら FRAMESIZE つまり、0x88000
pg_drawframeなら
という値を取得する式です。こういう使い方をするモノだと覚えておけば良いでしょう。



『画面を青く塗りつぶすプログラム』 実行画面
FILL_BLUE_sample00.png



『画面を青く塗りつぶすプログラムソース』の一部抜粋を見たい方は続きを読んで下さい。
画面を青く塗りつぶすプログラムのダウンロード
Fill_Blue.zip  123 KB (126,854 バイト)
DOWNLOAD
(ソースのコンパイルには、全角文字表示ライブラリが必要)
(ソースコード付き / CFW用の実行ファイル付き)


[部分抜粋です]

////////////////////////////////////////////////////////////////
// pg.c から抜粋
////////////////////////////////////////////////////////////////


//constants
#define PIXELSIZE 1 //in short
#define LINESIZE 512 //in short
#define FRAMESIZE 0x88000 //in byte

//variables
char *pg_vramtop=(char *)0x04000000;
long pg_screenmode; // 画面モ-ド の値を入れておく
long pg_showframe; // 表示フレーム(0 or 1)を保存
long pg_drawframe; // 描画フレーム(0 or 1)を保存

// 書き込みする V-RAM アドレスを取得する関数( pg.c に収録 )
unsigned char *pgGetVramAddr(unsigned long x,unsigned long y)
{
return(pg_vramtop+(pg_drawframe?FRAMESIZE:0)+(x<<2)+(y<<11)+0x40000000);
}

void pgFillvram(unsigned long color) // PSP画面を color の色で 塗りつぶし関数
{
unsigned char *vptr0; //pointer to vram
unsigned long i;

vptr0=pgGetVramAddr(0,0);
for (i=0; i<FRAMESIZE/2; i++)
{
*(unsigned long *)vptr0 = color;
vptr0 += PIXELSIZE*4;
}
}

////////////////////////////////////////////////////////////////
// main.c から抜粋
////////////////////////////////////////////////////////////////

#include "pg.h"
#include "zenkaku.h"

int main(int argc,char **argv)
{
setupCallbacks();
/* Gu初期化 */
sceGuInit();
sceGuStart(GU_DIRECT, list);
sceGuDrawBuffer(GU_PSM_8888, SCRBUF0, BUF_WIDTH);
sceGuDispBuffer(SCR_WIDTH, SCR_HEIGHT, SCRBUF0, BUF_WIDTH);
sceGuFinish();
sceDisplayWaitVblankStart();
sceGuDisplay(GU_TRUE);


pgFillvram(AO_IRO); // ← pg.c にあります / 画面を青色で塗りつぶし

do // ループ
{
readpad(); // ← pg.c にあります
mh_print( 12,240,"画面を青く塗りつぶしました。",WHITE); // 白色
mh_print( 12,258,"×ボタンを押すと終了。",YELLOW); // 黄色
}while((now_pad&PSP_CTRL_CROSS)==0); // ×ボタンが押されるまでループ

sceKernelExitGame();
return 0;
}
関連記事
スポンサーサイト

[edit]

CM: 0
TB: 0

page top

この記事に対するコメント

page top

コメントの投稿

Secret

page top

トラックバック

トラックバックURL
→http://nekoyama2gillien.blog36.fc2.com/tb.php/95-9bfb5120
この記事にトラックバックする(FC2ブログユーザー)

page top


h o m e |


 

2017-03