秋休み中 | //www.旧型、PSP開発幼稚園.game.jp/(本館)

秋休み中

■ふう、秋もお休み中ですう。現実世界はキビシーからひと働やっぱ休まんとイカんです。わあ冬休み楽しみ♪
そりゃともかくsegalagaそろそろテストROMとしての職責(?)をはたさなくなってきたんで、過去にダウングレード。
sp_A00

これは何が言いたいかというと、「セガャラガ」は256x240モード。つまり32カラムモードのテストだった訳です。んが320x240モード、
つまり40カラムモードのテストROMが欲しい。そこで、VDPコマンドの12番つまり(0x0c)を発行して、40カラムモードにしてみたのです。
(註:反転機能をまだ考慮してないからハグッタよーな迷路画面は、迷路の幅が256ドットだからワカルでしょう。タブン)

んでソース。 /* utils.c*/ static void init_vdp(void) { ushort *pw; register uchar *pb; pw = (ushort *) VDP_CNTL; /* Lifted the struct from gens 2.12 .*/ /* 0 UINT8 Set1; */ *pw = 0x8014; /* reg. 80 - Enable HBL */ /* 1 UINT8 Set2; */ *pw = 0x8174; /* reg. 81 - Enable VBL */ /* 2 UINT8 Pat_ScrA_Adr; */ *pw = 0x8238; /* reg. 82 - Plane A =E000 */ /* 3 UINT8 Pat_Win_Adr; */ *pw = 0x8338; /* reg. 83 - " " */ /* 4 UINT8 Pat_ScrB_Adr; */ *pw = 0x8406; /* reg. 84 - Plane B =C000 */ /* 5 UINT8 Spr_Att_Adr; */ *pw = 0x857F; /* reg. 85 - sprite table begins at $FE00 */ /* 6 UINT8 Reg6; */ *pw = 0x8600; /* 7 UINT8 BG_Color; */ *pw = 0x8700; /* background color */ /* 8 UINT8 Reg8; */ *pw = 0x8800; /* 9 UINT8 Reg9; */ *pw = 0x8900; /*10 0x0a UINT8 H_Int; */ *pw = 0x8a08; /* generate a HLI every 8 lines */ /*11 0x0b UINT8 Set3; */ *pw = 0x8b00; /*12 0x0c UINT8 Set4; */ *pw = 0x8c01; /*40 cell*/ // ---- si-- // s shadow/highlight 0:off 1:on // i interlace 0:off 1:on // ? // c H_Cell s__c 0__0:32 cell // c H_Cell s__c 0__1:40 cell // c H_Cell s__c 1__0:40 cell??(どうもこうなるらしい) // c H_Cell s__c 1__1:40 cell /*13 0x0d UINT8 H_Scr_Adr; */ *pw = 0x8d08; /*14 0x0e UINT8 Reg14; */ *pw = 0x8e00; /*15 0x0f UINT8 Auto_Inc; */ *pw = 0x8f02; /*16 0x10 UINT8 Scr_Size; */ *pw = 0x9000; /*17 0x11 UINT8 Win_H_Pos; */ /*18 0x12 UINT8 Win_V_Pos; */ <以下略> どっかでみたよーなそーすだなあ?ってsegadriveからのコピペですね!もっと言っちまえばGens2.12からのコピペ。 VDPコマンドはどおやって使うのかとゆーと、こーやって使うのです。(これでワカンナイならのーみそタン使ってないカモネ) えっと、しょうがないな。マジメ(?)に解説すると、「頭(MSB)はビット立てるつまりxxx|=0x8000;だにゃ」そんでとにかく、 「VDPレジスタ番号」、「VDPレジスタに入れる引数」。になる訳。例えば0x0cレジスタに0xffを入れたかったら、*pw=(0x8000)|(0x0c<<8)|(0xff);に、 なる訳ですね。(註:「pw」はshortのポインタで「0x00c00004」番地を指してる。「0x00c00004」番地はVDPのコントロールポート) とにかく、「*pw = 0x8c01; /*40 cell*/」にしてみた、「セガャラガ」とは、「そこだけが違う」(現状、あとは同じもの)。 んだが、OBJが表示されねー。何でOBJ出ないんだろと、少し調べる必要がある訳です。 ちなみに、256で(仮想画面の)パターンがミラーになってるのは、現状そーゆーモードになってるからで、モード変えれば(仮想画面のサイズ) 簡単に直るのです。マダやってないケド、えっと確かVDPコマンドの16番(0x10)だったよな。 つまり「/*16 0x10 UINT8 Scr_Size; */ *pw = 0x9000;」を変えないと...。
(2006-09/03、04:44) とゆー訳でやってみる。「*pw = 0x9000;」を「*pw = 0x9001;」にしたダケ。 SP_A00_2 それにしても、OBJはどおやって出すんだーうぉーwwん。 (2006-09/03、07:00)
PSP実機に転送し、segadriveA33でチェック。なんとOBJ出る。 SP_OBJ ちなみにpicodriveはOBJでない。Gens32がOBJ出ないし、やっぱここは「OBJ出ないのが正常動作」なんではあるまいか? 役に立つ(?)なあ。 (2006-09/03、07:30) sp_chr_hanten CHR反転機能は、OBJと同じで簡単だった。んだけどOBJまだ出し方わからんつ! pspDGEN170でもOBJが出る事ハケーン。HazeMD0.05a00は出ない。Genecystも出ない。Genecystスゴwwww。あの時代にもう ソコまで解析済みでしたか。恐れ入ります。それにしても、ううう、お、OBJが出ないなんて、とってもツインビ~じゃなかったナンセンス。 そおいや昔Censerのメガドラデモdisった奴がどっかにあったなあ。あれは確か40カラムモードだった気がする。データーばっかで、 プログラム小さかったよなあ。(今からDLして)disるのも(昔の)探すのもめんどいなあ。 (2006-09/03、13:33)


■やっとOBJ出たあ。 sp_vobj 原因はVRAM配置。OBJ表示がどうのこうのとゆー簡単に予想できるようなものではなかった。 要するにVRAMのメモリ配置がバッティングしてた。
#if 0 /* [NG] */ #define VRAM_CHRDEF 0x0000 #define VRAM_PLB 0xc000 #define VRAM_PLA 0xe000 #define VRAM_PLW 0xe000 #define VRAM_OBJLST 0xfe00 #endif
/* [OK] */ #define VRAM_CHRDEF 0x0000 #define VRAM_PLB 0xc000 #define VRAM_PLA 0xe000 #define VRAM_PLW 0xe000 #define VRAM_OBJLST 0xf000
って最後しか違わんな。何でそーなるのかは、ヨクワカラン。40カラムモードの場合は0xfe00からではダメなのかも?わかんね。 んで、ソースにゃ続きがある。今までは「設定」。「設定」は「反映」しないとさ。んで、
<略> /* scrollabase *//* 2 UINT8 Pat_ScrA_Adr; */ *pw = ((0x8200)|(VRAM_PLA>>10)); /* windowbase *//* 3 UINT8 Pat_Win_Adr; */ *pw = ((0x8300)|(VRAM_PLW>>10)); /* scrollbbase *//* 4 UINT8 Pat_ScrB_Adr; */ *pw = ((0x8400)|(VRAM_PLB>>13)); /* spritebase *//* 5 UINT8 Spr_Att_Adr; */ *pw = ((0x8500)|(VRAM_OBJLST>>9)); <略> こうやって「反映させる」そうしないと「意味不明」になっちゃうから念の為。

さてと、ここでちと問題。16x16OBJはCHR画面(2画面)の背後に出てる。本来手前に出て欲しいなあ。 それから「8x8の上下反転OBJ」画面では「青い丸(註:セガャラガで敵の爆弾?だったOBJ)」だ。 これは何故か、CHR画面(2画面)より手前に表示されてる。 迷路の一部の白い線が欠けてる(隠れてる)のは、手前に表示されてるからだ。 (2006-09/04、11:00)
■半透明ですう。 sp_hanto pico_hantomei (実機でも確認[picodrive]) (2006-09/05、07:33)
メガドラのOBJ座標がワカランと、しょーがない。自分のOBJ位置に(CHRで)「A」を描いてみた。 A_UTU なんか生まれて始めてプログラムを組んだ頃の気分。初心忘るるべからず。 /////////// xy( (((sprite[0].xAxis-(16*8))&0xfff8)>>3), (((sprite[0].yAxis-(16*8))&0xfff8)>>3) ); *vpw= COLOR_BANK0 | 'A'; ////////// (註:xy(xxx,yyy);は「(X,Y)座標→VRAM座標」変換&設定マクロ。画面モードが違うので、セガャラガのものとは違う) なーる程。X,Y共「128ドット」ずれてる訳ね。それで、セガャラガの仮想値は変なんだ~。納得。 (註:つまりOBJ座標128,128が画面の上左隅の座標。(普通は0,0)。 だから下右隅は(128+320,128+240)==(448,368)って事。) (2006-09/05、14:44) ■ sp_pri なんとかでっちあげられそーな気がするが、気のせいかもしんない。とくにOBJのプライオリティーがヨクワカラン。 なーんか無理やりやると、出来るんだけど、(プログラムが)すごくタコになりそう。もっと簡単な方法ないのかなあ? 一応VRAM直アクセスはあきらめて、仮想VRAM方式にした。んで、「自分の走行ルーチンだけ」ちと作った。こんなん。 static short add_vv_now;/*実はunsigned charで十分*/ static void pac_calc_add_vv_now(void)/* 自分の進める量を決める。 */ { add_vv_now=0x20;/*ここは固定小数点。ROUNDによって(量が)違う。*/ } static void pac_get_chr_nowkey(void)/* nowkeyの方向のCHRを調べる。 */ { pacvx = tbl16[TBL_JSTY+(nowkey)]; pacvy = tbl16[TBL_JSTX+(nowkey)]; bg_dat=(vmap [((((pac_y)>>3) + pacvy )&0x1f)] [((((pac_x)>>3) + pacvx )&0x1f)] ); } #define CHR_MONSTER_DOOR 0x14 static void move_pac(void)/*自分移動*/ { short getkey; /* 入力から方向のみ取り出す。 */ getkey=(sys_key & 0x0f); /* 4方向に制限 */ getkey = tbl16[TBL_INVER+(getkey)];/*他の目的でどうせ要るテーブルを利用*/ getkey = tbl16[TBL_INVER+(getkey)]; /* ぴったりチェック */ if( (0==(pac_x&0x07))&& // Y: x000? (0==(pac_y&0x07)) // X: x000? ){ if(getkey==0) { nowkey=oldkey; /* 押されなかったら、止まらなくする。 */ }else{ nowkey=getkey; } pac_get_chr_nowkey(); if((CHR_MONSTER_DOOR-1)<bg_dat)/* 自分にとっての壁? */ { nowkey=oldkey;/* 古い方向でもう一度調べる。 */ pac_get_chr_nowkey(); if((CHR_MONSTER_DOOR-1)<bg_dat)/* 自分にとっての壁? */ { nowkey=0;/* (「現在目指す方向」と「古い方向」の)両方壁なら止まる。 */ } } } /* 移動 */ pacvx = tbl16[TBL_JSTY+(nowkey)]; pacvy = tbl16[TBL_JSTX+(nowkey)]; pac_calc_add_vv_now(); { short add_vv; add_vv=add_vv_now; do{ pac_x += pacvx; pac_y += pacvy; add_vv -=0x10; }while(add_vv<0x10); } pac_x &= 0xff; pac_y &= 0xff; /* ここまで仮想座標、ここで実座標に変換 */ obj[OBJ_PAC].x = (128+(8*4)-8+4 )+pac_x; obj[OBJ_PAC].y = (128-(8*2)-8+4 )+pac_y; oldkey=nowkey; } なんか納得いかないが、めんどいからイイヤ。 (2006-09/06、21:21)
■地味にモンスターの移動ルーチンとか作る。こんなん。
static void move_monster(void){ short monss; short now_monster; short now_monster_obj; if(0<max_ijike_time_counter) { max_ijike_time_counter--; if(1==max_ijike_time_counter) priority_normal_mode(); } monss=1; do { MONSTER_STATUS *mon; short mon_now_muki; /* モンスターの種類 0:aka 1:pin 2:aos 3:guz */ now_monster=monss+monss+((sys_c_count&(1+1))?(1):(0)); now_monster_obj=OBJ_AKABEI_EYE+now_monster+now_monster; mon=&monster[now_monster]; /* ターゲット(追いかけ先)を決める */ if(0==(sys_h_count&(8))){ /* 散りモードの場合 */ mon->tgt_x=mon->SU_X; mon->tgt_y=mon->SU_Y; }else{ /* 追いかけモードの場合 */ /*単純に追いかける*/ mon->tgt_x=pac_x; mon->tgt_y=pac_y; switch(now_monster){ // case AKABEI: break; case PINKEY: //3x8==24dots先読み. mon->tgt_x += tbl16[TBL_PSHY+(nowkey)]; mon->tgt_y += tbl16[TBL_PSHX+(nowkey)]; break; case AOSUKE: // 距離が近いなら点対称の位置を目指す。 { short wwx; short wwy; wwx=(pac_x-monster[AKABEI].wx); wwy=(pac_y-monster[AKABEI].wy); if(wwx<128) mon->tgt_x += wwx; if(wwy<128) mon->tgt_y += wwy; } break; case GUZUTA: //3x8==24dots後ろ。(註:ワカンナイでっす) mon->tgt_x -= tbl16[TBL_PSHY+(nowkey)]; mon->tgt_y -= tbl16[TBL_PSHX+(nowkey)]; break; } #ifdef DEBUG_KAKUNIN /* 仮想座標→実座標に変換 */ obj[now_monster_obj ].x = V2R_X(mon->tgt_x); obj[now_monster_obj ].y = V2R_Y(mon->tgt_y); #endif } mon_now_muki=mon->old_muki; /* ぴったりチェック */ if( (0==(mon->wx&0x07))&& // Y: x000? (0==(mon->wy&0x07)) // X: x000? ){ // // X [7] | [6] / ; // X 111 | 110 / ; // X | / [2] ; // 011 X | / 010 ; // [3] X U / ; //----------L + R--------->x++ ; // / D X ; // 001 / | X 000 ; // [1] / | X [0] ; // / 101 V 100 X ; // / [5] y++ [4] X ; // ----------->X //表示アドレスオフセット量 // 上 //条件1:Xが負なら左右を逆にする。 | 1 //条件2:Yが負なら上下を逆にする。 | 左4 + 8右 //条件3:|Y|>|X|ならXとYをいれかえる。 V 2 // 厚みビット1684 Y 下 // 検索順序1 2 3 4 条件321 //モンスター検索テーブル(アルゴリズム) // short stbl[8*4]={ /*[0]*/ MUKI_R,MUKI_D,MUKI_U,MUKI_L, /* 検索順序:R->D->U->L */ /*[1]*/ MUKI_L,MUKI_D,MUKI_U,MUKI_R, /*[2]*/ MUKI_R,MUKI_U,MUKI_D,MUKI_L, /*[3]*/ MUKI_L,MUKI_U,MUKI_D,MUKI_R, /*[4]*/ MUKI_D,MUKI_R,MUKI_L,MUKI_U, /*[5]*/ MUKI_D,MUKI_L,MUKI_R,MUKI_U, /*[6]*/ MUKI_U,MUKI_R,MUKI_L,MUKI_D, /*[7]*/ MUKI_U,MUKI_L,MUKI_R,MUKI_D, }; short serch_offs; /* 検索順序を決める。 */ serch_offs=0; /* 検索条件を消す。 */ if((mon->tgt_x)<(mon->wx))/*自分よりターゲットXが負方向なら、*/ { /* swap(tgt.x,mon->wx); */ serch_offs |=(4);/* 4==(2^(0+2))「厚みビット4」 */ } if((mon->tgt_y)<(mon->wy))/*自分よりターゲットYが負方向なら、*/ { /* swap(tgt.x,mon->wx); */ serch_offs |=(8);/* 8==(2^(1+2))「厚みビット8」 */ } if( ((0==(serch_offs&(4)))?((mon->tgt_x)-(mon->wx)):((mon->wx)-(mon->tgt_x))) < ((0==(serch_offs&(8)))?((mon->tgt_y)-(mon->wy)):((mon->wy)-(mon->tgt_y))) )/*abs|Y|>abs|X|なら、*/ { serch_offs |=(16);/* 16==(2^(2+2))「厚みビット16」 */ } #define aaa //#undef aaa #ifdef aaa /* 方向のCHRを調べる。 */ #define MON_GET_CHR \ {{\ short tmpvx;\ short tmpvy;\ tmpvx = tbl16[TBL_JSTY+(mon_now_muki)];\ tmpvy = tbl16[TBL_JSTX+(mon_now_muki)];\ bg_dat=(vmap \ [((((mon->wy)>>3) + tmpvy )&0x1f)]\ [((((mon->wx)>>3) + tmpvx )&0x1f)]\ );\ }} #define VS_MON_KABE ((CHR_HENNA_ESA-1)<bg_dat)||/* モンスターにとっての壁? */ #else #define MON_GET_CHR #define VS_MON_KABE #endif /* 再帰(リエントラント)にすれば、すっきりするかも(?)。 */ mon_now_muki=stbl[serch_offs+0]; MON_GET_CHR; if( VS_MON_KABE (mon->old_muki==tbl16[TBL_INVER+(mon_now_muki)]) ){ mon_now_muki=stbl[serch_offs+1]; MON_GET_CHR; if( VS_MON_KABE (mon->old_muki==tbl16[TBL_INVER+(mon_now_muki)]) ){ mon_now_muki=stbl[serch_offs+2]; MON_GET_CHR; if( VS_MON_KABE (mon->old_muki==tbl16[TBL_INVER+(mon_now_muki)]) ){ mon_now_muki=stbl[serch_offs+3]; MON_GET_CHR; if( VS_MON_KABE (mon->old_muki==tbl16[TBL_INVER+(mon_now_muki)]) ){ mon_now_muki=mon->old_muki; } } } } } /* 移動(とりあえず1ドット) */ mon->wx += tbl16[TBL_JSTY+(mon_now_muki)]; mon->wy += tbl16[TBL_JSTX+(mon_now_muki)]; /* 移動(とりあえずもう1ドット) */ mon->wx += tbl16[TBL_JSTY+(mon_now_muki)]; mon->wy += tbl16[TBL_JSTX+(mon_now_muki)]; /**/ mon->wx &=0xff; mon->wy &=0xff; mon->old_muki=mon_now_muki; /* ここまで仮想座標、ここで実座標に変換 */ #ifndef DEBUG_KAKUNIN obj[now_monster_obj ].x = /* MONSTER EYE */ #endif obj[now_monster_obj+1].x = V2R_X(mon->wx); #ifndef DEBUG_KAKUNIN obj[now_monster_obj ].y = /* MONSTER EYE */ #endif obj[now_monster_obj+1].y = V2R_Y(mon->wy); } while(monss--); }
static void pac_get_chr(short keykey)/* 方向のCHRを調べる。 */ { pacvx = tbl16[TBL_JSTY+(keykey)]; pacvy = tbl16[TBL_JSTX+(keykey)]; bg_dat=(vmap [((((pac_y)>>3) + pacvy )&0x1f)] [((((pac_x)>>3) + pacvx )&0x1f)] ); } static short pac_walk;/* need static */ static void move_pac(void)/*自分移動*/ { short getkey; /* 入力から方向のみ取り出す。 */ getkey=(sys_key & 0x0f); /* 4方向に制限 */ getkey = tbl16[TBL_INVER+(getkey)]; /*他の目的でどうせ要るテーブルを利用*/ getkey = tbl16[TBL_INVER+(getkey)]; /* ぴったりチェック */ if( (0==(pac_x&0x07))&& // Y: x000? (0==(pac_y&0x07)) // X: x000? ){ if(getkey==0) { nowkey=oldkey; /* 押されなかったら、止まらなくする。 */ }else{ nowkey=getkey; } pac_get_chr(nowkey); if((CHR_MONSTER_DOOR-1)<bg_dat)/* 自分にとっての壁? */ { nowkey=oldkey;/* 古い方向でもう一度調べる。 */ pac_get_chr(nowkey); if((CHR_MONSTER_DOOR-1)<bg_dat)/* 自分にとっての壁? */ { nowkey=0;/* (「現在目指す方向」と「古い方向」の)両方壁なら止まる。 */ } } /* お食事 */ pac_get_chr(0); switch(bg_dat){ // case CHR_FRUIT_A: /* フルーツ#1*/ // case CHR_FRUIT_B: /* フルーツ#2*/ case CHR_POWER_ESA: /* パワーエサ power food.*/ max_ijike_time_counter=64*11;//1面の場合 /* 向き反転 */ monster[AKABEI].old_muki=tbl16[TBL_INVER+(monster[AKABEI].old_muki)]; monster[PINKEY].old_muki=tbl16[TBL_INVER+(monster[PINKEY].old_muki)]; monster[AOSUKE].old_muki=tbl16[TBL_INVER+(monster[AOSUKE].old_muki)]; monster[GUZUTA].old_muki=tbl16[TBL_INVER+(monster[GUZUTA].old_muki)]; /**/ priority_ijike_mode(); score1up+=(5-1);/*50pts*/ case CHR_HENNA_ESA: /* 変なエサ*/ case CHR_NORMAL_ESA: /* 普通のエサ dots.*/ score1up+=1;/*10pts*/ xy_plb( (((pac_x+8*4 )&0xfff8)>>3), (((pac_y-8*2 )&0xfff8)>>3) ); *vpw= 0; vmap[((((pac_y)>>3) + pacvy )&0x1f)] [((((pac_x)>>3) + pacvx )&0x1f)]=((CHR_HENNA_ESA==bg_dat)?(CHR_HENNA_KABE):(0)); pac_walk-=0x10;/* 喰って遅い*/ break; } } /* 移動 */ pacvx = tbl16[TBL_JSTY+(nowkey)]; pacvy = tbl16[TBL_JSTX+(nowkey)]; /* 自分の進める量を決める。 */ pac_walk+=0x10; /* +1 歩 */ if(nowkey!=oldkey){ pac_walk+=0x20; /* +2 歩 */ } /* 曲がった瞬間(now<>old)は、速い(?)。*/ { while(pac_walk<0x20){ pac_walk -=0x10; pac_x += pacvx; pac_y += pacvy; } } /**/ pac_x &= 0xff; pac_y &= 0xff; oldkey=nowkey; /* ここまで仮想座標、ここで実座標に変換 */ obj[OBJ_PAC].x = V2R_X(pac_x); obj[OBJ_PAC].y = V2R_Y(pac_y); }
int main(void)/*メイン*/ { init_system(); /* system初期化 */ init_coin(); /* game_data初期化 */ init_round(); /* ラウンド開始前の初期化部分のみ */ //test sound sound_effect(2); play_sample((ulong)SOUND, SOUND_LENGTH); /* ゲームループ*/ while(1) /* LOOP FOREVER */ { /* ポーズボタン調べる。*/ if(BUTTON_S==(sys_key&0xf0)){ pause_mode=1; } /* ポーズモードへ移行。*/ if(pause_mode){ pause_main(); } else{ /* ゲーム中(ポーズ中でない)*/ if(0==(sys_c_count&1)){ move_pac(); /* 自機処理*/ }else{ move_monster(); /* モンスター処理*/ } show_score_value(score1up); /* スコア表示*/ } /* VSYNC処理(VSYNC内でパッド読み込む)*/ flash_1up(); /* '1UP'とパワーエサ点滅。その他OBJアニメ。 */ show_objects(); /* スプライト(OBJ)表示*/ /* sound_main();*/ wait_vsync(); } return 0;/* ダミー。*/ }
あとさ、OBJの優先順位の問題もあるし。 sp3A00game やっぱモンスターが動くと、ゲームっぽくなるなあ。 (2006-09/08、14:30)