kikakubu.hの作成
メモ帳に以下の内容を書き、kikakubu.hという名前でcc65/includeに保存します。
/////////////////////////////////////////////////////////////////////////////////
// 2010.11.30 ver 0.14
// 企画で使うなり個人で使うなり似るなり焼くなりお好きにどうぞ。
// -----------------------------------------------------------------------------
// なん実企画部
// http://www37.atwiki.jp/kikakubu4/
/////////////////////////////////////////////////////////////////////////////////
#define REGIST_PPU_CTRL1 (char*)0x2000
#define REGIST_PPU_CTRL2 (char*)0x2001
#define REGIST_PPU_STS (char*)0x2002
#define REGIST_SPR_ADR (char*)0x2003
#define REGIST_SPR_GRA (char*)0x2004
#define REGIST_SCROLL (char*)0x2005
#define REGIST_ADR (char*)0x2006
#define REGIST_GRA (char*)0x2007
#define REGIST_DMA (char*)0x4014
#define JOYPAD (char*)0x4016
#define BTN_A 0x80
#define BTN_B 0x40
#define BTN_SELECT 0x20
#define BTN_START 0x10
#define BTN_UP 0x08
#define BTN_DOWN 0x04
#define BTN_LEFT 0x02
#define BTN_RIGHT 0x01
#define GUN_TRIGGER 0x10
#define GUN_HIT 0x08
#define MIC_USE 0x04
unsigned char padinfo[2][2];
unsigned char padother;
//コントローラ確認
void CheckPad()
{
unsigned char i,j,ret;
*JOYPAD = 1;
*JOYPAD = 0;
padother= 0;
for(i=0; i < 2; i++) {
padinfo[i][1] = padinfo[i][0];
padinfo[i][0]= 0;
for(j=0; j < 8; j++) {
ret = *(JOYPAD + i);
padinfo[i][0] <<= 1;
padinfo[i][0] += (ret & 0x01);
padother |= (ret & 0x0F);
}
}
}
//ボタン押しっぱなし player:0=1P , 1=2P
char ButtonDown(unsigned char player,unsigned char btn)
{
if(padinfo[player][0] & btn) {
return 1;
} else {
return 0;
}
}
//ボタン押す
char ButtonPush(unsigned char player,unsigned char btn)
{
if((padinfo[player][0] & btn) && ! (padinfo[player][1] & btn)) {
return 1;
} else {
return 0;
}
}
//マイク・光線銃など
char ControlOther(unsigned char btn)
{
if(padother & btn) {
return 1;
} else {
return 0;
}
}
// PPUコントロールレジスタの初期化
void InitPPU()
{
*REGIST_PPU_CTRL1 = 0x00;
*REGIST_PPU_CTRL2 = 0x00;
}
// PPUコントロールレジスタの設定
void SetPPU(unsigned char flag1,unsigned char flag2)
{
*REGIST_PPU_CTRL1 = flag1;
*REGIST_PPU_CTRL2 = flag2;
}
// スクロール設定
void SetScroll(unsigned char x, unsigned char y)
{
*REGIST_SCROLL = x;
*REGIST_SCROLL = y;
}
//背景設定(繰り返し)
void FillBackground(unsigned char address1, unsigned char address2, unsigned char val, unsigned char cnt)
{
char i;
*REGIST_ADR = address1;
*REGIST_ADR = address2;
for (i = 0; i < cnt; i++)
{
*REGIST_GRA = val;
}
}
//背景設定
void SetBackground(unsigned char address1, unsigned char address2, unsigned char *bg, unsigned char cnt)
{
char i;
*REGIST_ADR = address1;
*REGIST_ADR = address2;
for (i = 0; i < cnt; i++)
{
*REGIST_GRA = *(bg + i);
}
}
//座標から背景のアドレス計算
void GetBackgroundAddress(unsigned char screen, unsigned char x, unsigned char y, char *ret)
{
unsigned int pos;
switch (screen) {
case 0: //左下
pos = 0x2000;
break;
case 1: //右下
pos = 0x2800;
break;
case 2: //左上
pos = 0x2400;
break;
case 3: //右上
pos = 0x2c00;
break;
}
pos += y * 0x20 + x;
*(ret + 0) = (pos & 0xff00) >> 8;
*(ret + 1) = pos & 0x00ff;
}
//属性設定(繰り返し)
void FillAttribute(unsigned char address1, unsigned char address2, unsigned char val, unsigned char cnt)
{
FillBackground(address1,address2,val,cnt);
}
//属性設定
void SetAttribute(unsigned char address1, unsigned char address2, unsigned char *atr, unsigned char cnt)
{
SetBackground(address1,address2,atr,cnt);
}
//パレット設定
void SetPalette(unsigned char *palette,unsigned char sprite)
{
char i;
*REGIST_ADR = 0x3f;
if (sprite) {
*REGIST_ADR = 0x10;
} else {
*REGIST_ADR = 0x00;
}
for (i = 0; i < 16; i++)
{
*REGIST_GRA = *(palette + i);
}
}
//スプライト設定
void SetSprite(unsigned char first,unsigned char x,unsigned char y,unsigned char index,unsigned char flag)
{
if (first) {
*REGIST_SPR_ADR=0x00;
}
*REGIST_SPR_GRA=y;
*REGIST_SPR_GRA=index;
*REGIST_SPR_GRA=flag;
*REGIST_SPR_GRA=x;
}
//DMA転送領域初期化
void InitDMA(unsigned char *address)
{
unsigned char i;
for(i=0; i < 256; i++) {
*(address + i)=0;
}
}
//DMA転送準備
void SetDMA(unsigned char *address,unsigned char first,unsigned char x,unsigned char y,unsigned char index,unsigned char flag)
{
static unsigned char cnt;
if (first) { cnt = 0; }
*(address + cnt + 0)=y;
*(address + cnt + 1)=index;
*(address + cnt + 2)=flag;
*(address + cnt + 3)=x;
cnt+=4;
}
//DMA転送
void SendDMA(unsigned char address)
{
*REGIST_DMA = address;
}
//VBlank待ち
void VBlank()
{
while (! (*REGIST_PPU_STS & 0x80) );
}
//0爆弾待ち
void ZeroSprite()
{
while ( (*REGIST_PPU_STS & 0x40) );
while (! (*REGIST_PPU_STS & 0x40) );
}
kikakubu.hの解説
- CheckPad:コントローラの確認。基本的に毎回呼び出す。
- ButtonDown:押されたボタンの確認。(押し続ける)
- ButtonPush:押されたボタンの確認。(押す→離す)
- ControlOther:マイク・光線銃の確認。
- InitPPU:PPUコントロールレジスタの初期化。
- SetPPU:PPUコントロールレジスタの設定。
- flag1:PPUコントロールレジスタ1の設定。
- bit7:VBlank時にNMIを実行
- bit6:PPUマスター/スレーブセレクト
- bit5:スプライトサイズ(0:8x8,1:8x16)
- bit4:BGパターンテーブルアドレス(0:$0000,1:$1000)
- bit3:スプライトパターンテーブルアドレス(0:$0000,1:$1000)
- bit2:PPUアドレスインクリメント(0:+1,1:+32)
- bit0,1:表示するネームテーブルアドレス番号(00:$2000・左下、01:$2400・左上、10:$2800・右下、11:$2C00・右上)
- flag2:PPUコントロールレジスタ2の設定。
- bit5-7:bit0=1のとき背景色/bit0=1のとき色強調
000:なし・001:緑・010:青・100:赤(それ以外の数字は不可)
- bit4:スプライト表示(0:非表示,1:表示)
- bit3:BG表示(0:非表示,1:表示)
- bit2:スプライトクリップ(0:画面の左8ドットを表示しない,1:クリップなし)
- bit1:BGクリップ(0:画面の左8ドットを表示しない,1:クリップなし)
- bit0:ディスプレイタイプ(0:カラー,1:モノクロ)
- SetScroll:背景のスクロール。
- FillBackground:背景の設定(繰り返し)。
- address1:出力開始位置(上位2バイト)
- address2:出力開始位置(下位2バイト)
- val:出力内容(マスの番号)
- cnt:出力を繰り返す数
- SetBackground:背景の設定。
- address1:出力開始位置(上位2バイト)
- address2:出力開始位置(下位2バイト)
- *bg:出力内容のポインタ
- cnt:出力内容のバイト数
- GetBackgroundAddress:座標から背景のアドレスを算出。
- screen:画面(0:左下・初期画面,1:右下,2:左上,3:右上)
- x:横位置。
- y:縦位置。
- *ret:アドレスを格納する1バイト×2の配列
- SetPalette:パレットの設定。
- *palette:パレット内容のポインタ
- sprite:0:背景用パレット 1:スプライト用パレット
- FillAttribute:属性(背景4マス×4マス毎にどのパレットを使うか)の設定。(繰り返し)
- address1:出力先(上位2バイト)
- address2:出力先(下位2バイト)
- val:出力内容
- cnt:出力を繰り返す数
- SetAttribute:属性(背景4マス×4マス毎にどのパレットを使うか)の設定。
- address1:出力先(上位2バイト)
- address2:出力先(下位2バイト)
- *atr:出力内容のポインタ
- cnt:出力内容のバイト数
- SetSprite:スプライトの設定。
- first:1=1つ目のスプライト 0=2つ目以降
- x:横位置
- y:縦位置
- index:何コマ目の画像を表示するか
- flag:表示条件
- 7bit:上下反転
- 6bit:左右反転
- 5bit:背景よりも後ろに表示
- 0,1bit:パレット番号
- SetDMA:DMA転送準備。(スプライト用領域の設定)
- *address:スプライト用領域の開始アドレス
- first:1=1つ目のスプライト 0=2つ目以降
- x,y,index,flag:SetSpriteと同内容。
- SendDMA:DMA転送
- address:スプライト用領域の開始アドレスの三桁目 0x1=0x0100
- VBlank:VBlank待ち処理。
- ZeroSprite:0爆弾待ち処理。
※SetRegister・SetBackground・SetAttribute・SetPaletteは便宜上分けているだけで、中でやっている処理は同じです。
※FillBackgroundとFillAttributeも同様。
留意事項
- SetBackgroundによる描画が間に合わない場合、背景がまだらに表示されます。
VBlank()
SetBackground(0x20,0x00,(char *)bg,32);
SetScroll( 0, 0 );
- 一時的に背景の描画を停止し、その間に描画することで回避できます。
SetPPU(0x08,0x06);
SetBackground(0x20,0x00,(char *)bg,32);
SetScroll( 0, 0 );
SetPPU(0x08,0x1e);
VBlank();
SetBackground(0x20,0x00,(char *)bg,10)
SetScroll( 0, 0 );
VBlank();
SetBackground(0x20,0x0a,(char *)bg,10)
SetScroll( 0, 0 );
VBlank();
SetBackground(0x20,0x14,(char *)bg,12)
SetScroll( 0, 0 );
- SetBackgroundを呼び出さずにベタに処理を書くとより効果的です。
(#defineの使用は問題ありません。)
*REGIST_ADR = 0x20;
*REGIST_ADR = 0x00;
*REGIST_GRA = 0;
*REGIST_GRA = 1;
:
:
*REGIST_GRA = 31;
最終更新:2010年12月04日 00:20