少しずつソースコードを開示したいと思います。
とりあえずVRAMの管理部分から…
/*VRAM上のアドレスを管理するための構造体*/
#define VRAMCTRLFLAGS_EXIST 0x01
#define VRAMCTRLFLAGS_STATIC 0x02
typedef struct tagDXPVRAMCTRL
{
union
{
u32 offset;
void* address;
};
u32 size;
u8 flags;
}DXPVRAMCTRL;
#define VRAMARRAYNUM (2*1024) /*確保できるVRAM領域の最大数(≒テクスチャの最大数)*/
static u8 vramdata[2*1024*64 + 1]; /*VRAMの使われている場所を記憶する16byte単位。最後のは番兵*/
static DXPVRAMCTRL vramarray[VRAMARRAYNUM + 1];/*確保済みVRAMの情報保持*/
static u32 vramfree; /*あとどれくらい空いているのか*/
void InitVRAM();
DXPVRAMCTRL* AllocVRAM(int Size,int StaticFlag);
void FreeVRAM(DXPVRAMCTRL *VRamCtrl);
//static void DeflagVRAM(){}
void InitVRAM()
{
int i;
for(i = 0;i < 2 * 1024 * 64;++i)vramdata[i] = 0x00;
vramdata[2 * 1024 * 64] = 0x01;
for(i = 0;i < VRAMARRAYNUM;++i)
{
vramarray[i].address= 0;
vramarray[i].flags = 0;
vramarray[i].size = 0;
}
vramarray[VRAMARRAYNUM].flags = VRAMCTRLFLAGS_EXIST;
}
DXPVRAMCTRL* AllocVRAM(int Size,int StaticFlag)
/*静的フラグが立っている場合は逆方向から検索する。若干の改良(?)*/
{
int i,j,df;
if(Size > vramfree)return NULL;
if(Size % 16)Size += 16 - Size % 16;/*確保するサイズが16で割り切れない場合は補正*/
df = 0;
if(!StaticFlag)
{
i = 0;
FREEAREASERCH:
while(vramdata[i])++i; /*使われていない場所を検索*/
if(i >= 2 * 1024 * 64)return NULL;/*番兵にぶつかったか、みょんな力が働いたかのどちらか*/
for(j = 0;i + j < 2 * 1024 * 64 && j < (Size >> 4);++j);/*連続して空いているのか確認*/
if(i + j >= 2 * 1024 * 64)return NULL;
if(j < (Size >> 4))goto FREEAREASERCH;/*連続してなかったら検索しなおす*/
}
else
{
i = 2 * 1024 * 64;
FREEAREASERCH_STATIC:
while(vramdata[i])
{
--i; /*使われていない場所を検索*/
if(i < 0)return NULL;
}
for(j = 0;i - j >= 0 && j < (Size >> 4);++j);/*連続して空いているのか確認*/
if(i - j < 0)return NULL;
if(j < (Size >> 4))goto FREEAREASERCH_STATIC;/*連続してなかったら検索しなおす*/
i = i + 1 - j; /*iを場所の先頭にもってくる*/
}
/*ここまでで空き領域検索終了。データ検索に入ります*/
j = 0;
while(!(vramarray[j].flags & VRAMCTRLFLAGS_EXIST))++j;
if(j == VRAMARRAYNUM)return NULL;
/*検索終了♪*/
for(k = 0;k < Size;++k)vramdata[i + k] = 0x01;
vramarray[j].offset = i * 16;/*16バイト境界前提なのでw*/
vramarray[j].size = Size;
vramarray[j].flags = VRAMCTRLFLAGS_EXIST |
(StaticFlag ? VRAMCTRLFLAGS_STATIC : 0)
;
return vramarray + j;
}
void FreeVRAM(DXPVRAMCTRL *ptr)
{
int i;
if(ptr == NULL)return;
if(!(ptr->flags & VRAMCTRLFLAGS_EXIST))return;
if(ptr < vramarray || ptr >= vramarray + VRAMARRAYNUM)return;
for(i = (ptr->offset >> 4);i < (ptr->size >> 4);++i)vramdata[i] = 0x00;
ptr->address = 0;
ptr->flags = 0;
ptr->size = 0;
}
ちょっとみょんな仕様になっています。
AllocVRAMを呼ぶとDXPVRAMCTRLへのポインタを返す仕様です。
えー、なんでこんな仕様で作ったかというと、VRAMの内部でデフラグみたいなことができるようにするためです。ポインタで渡しておけば大本の場所の情報の変更ですむので。
まだデフラグのルーチン組んでませんがねwwww
なんでVRAMをデフラグしたいかというと、兎にも角にもPSPのVRAMがちっちゃいからです。2MByteしかありません。
画面用のバッファが二枚必要なのですが、16bitカラーで確保した場合でも512*272*2*2=544Kbyte必要になります。既にVRAMの1/4も使われてます。
当然のごとく32bitカラーの場合VRAMの1/2が画面バッファになってしまうという…仕様です。
これで無駄な領域ができたりしたらもう…考えたくありません。
そこで、VRAMのデフラグです。テクスチャなんて一度作ったら消すまでサイズは変わりませんからWindowsのアレみたいな弊害も出ないです。
ですが、間違って画面バッファを移動したりしたら…最低な事態になります。なにが表示されるんでしょうか… あ、気になる。今度実験でもしますw
そこで移動不可なものにはVRAMCTRLFLAGS_STATICフラグを立てることにしてます。
多分これで大丈夫だと思います。多分ね…
追記
ああああ・・・・タブが無視されてソースコードの表示がひどいことに…orz FC2ブログのばかやろぅー
さらに追記(081209)
このソースコードちょっとバグってます。修正は完了していますが、更新がめんどうなので来週あたりに全コードとバイナリを公開する予定なのでそれを待ってください。
0 件のコメント:
コメントを投稿