fc2ブログ
先週末秋葉原に行った際にAITNDOのFMラジオモジュールFM577-4Pを購入してきました。



I2Cで割と簡単に操作できそうでしたのでICHIGOJAMにつないで実験中です。


aitendoによるとこのモジュール電源は5Vですが、乗っているDSPラジオとアンプICは3Vでも動作できるものでしたので、
ichigojamの3.3Vで動かしています。

このモジュールはTEA5767というチップを乗せています。データシートはこちらです。

このチップのレジスタ構成はちょっと変わっていて、レジスタは5個固定で、レジスタアドレスに相当するものがありません。
どういうことかというと、通常はI2Cではデバイスアドレス、レジスタアドレス、データ1、データ2、。。。
という書き込みをするところ、このチップはデバイスアドレス、データ1、データ2、。。。データ5、となります。
ICHIGOJAMのI2CW命令は、デバイスアドレス、レジスタアドレス、レジスタデータの3パラメータ構成なので少し悩みましたが、結局以下のコードで設定できることがわかりました。

10 POKE #700,#27,#72,#00,#3E,#00
20 A=I2CW(#60,#700,1,#701,4)
30 SLEEP


固定周波数82.5MHzで設定するコードです。詳細は後日解説します。

問題はなぜ30行にSLEEPがいるのか、です。

最初10行と20行だけで動かしてみたのところ、ひどい雑音とかすかな音楽が聞こえてきました。
どうやらI2C設定はできていて、周波数か他の設定が間違っているのだな、と思って
設定値を確認してみたのですが、特におかしいところがない。。。。。

色々試している中で。たまたまCLSで画面を消去すると状態が良くなることがわかりました。
これはノイズ影響だな、と思ってLCDモニタの電源を切ってみても変わりない。。。

次にichigojamのCPUを強制的にリセット状態にすると著しく改善することがわかりました。
どうやらCPU動作のノイズによる模様です。
リセット状態のままでおけないのでSLEEPにしたところやはり改善したので30行に追加しました。

いかしやっぱり画面表示して選局とかしたいのでSLEEPのままとも行きません。
次回はノイズ観測と対策を打ってみたいと思います。



スポンサーサイト



2016.07.26 Tue l ICHIGOJAM l コメント (0) l top
どうやらワイヤフレームで3D表示っぽいことができるようになりました。

その前に苦労した自由ラインルーチンについてはこちらをご覧ください。)



■ワイヤフレーム3Dルーチンは以下です。これを実行すると、#700-#7FFに書き込まれます。

1 poke#700,240,181,133,36,137,176,3,145,36,1,14,25,3,156,164,70,58,73,97,68,6,145,0,36,49,95,4,145,2,36,49,95,5,145,4,36,49,95,140,70,0,41,4,218,75
2 poke#72d,66,27,4,27,20,156,70,84,224,4,156,90,67,97,70,97,67,64,37,84,17,73,17,9,27,67,67,9,4,5,152,9,12,1,145,97,70,65,67,88,17,73,17,9,26
3 poke#75a,9,4,9,12,82,0,91,0,18,4,27,4,2,145,18,20,27,20,145,17,8,4,0,12,7,145,1,0,31,49,9,4,9,12,62,41,35,216,153,17,12,4,36,12,39
4 poke#787,0,23,55,63,4,63,12,46,47,26,216,151,17,127,16,7,151,31,39,9,1,185,67,7,159,127,24,169,33,9,1,127,24,3,153,207,25,2,33,100,0,12,64,1,57
5 poke#7b4,8,64,32,67,129,64,8,0,128,33,73,66,8,67,57,120,1,67,57,112,1,153,138,24,2,153,1,61,203,24,18,4,27,4,45,4,18,20,27,20,45,12,197,209,6
6 poke#7e1,155,6,54,4,154,5,152,158,66,1,208,99,70,146,231,0,32,9,176,240,188,2,188,8,71,192,70,200,8,0,0


■使い方
  [40]-[99]に3ワード単位で描画したいラインのX,Y,Z座標を書き込んで、
  CLSののちに#700をコールすると一気に描画されます。

  [40+3*N] : X座標をー31~+31の範囲で入れます。
  [40+3*N+1] : Y座標をー31~+31の範囲で入れます。
  [40+3*N+2] : Z座標を絶対値0~100くらいで入れます。数字が大きいほど近くなります。
          
  Z座標に線の切れ目を示す仕掛けが入っています。マイナスをつけるとそこが線の区切りになります。
  逆に正の数だと区切りをつけずに一筆書きで描画します。
  例えば [40]=0:[41]=0:[42]=-10 : [43]=10:[44]=0:[45]=10: [46]=10:[47]=10:[48]=10 : [49]=20:[50]=20:[51]=10:
       では(X,Y,Z) = (0,0,10)-(10,0,10)-(10,10,10)-(20,20,10)を一筆書きでつなぎます。
それにたいして [40]=0:[41]=0:[42]=-10 : [43]=10:[44]=0:[45]=10: [46]=10:[47]=10 :[48]= -10 : [49]=20:[50]=20:[51]=10:
       だと(X,Y,Z) = (0,0,10)-(10,0,10) と (10,10,10)-(20,20,10)の2本の線を書きます。
   線分データ量を減らして、自由度を上げるためにこうしています。
   この方式のため、最初の座標のZ([42]は必ずマイナスとしてください。

■制限
  [40]-[99]は使えません。

■デモ3パターンを作ったので動画にしました。



「スポンサードリンク」

style="display:block"
data-ad-client="ca-pub-0620260288102702"
data-ad-slot="9773401572"
data-ad-format="auto">



■デモプログラム1 :回転する3角形

10 CLS:T=0:S=0:[0]=10:[1]=8:[2]=5:[3]=0:[4]=-5:[5]=-8:[6]=-10:[7]=-8:[8]=-5:[9]=0:[10]=5:[11]=8
30 [12]=0:[13]=5:[14]=8:[15]=10:[16]=8:[17]=5:[18]=0:[19]=-5:[20]=-8:[21]=-10:[22]=-8:[23]=-5
40 FORE=40TO99:[E]=-1:NEXT
50 K=24:[K]=RND(32)-16:[K+1]=RND(24)-12:[K+2]=5:[K+3]=RND(8)
70 FORD=5TO50
80 J=40:K=24:X=[K]:Y=[K+1]:Z=[K+2]:C=[K+3]:IFS=0GSB500ELSEGSB600
90 Z=D*2
100 [K+2]=Z:[K+3]=(C+1)%12
110 CLS:A=USR(#700,0)
135 WAIT 2
140 NEXT
150 T=T+1:IFT>3T=0:S=1-S
170 GOTO 50
500 H=0:I=0:GSB1000:[J]=X+V:[J+1]=Y-5:[J+2]=-(z+W)
520 H=10:I=0:GSB1000:[J+3]=X+V:[J+4]=Y+5:[J+5]=z+W
530 H=-10:I=0:GSB1000:[J+6]=X+V:[J+7]=Y+5:[J+8]=z+W
540 H=0:I=0:GSB1000:[J+9]=X+V:[J+10]=Y-5:[J+11]=z+W
550 RTN
600 H=0:I=-5:GSB1000:[J]=X+V:[J+1]=Y+W:[J+2]=-Z
610 H=10:I=5:GSB1000:[J+3]=X+V:[J+4]=Y+W:[J+5]=z
620 H=-10:I=5:GSB1000:[J+6]=X+V:[J+7]=Y+W:[J+8]=z
630 H=0:I=-5:GSB1000:[J+9]=X+V:[J+10]=Y+W:[J+11]=z
650 RTN
1000 V=(H*[C]-I*[12+C])/10
1010 W=(H*[12+C]+I*[C])/10
1020 RTN


■デモプログラム2 :回転する角錐

10 CLS:[0]=10:[1]=8:[2]=5:[3]=0:[4]=-5:[5]=-8:[6]=-10:[7]=-8:[8]=-5:[9]=0:[10]=5:[11]=8
30 [12]=0:[13]=5:[14]=8:[15]=10:[16]=8:[17]=5:[18]=0:[19]=-5:[20]=-8:[21]=-10:[22]=-8:[23]=-5
40 FORE=40TO99:[E]=-1:NEXT
50 FORE=0TO1:K=24+E*4:[K]=RND(32)-16:[K+1]=RND(24)-12:[K+2]=5+E*30:[K+3]=RND(8):NEXT
70 FORD=5TO50
80 FORE=0TO1:J=40+E*24:K=24+E*4:X=[K]:Y=[K+1]:Z=[K+2]:C=[K+3]:GSB500
90 Z=Z+2:IFZ>100Z=20
100 [K+2]=Z:[K+3]=(C+1)%12:NEXT
110 CLS:A=USR(#700,0)
135 WAIT 2
140 NEXT:GOTO50
500 H=0:I=-4:GSB1000:[J]=X+V:[J+1]=Y+W:[J+2]=-Z
510 H=4:I=4:GSB1000:[J+3]=X+V:[J+4]=Y+W:[J+5]=Z
520 H=-4:I=4:GSB1000:[J+6]=X+V:[J+7]=Y+W:[J+8]=Z
530 H=0:I=-4:GSB1000:[J+9]=X+V:[J+10]=Y+W:[J+11]=Z
540 H=0:I=0:GSB1000:[J+12]=X+V:[J+13]=Y+W:[J+14]=Z+8
550 H=4:I=4:GSB1000:[J+15]=X+V:[J+16]=Y+W:[J+17]=Z
560 H=0:I=0:GSB1000:[J+18]=X+V:[J+19]=Y+W:[J+20]=-(Z+8)
570 H=-4:I=4:GSB1000:[J+21]=X+V:[J+22]=Y+W:[J+23]=Z:RTN
1000 V=(H*[C]-I*[12+C])/10:W=(H*[12+C]+I*[C])/10:RTN



■デモプログラム3 :キー操作できる立方体
 
 これは上下左右キーでXY方向移動、1・2キーでZ方向移動、3・4キーで回転ができます。

10 CLS:[0]=10:[1]=8:[2]=5:[3]=0:[4]=-5:[5]=-8:[6]=-10:[7]=-8:[8]=-5:[9]=0:[10]=5:[11]=8
30 [12]=0:[13]=5:[14]=8:[15]=10:[16]=8:[17]=5:[18]=0:[19]=-5:[20]=-8:[21]=-10:[22]=-8:[23]=-5
40 FORE=40TO99:[E]=-1:NEXT:C=0:X=0:Y=0:Z=40
100 GSB500:K=INKEY():IFK=51C=C-1:IFC<0C=11
110 IFK=52C=C+1:IFC>11C=0
120 IFK=28ANDX>-32:X=X-1
130 IFK=29ANDX<32:X=X+1
140 IFK=30ANDY>-32:Y=Y-1
150 IFK=31ANDY<32:Y=Y+1
160 IFK=49ANDZ>20:Z=Z-2
170 IFK=50ANDZ<100:Z=Z+2
180 CLS:?"X:";X;" Y:";Y;" Z:";Z;" R:";C:A=USR(#700,0):WAIT2:GOTO100
500 H=-10:I=-10:GSB1000:[40]=X+V:[41]=Y-3:[42]=-(z+W):[55]=X+V:[56]=Y+3:[57]=Z+W
510 H=10:I=-10:GSB1000:J=43:GSB700:H=10:I=10:GSB1000:J=46:GSB700
520 H=-10:I=10:GSB1000:J=49:GSB700:H=-10:I=-10:GSB1000:J=52:GSB700
530 H=10:I=-10:GSB1000:J=70:GSB710:H=10:I=10:GSB1000:J=76:GSB710
540 H=-10:I=10:GSB1000:J=82:GSB710:RTN
700 [J]=X+V:[J+1]=Y-3:[J+2]=z+W:[J+15]=X+V:[J+16]=Y+3:[J+17]=Z+W:RTN
710 [J]=X+V:[J+1]=Y-3:[J+2]=-(z+W):[J+3]=X+V:[J+4]=Y+3:[J+5]=Z+W:RTN
1000 V=(H*[C]-I*[12+C])/10:W=(H*[12+C]+I*[C])/10:RTN


■マシン語ルーチンのソースコード

1行目の<と>は全角になっていますが、お使いになる場合は半角に変えてください。
(FC2ブログ文字化け対策)

#include <stdint.h>
#define VRAM_ADR 0x900 // 画面
#define WORK_ADR 0x800

uint16_t stars(uint16_t c, uint8_t* m_p, uint8_t* f_p)
{
int16_t p,x0,y0,z0,x1,y1,z1,i,x,y,xp,yp,dx,dy,w;
uint8_t c1;
int16_t* w_p = m_p + WORK_ADR; // 変数アドレス獲得
uint8_t* v_p = m_p + VRAM_ADR; // 画面アドレス獲得

p=40;
// x1=0;y1=0;z1=0; //********* メモリ節約のため初期化しない。最初のデータをZ<0とすること。
while (p<100) { //***** 配列[40]-[99]を使用
x0 = x1; y0=y1; z0=z1;
x1 = w_p[p++];y1 = w_p[p++];z1= w_p[p++];
if (z1<0) {
z1 = -z1; //***** Zがマイナスは一筆書きの切れ目を意味する
}else{
dx = ((x1*z1)>>5) - ((x0*z0)>>5); //***** 3D-2D変換後のX座標始点と終点の差分を計算
dy = ((y1*z1)>>5) - ((y0*z0)>>5); //***** 3D-2D変換後のY座標始点と終点の差分を計算
x = ( (x0*z0) << 1); //***** 3D-2D変換後の始点X座標 ((x0*z0)>>5) <<6) 画面座標の64倍
y = ( (y0*z0) << 1); //***** 3D-2D変換後の始点X座標((x0*z0)>>5) <<6) 画面座標の64倍
for (i=0;i<64;i++) { //64回dx、dy加算で線を引く
xp=x>>6; //画面座標にする
yp=y>>6; // 画面座標にする
w=((yp&0xfffe) <<4) + (xp>>1) + 384+16; //*** 変換した座標に対応するVRAMアドレス計算
c1= ( 1 <<( ( ( xp&1) | (yp&1)<<1) ) ) | 0x80; //*********** セミグラフィックキャラ計算
if ( (xp>-32)&&(xp<32)&&(yp>-24)&&(yp<24) ) {v_p[w] |= c1;}
x += dx;
y += dy;
}
}
}
return 0;
}


マシン語256B、BASIC1KBでも結構いろいろできるものです。

それではまたです。

2016.07.02 Sat l ICHIGOJAM l コメント (0) l top
キャラクタ3Dがまあまあ動いたので気をよくして、次は「ワイヤフレーム3Dいってみよう!」ということにしました。

「まずはラインルーチンから」と考えたところで、はたと困りました。

普通にブレゼンハムのアルゴリズムを考えたのですが、これって傾きが1未満と1以上で描画を分けるのですよね。つまり2倍のコードが必要なわけです。始点と終点のX,Y大小関係も考慮が必要です。
これまでの経験上、これはichigojam用としてはメモリが足りないだろう、とわかります。

どうしたものかなあ、と考えていたところ、通勤中の電車内でひらめきました。

  ・ichigojamのセミグラフィックを64x64しかないのを逆手に取り、その範囲にあったアルゴリズムにします。

   ・描画する座標x,yそれぞての始点と終点の差分を取りdx、dyとします。 
   ・描画座標は64倍で計算します。
   ・64倍された始点座標にdx、dyを加算していくと、64回加算でちょうど終点座標の64倍になります。
   ・その加算過程の座標を1/64してドットをうつと、始点から終点にいたる線が描画されます。

これは普通に縦横数百PIXEL以上の画面では演算回数が多くなりすぎて使えないでしょう。
また、短い線だと同じPIXELに何回も無駄に書きます。(極端な話長さ1piexlの線でも同じところに64回点を打ちます。)
64x64しかないから画面でマシン語だから使えるアルゴリズムです。

帰宅して早速C言語にしてみました。

最初の行の<と>は全角ですが、使用する場合は半角の<と>変えてください。
FC2ブログ文字化けを防ぐためにこうしています。


#include <stdint.h>
#define VRAM_ADR 0x900
#define WORK_ADR 0x800

uint16_t stars(uint16_t c, uint8_t* m_p, uint8_t* f_p)
{
int16_t p,x0,y0,x1,y1,i,x,y,xp,yp,dx,dy,w;
uint8_t c1;
int16_t* w_p = m_p + WORK_ADR;
uint8_t* v_p = m_p + VRAM_ADR;

p=0;
while (p<4) {
x0 = w_p[p++];y0 = w_p[p++];
x1 = w_p[p++];y1 = w_p[p++];
dx = x1 - x0;
dy = y1 - y0;
x = x0 << 6;
y = y0 << 6;
for (i=0;i<64;i++) {
xp=x>>6;
yp=y>>6;
w=((yp&0xfffe) <<4) + (xp>>1) + 384+16; //*** 変換した座標に対応するVRAMアドレス計算
c1= ( 1 <<( ( ( xp&1) | (yp&1)<<1) ) ) | 0x80; //*********** セミグラフィックキャラ計算
if ((xp>-32)&&(xp<32)&&(yp>-24)&&(yp<24)&&((v_p[w]&0x70)==0) ) {v_p[w] |= c1;}
x += dx;
y += dy;
}
}
return 0;
}


で、BASICでは以下のコードでテストしてみました。

10 cls
20 for i=-5to5
25 cls
30 [0]=31:[1]=-i:[2]=-31:[3]=i
40 a=usr(#700,0)
45 wait 10
50 next
100 for i=-5to5
110 cls
120 [0]=-i:[1]=-i:[2]=i:[3]=i
130 a=usr(#700,0)
140 wait 10
150 next
200 for i=-5to5
210 cls
220 [0]=-i-5:[1]=-i+5:[2]=i:[3]=i*2
230 a=usr(#700,0)
240 wait 10
250 next


意図通りに線が描画されます。傾きも始点・終点位置関係も問題なしです。

いけるようなので明日はZ座標を導入して3Dのラインを書けるようにします。

その次はいよいよワイヤフレーム3Dです。

それではまたです。


2016.06.29 Wed l ICHIGOJAM l コメント (0) l top
最近少し早く帰れるようになったので趣味の方のプログラムがはかどります。

ichigojamマシン語活用でわかってきたことを応用して、汎用的に使えるマシン語3Dルーチンを作ってみました。

BASIC領域をあまり消費せずに高速で3D風表示ができますので、シューティングゲーム等にも使えると思います。
実は昔のPC8001用3Dゲーム「OLION」というのを意識して作ってみました。

あまりメジャーじゃなかった感じだし、正直やってみてあまり面白くはなかった(^^; ような記憶ですが、
最初に画面を見た時の「おお3Dだ!」という感動だけは覚えています。

■概要
  18個までの文字をX,Y,Z座標指定で3D空間に配置してコールすることで文字を2D変換して表示できます。
  以下のような表示ができます。




■使い方
  下の「マシン語書き込みプログラム」を実行します。これにより、#700-#82Fの空間にルーチンが格納されます。
  配列変数[24]-[99]に配列4個一文字で文字コードとX,Y,Z座標を
   [24] = 文字コードです。ichigojamの固定キャラクタ番号を#01-#FFで指定します。
       #00で指定するとその文字および以下XYZは無視されます。
   [25] = x座標を -32~+32で入れます。
   [26] = Y座標を -32~+32で入れます。
   [27] = Z座標を 0~100くらいで入れます。0が最遠で数字が大きいほど近くなります。
   以下同様に[24+N*4]~[24+N*4+3]に表示したい文字情報を入れます。
    (Nは0以上18以下です。これで配列[100]までを使い切ります。)
   
   その後CLSで画面消去したのちにA=USR(#700,0)でコールすると各文字を3D-2D変換して表示します。

■制限
  プログラムのお尻が配列領域まではみ出しています。このため配列[0]~[23]は使用・書き換え禁止です。
  書き換えてコールすると暴走します。CLVも使用できません。

■マシン語書き込みプログラム
  以下をロードして実行します。


1 poke#700,240,181,144,32,70,76,143,176,0,1,12,146,8,24,131,34,12,25,18,1,5,144,9,148,139,24,25,136,157,136,201,4,9,12,90,136,6,149,216,136,0,41,7,209,9
2 poke#72d,159,8,51,187,66,242,209,15,176,240,188,2,188,8,71,0,4,18,4,0,20,18,20,4,50,132,70,96,70,80,67,53,78,10,144,8,34,72,28,12,156,9,4,9,20
3 poke#75a,97,92,6,157,0,4,0,12,1,144,3,145,48,4,41,4,9,20,0,20,64,24,7,28,96,70,120,67,64,17,4,4,36,12,33,28,23,49,9,4,9,12,2,145,1
4 poke#787,33,140,67,200,37,36,5,109,4,100,25,103,70,1,64,36,12,127,66,73,0,7,148,11,151,10,152,8,145,8,33,68,17,37,28,31,53,45,4,45,12,62,45,33,216
5 poke#7b4,2,157,46,45,30,216,37,4,7,159,45,20,109,16,125,25,45,4,5,159,45,20,125,25,0,149,45,120,4,149,4,159,112,37,47,66,14,209,3,157,1,39,61,64,60
6 poke#7e1,64,8,159,60,67,165,64,128,39,44,28,127,66,4,157,60,67,0,159,44,67,60,112,3,156,1,57,11,157,100,8,9,4,3,148,9,12,64,25,0,41,204,209,113,28
7 poke#80e,1,58,14,4,18,4,54,12,18,12,0,209,135,231,1,153,152,231,200,8,0,0,252,255,0,0


■サンプルソフト
  動きは動画でご確認ください。



10 CLS
20 FORI=6TO24:J=I*4:[J]=0:[J+1]=I*6-50:[J+2]=I*2-20:[J+3]=0:NEXT
30 [24]=#49:[28]=#63:[32]=#68:[36]=#69:[40]=#67:[44]=#6F:[48]=#6A:[52]=#61:[56]=#6D
40 T=50:GOSUB1000
50 FORI=6TO24:J=I*4:[J]=0:NEXT
60 [24]=#33:[25]=10:[26]=5:[27]=10:[28]=#44:[29]=16:[30]=5:[31]=10
70 [32]=#33:[33]=-16:[34]=-5:[35]=40:[36]=#44:[37]=-10:[38]=-5:[39]=40
75 [40]=#33:[41]=-16:[42]=10:[43]=0:[44]=#44:[45]=-10:[46]=10:[47]=0
80 T=100:GOSUB 1000
90 FORI=6TO24:J=I*4:[J]=0:NEXT
100 FORI=6TO10:J=I*4:[J]=#FF:[J+1]=RND(32)-16:[J+2]=RND(32)-16:[J+3]=RND(10)*4:NEXT
110 T=200:GOSUB 1000
200 FORI=6TO24:J=I*4:[J]=0:NEXT
210 FORI=6TO10:J=I*4:[J]=#F1:[J+1]=RND(32)-16:[J+2]=RND(32)-16:[J+3]=RND(10)*4:NEXT
220 T=200:GOSUB 1000
230 GOTO 20
1000 FORI=0TO T
1010 FORJ=0TO9:K=J*4+24:[K+3]=[K+3]+1
1012 IF [K]=#F1 [K+1]=[K+1]+RND(3)-1
1015 IF[K+3]>60 [K+3]=0
1016 NEXT
1020 CLS
1030 A=USR(#700,0)
1050 NEXT
1060 RTN


■3Dルーチンソースコード
  以下をコンパイルしてマシン語書き込みプログラムを生成しています。
  何やってるのかできるだけわかるようにコメントつけました。

  できれば#700~#7FFに収めようと努力したのですができませんでした。
  範囲チェックを外せば入るのですが、暴走が恐ろしくてできません。


2016/06/29PM8追記:1行目の#includeの次は全角の<>で挟まれていますが、
         半角の<と>に置き換えてください。
         FC2ブログは半角の<と>で挟まれているとおかしな文字化けをするみたいです。
2016/06/30AM6追記:ソースコード誤り訂正。
    誤:#define WORK_ADR 0x0830 → 正:#define WORK_ADR 0x0800



#include <stdint.h>
#define VRAM_ADR 0x0900
#define WORK_ADR 0x0800

uint16_t stars(uint16_t c, uint8_t* m_p, uint8_t* f_p)
{
int16_t x,y,z,w,ca,x0,y0,x1,y1,i;
uint8_t c0,c1;
//********** 実アドレスゲット *********
int16_t* w_p = m_p + WORK_ADR; //******** 変数領域
uint8_t* v_p = m_p + VRAM_ADR; //******** VRAM領域

i = 24;
while(i<100) { //**** 文字数分LOOP
//******************** ca:キャラクタデータアドレス, X,Y,Z:3次元座標 *******************
ca = w_p[i++]*8; x = w_p[i++]; y = w_p[i++]; z =w_p[i++];
//********************* 一文字 8x8 DOT表示ループ **********************************************
if (ca !=0) { //***** キャラクタ00の場合は何もしない
for (y0=-4;y0<4;y0++) { //*** キャラクタ縦8行分LOOP **********************
c0 = f_p[ca++]; //*** キャラクタデータ1行分を取り出す**************
for (x0=-4;x0<4;x0++) { //*** キャラクタ横8桁分LOOP **********************
x1 =((x-x0)*z)>>5; //*** X座標を3D-2D変換
y1 = ((y+y0)*z)>>5; //*** Y座標を3D-2D変換
w=((y1&0xfffe) <<4) + (x1>>1) + 384+16; //*** 変換した座標に対応するVRAMアドレス計算
c1= ( (c0&1) <<( ( ( x1&1) | (y1&1)<<1) ) ) | 0x80; //*********** セミグラフィックキャラ計算
//**** VRAM領域内で空白またはセミグラフィックキャラなら書き込み
if ((x1>-32)&&(x1<32)&&(y1>-24)&&(y1<24)&&((v_p[w]&0x70)==0) ) {v_p[w] |= c1;}
c0 >>= 1; //***** 次のPIXELを計算
}
}
}
}
}




それではまたです。
2016.06.28 Tue l ICHIGOJAM l コメント (0) l top
前回試してみた3D→2D演算の応用で、懐かしゲーム「走れSKYLINE」を再現してみました。



このゲームは私はPLAYしたことはないのですが、昔PC8001用で発表されて結構話題になり、ほかの機種にも移植されていたゲームで印象には残っています。今回Youtubeで確認してできるだけ似たものを作ってみました。
動作は動画でご覧ください。



余談ですが、YOUTUBEで検索すると、昔のゲームがいっぱい出てきて実に懐かしい限りです。
1500円のマシンで雰囲気レベルとはいえ再現できるとは実に良い時代になったものです。

まずはC言語によるマシン後ルーチン。オブジェクト256Byteに収まるようにかなり絞り込みんだつもりです。
ここで画面クリア、道路の描画、そして道路データのスクロールをやっています。

#include
#define VRAM_ADR 0x900
#define WORK_ADR 0x800

uint16_t stars(uint16_t c, uint8_t* m_p, uint8_t* f_p)
{
int16_t i,j,x,y,z,w,x0,x1;
//********** 実アドレスゲット *********
int16_t* w_p = m_p + WORK_ADR;
uint8_t* v_p = m_p + VRAM_ADR;
//********** 画面クリア *********
for (i=32;i<756;i++) {
v_p[i] = 0x80;
}
//********** 道路表示 *********
for (i=0;i<32;i++) {
x=w_p[i]+w_p[41];j=i+2;
x=(((j)*x)>>5)+32;
y=( (j*j)>>5)+9+(i*(w_p[40]&0x07)>>5);
w= (y/2)*32;
x1=x; x0=0;
if ( (i&1)==1 ) {x0=x; x1=63;}
for(j=x0;j z=w+(j/2);
if (z<756) {
v_p[z] |= (1<<( (j&1)+((y&1)<<1) )) ;
}
};
}
//********** スクロール*********
for (i=0;i<32;i+=2) {
w_p[32-i]=w_p[30-i];
w_p[31-i]=w_p[29-i];
}
return 0;
}


これで生成されるihigojam用のPOKE文は以下の通りです。

1 poke#700,247,181,144,32,0,1,8,24,146,34,53,76,18,1,1,144,139,24,10,25,128,32,24,112,1,51,147,66,250,209,0,35,88,0,128,37,8,24,45,1,64,25,4,136,45
2 poke#72d,72,8,90,32,24,133,36,36,1,15,91,7,36,154,28,39,64,0,4,22,28,0,20,95,67,80,67,114,67,127,17,82,17,9,55,191,24,63,4,63,12,62,4,54,20
3 poke#75a,64,17,118,16,32,48,118,5,0,4,54,12,1,36,0,12,0,150,0,34,35,66,1,208,2,28,63,32,39,64,127,0,20,4,5,4,36,20,45,20,172,66,25,218,229
4 poke#787,15,44,25,0,157,100,16,44,25,21,77,36,4,36,20,172,66,11,220,1,158,1,37,52,25,22,28,46,64,180,70,188,68,102,70,181,64,38,120,53,67,37,112,1,50
5 poke#7b4,18,4,18,12,223,231,1,51,32,43,175,209,10,72,11,74,11,24,137,24,26,136,154,128,154,30,18,136,4,59,218,128,139,66,247,209,0,32,254,188,2,188,8,71,244
6 poke#7e1,11,0,0,82,8,0,0,243,2,0,0,60,8,0,0,252,7,0,0


そしてメインプログラム。道路データの生成、キー操作、自車描画、背景ビル描画をやっています。
キー操作は左右キーがハンドル上下キーがアクセル・ブレーキになっています。

これでほぼ1KBです。
完成ゲームとして公開する意図はないのでゲームとしての判定などは入れていません。
起動時の表示などを省けばメモリに余裕ができますので、ゲームとしての衝突判定やスコア計算、
もしかしたら他車の追加などもできると思います。


「スポンサードリンク」

style="display:block"
data-ad-client="ca-pub-0620260288102702"
data-ad-slot="9773401572"
data-ad-format="auto">




10 'hashire skyline
20 CLV:CLS
30 FORI=0TO5
40 LC10,5:?"Welcome to"
50 LC5,7:?" ":WAIT20
60 LC5,7:?"Racing Sports turbo":WAIT20
65 NEXT
70 CLS:[40]=0:Z=5:C=0:W=0:F=10:T=60:L=0
80 P=-16:R=RND(5)*2+10:V=0
90 FORI=0TO15:[I*2]=P:[I*2+1]=[I*2]+32:NEXT
100 A=USR(#700,0):GOSUB250:WAIT 100
110 K=INKEY()
120 P=P+V:Z=Z-V:IF P<-16ORP>16 P=P-V
130 R=R-1:IF R<0 R=RND(5)*2+5:V=RND(3)-1
140 IF Z<0 Z=0
150 IF Z>10 Z=10
160 IF K=29 AND C>-16:C=C-2:W=1
170 IF K=28 AND C<16:C=C+2:W=-1
180 IF K=31 AND F<0 AND F>-10 F=F-1
190 IF K=30 AND F<-1 F=F+1
200 [0] =P:[1]=P+32:[41]=C
210 A=USR(#700,0)
220 [40]=([40]+1)&7
230 GOSUB 250
240 GOTO 110
250 LCZ/2+5,2:?" # # # ";
280 LCZ/2+5,3:?" # # # # ## # ";
290 LC14+W,20:?" ";CHR$(#9F);CHR$(#8F);CHR$(#8F);CHR$(#9E);" ";
300 LC14+W,21:?" ";CHR$(#9A);CHR$(#9B);CHR$(#9A);CHR$(#9B);" ";
310 G=ABS(F):WAIT G*2
320 IF F>=0 F=F-1
330 BEEPG*10+50,3:L=L+G
340 LC0,0:?(10-G)*25;"km ";T;" ";L;" ";
350 RTN


それではまたです。
2016.06.25 Sat l ICHIGOJAM l コメント (0) l top