上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
--.--.-- -- l スポンサー広告 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
IJBIN2POKEでichigojamのマシン語を使ってみて分かったことを記録してみます。
(らしい、とあるのは試行錯誤してみた結果で、仕様などを確認したわけではないからです。)

①サブルーチンは使えるが、引数の引き継ぎがうまくいかないらしい。
   → 今回は使いませんでしたが、固定アドレスに引数を格納すればよいと思われます。

②グローバル変数は使えないらしい。 
   → やはり固定アドレスに引数を格納すればよいと思われます。

③割り算は使えないらしい。
   → これは中々分かりませんでした。A=B/10;等でコンパイルは通るのですが、計算結果は
      正しくならない模様です。おそらく割り算に必要なライブラリを登録していないためと思います。
      しかし、考えてみると、汎用的な割り算はかなりのステップを消費するはずです。
      ライブラリをリンクすると貴重なメモリを消費すると想像されます。
      使わないものと割り切って、右シフトで代用するようにします。

④行番号1、行増分1、出力形式DEC、一行データ数45とすると一番多くのコードをichigojamに送れる。
  → 出力形式HEXだと1バイトが必ず#xxで3文字消費しますが、DECにすると1~3バイトにで
    平均は3バイト以下になります。
    一行データ数はIJBIN2POKEプルダウンでは20までですが、キーボードから直接数字をいれることで
    20より大きい数が入ります。ここを大きくするとPOKE文のアドレス部分が減るのでお得になります。
    45より大きくするとichigojamの1行の長さを超えるエラーになります。

    これでコンパイル結果だいたい256バイトでichigojam用POKE文コードが1KBになるくらいのようです。
    PCG領域256BYTEをマシン語領域に使うならちょうどよいくらいです。

    しかしマシン語256バイトって、32ビットコードで64ステップなんですよね。
    中々複雑なことはできません。1KBあればかなりのことができそうですが、贅沢かな。

それではまたです。


2016.06.21 Tue l ICHIGOJAM l コメント (0) l top
昨日のソフトでXY座標をキー入力で制御する方法を思いついたので、早速導入してみました。

今日のソースは以下の通りです。昨日は普通に引数cの値によってX,Yを増減し、0または63(Yは0または31)で反対側に折り返す、というコードにしていたのですが、それではメモリが足りず悩んでいたところでした。
以下の方法でなんとかPCG領域の256byteにおさまるようになりました。

  ・X,Yの増減を配列変数で引き渡す。
  ・固定値-5を必ず引くことでX,Y増減値はを正の数で良しとする。
    (例えば10と入れると+5、0、5といれると0、と入れると‐5になります。)
  ・増減後にXは0x3f、Yは0x1fとのANDをとることで折り返し演算を簡単にする。

#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 x,y,v,w,z,x0,y0,z0,i,j,k;
uint8_t* w_p = m_p + WORK_ADR;
uint8_t* v_p = m_p + VRAM_ADR;

//***** ERASE/MOVE/DISP STARS ************
for (i=0;i<19;i++) {
j=i*3;
x=w_p[j];y=w_p[j+1];z0=w_p[j+2];
x0=( (z0*(x-32)) >> 5)+32;
y0=( (z0*(y-16)) >> 5) + 20;
w=(y0/2)*32+(x0/2);
z= 1 <<( (x0&1)+((y0&1)<<1)) ;
k= v_p[w] | 0x80;
if ( (v_p[w]&0x70) ==0x00 ) {
if (c==1) {
v_p [w]= k & (0x8f - z) ;
}
if (c==2) {
v_p [w]= k | z ;
}
}
if (c>=3) {
z0+=3;if (z0>32) {z0=10;}
x=x+ w_p[90] - 5;
y=y+ w_p[91] - 5;
w_p[j] = x & 0x3f;
w_p[j+1] = y & 0x1f;
w_p[j+2] = z0;
}
}
return 0;
}


これによるマシン語プログラムは以下の通りです。
IJBIN2POKEの行番号を1、行ステップを1、1行当たり数を45に設定してぎりぎり1024バイトに収まるコードができました。

1 poke#700,#f0,#b5,#90,#22,#35,#4d,#12,#01,#87,#b0,#8a,#18,#80,#24,#4d,#19,#24,#01,#04,#92,#05,#95,#0b,#19,#1e,#78,#9a,#78,#5f,#78,#34,#1c,#00,#92,#20,#3c,#54,#43,#00,#9d,#3a,#1c,#10,#3a,#6a
2 poke#72d,#43,#52,#11,#14,#32,#12,#04,#64,#11,#12,#0c,#20,#34,#15,#04,#2d,#14,#24,#04,#03,#97,#24,#0c,#ef,#0f,#7f,#19,#25,#04,#7f,#10,#2d,#14,#02,#96,#7e,#01,#ef,#0f,#bc,#46,#65,#44,#6d,#10
3 poke#75a,#75,#19,#2d,#04,#04,#9e,#2d,#14,#75,#19,#2f,#78,#70,#26,#bc,#46,#37,#42,#14,#d1,#01,#27,#3a,#40,#ba,#40,#3c,#40,#a4,#18,#a7,#40,#62,#46,#80,#24,#14,#43,#01,#28,#04,#d1,#71,#22,#52
4 poke#787,#42,#d7,#1b,#3c,#40,#02,#e0,#02,#28,#02,#d1,#3c,#43,#2c,#70,#17,#e0,#02,#28,#15,#d9,#00,#9e,#03,#36,#20,#2e,#00,#dd,#0a,#26,#0e,#4a,#8a,#5c,#03,#9c,#05,#3a,#a2,#18,#0c,#4c,#0c,#5d
5 poke#7b4,#02,#9d,#05,#3c,#2c,#19,#3f,#25,#2c,#40,#1c,#70,#1f,#24,#22,#40,#5a,#70,#9e,#70,#05,#9e,#03,#33,#b3,#42,#a3,#d1,#00,#20,#07,#b0,#f0,#bc,#02,#bc,#08,#47,#c0,#46,#39,#08,#00,#00,#5b
6 poke#7e1,#08,#00,#00,#5a,#08,#00,#00


そしてスターラスターもどき。


動きは動画でどうぞ。


「スポンサードリンク」

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



メインプログラムは以下の通りです。ほぼ1KB使いきりです。

2016/6/21 下のコードはichigojamの特殊キャラクタが文字化けしています。
お使いになる方は、このZIPファイルをダウンロード、解凍してできたmain20160621.txtをIJUtilities等のソフトでichigojamに転送してください。



5 CLV
10 CLS
20 FORI=0TO11:LC1+I,3+I:?CHR$(26):LC30-I,3+I:?CHR$(25):NEXT
30 LC11,15:?""
32 FORI=16TO21:LC11,I:?" ":NEXT
34 LC11,22:?"
5 LC15,18:?""
36 FORI=0TO2:LC2+I*3,18-I:?"===";:LC21+I*3,16+I:?"===";:NEXT
40 LC16,11:?"+"
100 X=16:Y=11:FORI=0TO29
120 POKE#800+I*3,RND(64),RND(32),10+RND(30)
130 NEXT
132 IFV=0GOSUB1000:V=1
135 POKE#800+90,5,5
200 A=USR(#700,1)
210 A=USR(#700,3)
220 A=USR(#700,2)
223 POKE#800+90,5,5
224 K=INKEY():IF K=32 GOTO 500
225 LCX,Y:?" ";:IF K=0:X=16:Y=11
226 IF K=28 Y=11:X=15:LCX,Y:POKE#800+90,10,5
227 IF K=29 Y=11:X=17:POKE#800+90,0,5
228 IF K=31 Y=12:X=16:POKE#800+90,5,0
229 IF K=30 Y=10:X=16:POKE#800+90,5,10
230 LCX,Y:?"+";:WAIT5
240 GOTO200
500 I=0
520 A=USR(#700,3)
530 A=USR(#700,2)
536 IF (I%8)=0 THEN FORJ=0TO19:POKE#800+J*3,RND(64),RND(32),10+RND(30):NEXT
540 I=I+1:IFI<100GOTO520
550 GOTO10
1000 PLAY"T300O4G8R8D8D2R8D4O5C4O4B4A8B8A8B8A2R4"
1005 IF SOUND()=1 GOTO 1005
1010 PLAY"T300O4G8R8D8D2R8D4O5C4O4B4A8B8A8B8O5C2R8C8.C8.C8.D2."
1020 RTN


メモリ制約回避は中々頭の体操になります。
2016.06.20 Mon l ICHIGOJAM l コメント (1) l top
マシン語の使い方がわかってきたのでスターウォーズ風の3D画面を作ってみました。




まずマシン語コード。これをSAVE0として保存します。


1 poke#700,#f7,#b5,#2e,#4f,#90,#22,#80,#24,#cf,#19,#12,#01,#24,#01,#01,#97,#8e,#18,#0b,#19
2 poke#714,#5a,#78,#9d,#78,#18,#3a,#6a,#43,#19,#78,#20,#39,#69,#43,#12,#11,#18,#32,#12,#04
3 poke#728,#12,#0c,#14,#04,#49,#11,#24,#14,#20,#31,#e7,#0f,#09,#04,#09,#0c,#3f,#19,#7f,#10
4 poke#73c,#0c,#04,#7f,#01,#24,#14,#00,#97,#e7,#0f,#bc,#46,#64,#44,#67,#10,#00,#9c,#e7,#19
5 poke#750,#01,#24,#22,#40,#21,#40,#a2,#40,#3f,#04,#89,#18,#3f,#0c,#8c,#40,#01,#28,#0c,#d1
6 poke#764,#3f,#04,#3f,#14,#f7,#19,#3d,#78,#2a,#06,#00,#2a,#1b,#dc,#0f,#21,#0c,#1b,#25,#40
7 poke#778,#80,#24,#64,#42,#0b,#e0,#02,#28,#0c,#d1,#3f,#04,#3f,#14,#f7,#19,#3d,#78,#2a,#06
8 poke#78c,#00,#2a,#0c,#dc,#80,#21,#49,#42,#0c,#43,#25,#43,#3d,#70,#06,#e0,#03,#28,#04,#d1
9 poke#7a0,#03,#35,#20,#2d,#00,#dd,#0a,#25,#9d,#70,#01,#9f,#03,#33,#bb,#42,#b0,#d1,#0c,#20
10 poke#7b4,#fe,#bc,#02,#bc,#08,#47,#c0,#46,#57,#08,#00,#00


次がメインプログラム。これをSAVE1で保存します。

10 CLS
20 FORI=1TO8
30 LCI,I:?CHR$(26):LC31-I,I:?CHR$(25)
40 LCI,22-I:?CHR$(25):LC31-I,22-I:?CHR$(26)
50 NEXT
100 FORI=0TO29
120 POKE#800+I*3,RND(64),24-13+RND(26),10+RND(30)
130 NEXT
200 A=USR(#700,1)
210 A=USR(#700,3)
220 A=USR(#700,2)
225 IF INKEY()=32 GOTO 500
230 WAIT5
240 GOTO200
500 '*** warp ***
510 LC13,12:?"WARP!"
515 I=0
520 A=USR(#700,3)
530 A=USR(#700,2)
535 WAIT 5
536 IF (I%8)=0 THEN FORJ=0TO29:POKE#800+J*3,RND(64),24-13+RND(26),10+RND(30):NEXT
540 I=I+1:IFI<50GOTO520
550 GOTO10


こうしてLRUN0、LRUN1とすると3D画面もどきが出ます。


スペースキーでワープです。いまはこれしかできません。。。。。メモリ制限がきついです。

C言語ソースは以下の通りです。これをIJBIN2POKEにかけると最初のPOKE文ができます。
これでほぼ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 x,y,v,w,z,x0,y0,z0,i,j,k;
uint8_t* w_p = m_p + WORK_ADR;
uint8_t* v_p = m_p + VRAM_ADR;

//***** ERASE/MOVE/DISP STARS ************
for (i=0;i<29;i++) {
j=i*3;
x=w_p[j];y=w_p[j+1];z0=w_p[j+2];
x0=( (z0*(x-32)) >> 5)+32;
y0=( (z0*(y-24)) >> 4) + 24;
w=(y0/2)*32+(x0/2);
z= 1 <<( (x0&1)+((y0&1)<<1)) ;
k= v_p[w] | 0x80;
if ( (v_p[w]>=0x80) ||(v_p[w]==0) ) {
if (c==1) {
v_p [w]= k & (0x0f - z) ;
}
if (c==2) {
v_p [w]= k | z ;
}
}
if (c>=3) {
z0+=3;if (z0>32) {z0=10;}
w_p[j+2] = z0;
}
}
return 0;
}


とりあえず今回の休みはここまで。

次はいつできるか不明です。
2016.06.19 Sun l ICHIGOJAM l コメント (0) l top
マシン語で高速グラフィックをやろうとしていますが、どうもサブルーチンにするとうまくない動作をします。
下のようにpsetをサブルーチンにしているのですが、これだと暴走します。

#include
void pset(int16_t ,int16_t ) ;

int16_t usr_sample(int16_t val, void *mem)
{
int16_t x,y,v,w,z;
uint8_t *p0;
p0 = 0x100002d0;
for (y=0;y<10;y++) {
x=y;
pset(x,y);
//z=(x&1)+(y&1)*2;w=(y/2)*32+(x/2);
//p0[w]=p0[w] | (1< }
return -2 * val;
}

void pset(int16_t x,int16_t y)
{
int16_t w,z;
uint8_t *p0;
p0 = 0x100002d0;
z=(x&1)+(y&1)*2;w=(y/2)*32+(x/2);
p0[w]=p0[w] | (1<}


「スポンサードリンク」

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



pset関数内でx、yを固定値にすると正常に動くので、どうやら関数呼び出しは行われている物の、引数の引き継ぎがうまくできていないみたいです。

ならば、と思って以下のようにしてみました。グローバル変数X,Yを定義して、その値を渡してみます。

#include
int16_t X,Y; <====================== ここ変更
void pset(int16_t ,int16_t ) ;
int16_t usr_sample(int16_t val, void *mem)
{
int16_t x,y,v,w,z;
uint8_t *p0;
p0 = 0x100002d0;
for (y=0;y<10;y++) {
X=x;Y=y; <====================== ここ変更
pset(X,Y); <====================== ここ変更
//z=(x&1)+(y&1)*2;w=(y/2)*32+(x/2);
//p0[w]=p0[w] | (1< }
return -2 * val;
}

void pset(int16_t x,int16_t y)
{
int16_t w,z;
uint8_t *p0;
p0 = 0x100002d0;
z=(x&1)+(y&1)*2;w=(y/2)*32+(x/2);
p0[w]=p0[w] | (1<}



これでもだめでした。そういうものなのかな?

単一関数で作ると同じような処理で無駄が多発するのでサブルーチンは使いたいですね。
固定メモリ領域で引数を渡せばよさそうですが、それも美しくないですね。

何かコンパイル、リンク設定的なものがないか調べてみようと思います。


2016.06.19 Sun l 未分類 l コメント (0) l top
どうもVRAMの指定アドレスと表示が合わないな、と思って調べていたところ、
猫にコ・ン・バ・ン・ワ様の別のページを見つけました。

ichigojamのファームバージョンごとに実アドレスが違っているということですね。それはそうですね。
実アドレスを調べるコードを開示していただいているので、それを使ってみたところ、Version1.2.1では以下と分かりました。

MEMORY MAP
#000 CHR 0x00004FF0
#700 PCG 0x100000D0
#800 VAL 0x100001D0
#900 VRM 0x100002D0
#C00 PRG 0x100005D0


これで再度試してみます。


2016.06.19 Sun l ICHIGOJAM l コメント (0) l top
ichigojamファームを1.2.1にバージョンアップしてみたところ、以前のものよりかなり速くなっていることが分かりました。

この際だからマシン語と組み合わせて色々やってみようかと思い、環境をセットアップしました。

使ったのが、こちらのIJUTILITYS様のところにある。IJBIN2POKEです。



「スポンサードリンク」

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




これは大変素晴らしいソフトで、上の入力スペースにC言語を入れると、即ICHIGOJAM用のPOKE文データを吐き出してくれます。写真は画面を@で埋めるCソースで試したもので、コードは下のようになります。

#include
int16_t usr_sample(int16_t val, void *mem)
{
int x,y;
char *p0;
p0=0x10000388;
for (x=0;x<24;x++) {
for (y=0;y<32;y++) {
*p0++ = 0x40;
}
}
}

最初 p0=0x900としていたのですが、それだと暴走します。仮想アドレスと気付いて、実アドレスの所在を調べたところ
猫にコ・ン・バ・ン・ワ様の所で公開されているのを見つけ、p0=0x10000388;としたところ、うまく動くようになりました。

スピードはさすがマシン語で、一瞬に画面を@で埋め尽くします。
マシン語サイズも32BYTE程で思ったよりコンパクトです。これはgccがえらいのかな。

ともかく、これでマシン語も使えるようになりましたので、昔を思い出して色々作ってみようかと思います。










2016.06.19 Sun l ICHIGOJAM l コメント (0) l top
ichigojamと繋いでプログラム動作させてみました。
全体像はこんな感じです。


配線は以下のように。



100円ピアノのGND(電池のマイナス)と8個のキーパッドをichigojamのGND,OUT1~6、8,9に繋ぎます。
キーはドレミファソラシドの順でOUT1~6、8,9とします。

動きは動画でご覧ください。


「スポンサードリンク」

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


プログラムは以下の通りです。コマンドとして以下が有ります。

  ”Pキー” :普通の演奏モードです。1~8キーでドレミファソラシドの演奏。スペースでモードから抜けます。
  ”Rキー” :演奏記録モードです。1~8キーでドレミファソラシドの演奏。スペースでモードから抜けます。
          または最大50音符で抜けます。
  ”Mキー” :メモり演奏モードです。演奏記録モードで演奏した内容をリピートします。

2016/6/19AM9 510行、820行を修正しました。

15 t=0:p=0
20 CLS
40 ?"***** 100yen piano *****
60 lc1,5:?"DO RE MI FA SO RA SI DO"
70 OUT1,0:OUT2,0:OUT3,0:OUT4,0:OUT5,0:OUT6,0:OUT8,0:OUT9,0
90 LC1,8:?"Play Rec MemPlay"
100 K=INKEY()
110 IF K=112 OR K=80 GOTO 200
120 IF K=114 OR K=82 GOTO 500
125 IF K=109 OR K=77 GOTO 800
130 GOTO 100
200 '***** PLAYING *****
210 LC1,10:?"PLAYING"
220 GOSUB900
230 IF K=32 GOTO 20
300 GOTO 220
500 LC1,10:?"RECORDING"
510 P=0:T=0
520 GOSUB 900
530 LC1,12:?"TONE:";K;"TIME:";T;" "
540 IF K=32 GOTO 700
550 [P*2]=T:[P*2+1]=K:T=0
560 P=P+1:IF P>=50 GOTO 700
600 GOTO 520
700 LC1,14:?"ENDED"
710 WAIT 60:GOTO 20
800 I=0
805 IF I>=P GOTO 20
806 LC1,12:?I
810 FORJ=0TO[I*2]*2:NEXT
820 K=[I*2+1]+#30:GOSUB943
830 I=I+1:GOTO805
900 K=INKEY():IF K<>0 GOTO 930
910 IF T<10000 T=T+1
920 GOTO 900
930 IF K=32 RTN
940 IF K<#31 OR K>#38 RTN
943 LC1,6:?" ";
945 LC1+(K-#31)*3,6:?"^^^";
950 K=K-#30
960 IF K<7 THEN OUT K,1:WAIT10:OUT K,0:RTN
970 OUT K+1,1:WAIT10:OUT K+1,0
980 RTN


これで普通演奏、録音、再生ができます。
プログラムを工夫すればオルゴールや、ichigojamの演奏機能を合奏なども出来ると思います。




※ご注意:電池3Vで動いているおもちゃですし何か問題が有るとは思えませんが、特にデータシート等が有るわけではないので申し訳ないですが保証はできないです。同じことを実験される場合は一応自己責任でお願いいたします。
2016.06.18 Sat l 未分類 l コメント (0) l top
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。