カテゴリ: IchigoJam

  • タイトル
    91X(電子工作マガジン2018年AUTUMN号掲載)

  • 開発環境
    IchigojamBASIC1.2.1

  • 内容
    マーカー(自機)を動かし、自分の領域を増やしていく陣取りゲームです。

  • 遊び方
    マーカーは矢印キーで移動し、自分のエリア(濃いアミカケ)内を自由に移動することができます。
    スペースキーを押しながら矢印キーを押すと、自分のエリア外にライン(薄いアミカケ)を引きながら移動することができます。
    再度自分のエリアに戻ってくると、ラインで囲った領域が新たに自分のエリアとなります。
    マーカーが敵に触れたり、作成中のラインに敵が触れるとゲームオーバーです。
    1回のラインで多くのエリアを確保すると得られる得点がアップします。

  • qix
  • 操作方法
    [↑]キー上移動
    [↓]キー下移動
    [←]キー左移動
    [→]キー右移動
    [SPACE]キーラインを引く

    画面の「S」はスコア、「A」は確保したエリア、「T」は残り時間です。

  • プログラムのしくみ
    機械語部分(プログラム1)とBASIC部分(プログラム2)に分かれています。
    機械語ルーチンは、初期画面作成、敵キャラクタの移動、塗りつぶしの3つの処理が含まれています。
    BASICルーチンは、キー入力、マーカー移動、サウンド等の処理をしています。

    変数表
    E,F,G頻出数字
    I,Jループ用一時変数
    A確保領域
    M自分の位置
    N自分の位置に元々あったキャラクタ
    C自分または敵の移動先キャラクタ
    V自分または敵の移動方向
    Q敵の頭の位置
    O敵の尾の位置
    P敵の長さ
    D線描画フラグ
    Kキー入力
    B新たに確保した領域
    Sスコア
    Wウエイト用

    機械語サブルーチン(プログラム1)
    USR(#700,0)
    塗りつぶし
    引数:無し
    戻値:領域数
    USR(#774,0)
    枠描画
    引数:無し
    戻値:無し
    USR(#77C,1)
    敵移動
    引数:上位4bit=キャラクタ(RND(14))+下位4bit=方向(RND(4))
    戻値:FF=GameOver/FE=retry_RND(4)/FD=error/00=no_error

  • プログラムの具体的な入力方法
    プログラム1は機械語プログラムですので、間違えないように入力してください。
    入力間違いがあるとエラーメッセージが出ずに、IchigoJamが操作不能になってしまう可能性があります。
    ですので、プログラムを入力したら、まずSAVEしてからRUNするようにしてください。
    もしIchigoJamが操作不能になってしまった場合は電源を入れ直してください。
    (保存していないプログラムは消えてしまいます)
    また、6行の「END」を、「(例)LRUN2」のようにプログラム2の保存番号に変更すると、プログラム1を実行後すぐにプログラム2を読み込んで実行することができます。
    プログラム1は通常のPOKE文だとメモリ容量を超えてしまうため、BASE16というアルゴリズムで圧縮してあります。
    (正確にはバイナリ→テキスト変換。POKE文を利用したプログラムに対して圧縮の意味)

  • プログラムの改造
    プログラム2のPに4を加えた数が敵の初期の長さになります。長くすると難しくなります。(短くすると正しく動作しません)
    Wは全体の動きを遅くするための数値です。初期値5から1面クリアごとに小さく(=早く)なります。増減させて難易度を変更できます。
    7行の9999は制限時間です。増減させて難易度を変更できます。

  • 91X(プログラム1)
    1 'QIX1
    2 Z="ONKEI@B@@@@ADGAHBNBFCF@AB@BB@ACBKBDBALMLM@EMB@BH@CM@HABHOGMKHNBHOEMLMAAIB@CI@@BC@@O@@JOHAOBC@@O@@GOHBABC@@O@@DOHD@BC@@O@@AOHNFNGLHEL@@BH@@M@G@DGB@B@LHEDMNNG@@B@":Y=#700:GSB8
    3 Z="B@BBB@BDMAEM@KAK@GM@@CBI@CM@@DBI@AM@@@BI@BMA@AC@@CBCMCEE@ACBKBDBO@MKONKMONKD@FB@I@BGCO@AGOAHKNBFCF@AGFAHB@BB@ACJM@EEI@EEOKMACMDFAOCEFNALBLBBAB@AE@EEI@EEB@CJOKME":Y=#750:GSB8
    4 Z="@CB@GNALBABALHEEHHEEB@CALHEEHHEEONKLG@DG@@KE@BKD@ODF@HBFCF@BOLCFCNDDKEAL@B@II@DF@CBBA@D@@@BBJLEJB@CLCLDDDAAN@FM@AOBA@BBH@CM@BABA@CBH@@M@D@BAOOB@FBEL@DBJ@FMAHOBB":Y=#7A0:GSB8
    5 Z="FBEDDBDFHACBB@BAFBEDDAN@ONB@@@BJCNMAFCAHB@CK@@BA@@O@CMOH@@BHCGMAAOBA@@O@CHOH@@BHCBMABABA@@O@CCOH@@BHBMMAD@BA@@O@BNOH@@BHBHMADADFHACAB@CDBAG@B@CCMKAK@@BBJKEBKCEJ":Y=#7F0:GSB8
    6 Z="CKDDB@CK@@BA@@O@ANOH@@BHA@MAAOBA@@O@AIOH@@BH@KMABABA@@O@ADOH@@BH@FMAD@BA@@O@@OOH@@BH@AMAOMB@@GN@@@B@AJDFB@CBA@G@@KDDMKAK@@BBKCEB@BKL@@KMG@DG@@B@EJELH@BJ@BMMHOBJ":Y=#840:GSB8
    7 Z="@@MJONB@G@DG":Y=#890:GSB8:END
    8 W=Y+LEN(Z)/2-1:FORX=YTOW:POKEX,PEEK(Z)&15<<4+PEEK(Z+1)&15:Z=Z+2:NEXT:RTN
    

    91X(プログラム2)
    1 'QIX2
    '全体初期設定
    2 E=143:F=32:G=23:s=0:p=0:W=5
    '面初期設定
    3 CLS:A=USR(#774,0):A=0:LC21,G:?"T:";:M=#921:N=3:V=1:P=P+4:W=W-1:PLAY"T700EREDRDRDE2REFRFGR0R0"
    'QIX配置
    4 Z=#9A0+RND(512):IFPEEK(Z)GOTO4ELSEPOKEZ,134:Y=Z:FORI=0TOP:Y=Y+V:IFY<#960Y=Y+F:V=1:I=I-1ELSEIFPEEK(Y)Y=Y+31:IFPEEK(Y)Y=Y-33:IFPEEK(Y)Y=Y+1:V=-F:I=I-1
    5 POKEY,134:NEXT:CLT:C=3:N=4:V=0:wait120:GOTOG
    'QIX移動
    6 J=J+1:IFJ>9J=Y:Y=Z:Z=J:J=0:POKEZ,E:GOTO6
    7 a=usr(#7B4,rnd(14)<<4+rnd(4)):IFa=#FF||TICK()>9999POKEZ+V,E:POKEZ,E:GOTOFelseifa=#FEgoto6
    10 J=0:LCG,G:?9999-TICK();:WAITW
    '自移動
    11 V=0:D=0:K=PEEK(#1002):IF!KGOTO6ELSEIFK&16D=1
    12 IFK&1V=-1ELSEIFK&2V=1ELSEIFK&4V=-FELSEIFK&8V=F
    13 C=PEEK(M+V):IFD&&(C>128&&C74LC12,10:?" CLEAR ";:play"t999erer9grgr9brb":WAITE:GOTO3
    24 IFC=3POKEM,N:M=M+V:N=PEEK(M):POKEM,42
    25 IF!C&&DPOKEM,N:M=M+V:N=4:POKEM,42
    26 GOTO6
    32 lc9,9:?"GAME OVER":play"t500fr9fgfrfgedc":LC0,0:OK
    

    91X(プログラム1のアセンブラリスト)
    '塗りつぶし	引数:無し/戻値:領域数
    push	{r1-r7,LR}
    mov	r0,#90
    lsl	r0,r0,4		'仮想LC0,0(#900)
    add	r7,r0,r1	'R7=実VRAM
    mov	r6,#2E		'#BE0-#900=#2E0
    lsl	r6,r6,4		'R6=仮想LC0,23(#BE0)
    @VRAMTOP		'敵側塗りつぶし(#20)	R2=カウンタ
    mov	r2,#20					
    @LOOP1			'敵側探索
    add	r2,1
    cmp	r2,r6
    bgt	@FILL		'塗りつぶし
    ldrb	r0,[r2,r7]				
    cmp	r0,#20					
    beq	@LBL1					
    cmp	r0,#81					
    blt	@LOOP1
    cmp	r0,#8E
    bgt	@LOOP1
    @LBL1			'!= ,!=O,!=o
    add	r1,r2,r7
    sub	r1,#20		'R1=チェックVRAM
    mov	r3,#00		'R3=R1の上
    gosub	@CHKNULL				
    mov	r3,#1F		'R3=R1の左
    gosub	@CHKNULL			
    mov	r3,#21		'R3=R1の右
    gosub	@CHKNULL				
    mov	r3,#40		'R3=R1の下
    gosub	@CHKNULL				
    bla	@LOOP1					
    @CHKNULL
    ldrb	r0,[r1,r3]
    cmp	r0,#00
    beq	@PUTSPC
    ret
    @PUTSPC
    mov	r0,#20		'R0=CHR$(#20)=SPACE
    strb	r0,[r1,r3]
    bla	@VRAMTOP
    @FILL			'自領域塗りつぶし(#00)
    mov	r0,#00		'R0=領域数(戻値)
    mov	r2,#20		'R2=カウンタ
    mov	r4,#20
    @LOOP2
    ldrb	r1,[r2,r7]				
    sub	r3,r1,r4
    beq	@LBL3					
    cmp	r1,#03
    beq	@LBL2
    cmp	r1,#04
    beq	@LBL2
    cmp	r1,#00
    bne	@LBL4
    @LBL2
    add	r0,#01					
    mov	r3,#03
    @LBL3
    strb	r3,[r2,r7]				
    @LBL4
    add	r2,1
    cmp	r2,r6					
    blt	@LOOP2					
    pop	{r1-r7,PC}
    
    'nop
    'nop
    
    '--枠描画
    '枠	引数:無し/戻値:無し
    push	{r1-r7}
    mov	r0,#0,6
    mov	r7,#90
    lsl	r7,r7,4		'仮想LC0,0(#900)
    add	r7,r7,r1	'R7=実LC0,0
    mov	r6,#BE
    lsl	r6,r6,4		'仮想LC0,23(#BE0)
    add	r6,r6,r1	'R6=実LC0,23
    mov	r2,#20		'R2=カウンタ
    @KABELOOP1
    sub	r2,#01
    strb	r0,[r2,r7]	'上枠
    strb	r0,[r2,r6]	'下枠
    bne	@KABELOOP1
    mov	r5,r7
    add	r5,#1F		'#91F
    add	r6,r5,1		'#920
    mov	r2,#2C		'R2=カウンタ(#2C0)
    lsl	r2,r2,4
    @KABELOOP2
    strb	r0,[r2,r5]	'右枠
    strb	r0,[r2,r6]	'左枠
    sub	r2,#20
    bpl	@KABELOOP2	'r2>#00(=r2+r5>#900)
    mov	r0,#03
    add	r6,r7,#01
    mov	r1,#21
    strb	r0,[r1,r7]
    strb	r0,[r1,r6]
    add	r1,#20
    strb	r0,[r1,r7]
    'mov	r0,#2A		'#2A="*"
    strb	r0,[r1,r6]
    pop	{r1-r7}
    ret
    
    'nop
    'nop
    
    '--QIX移動
    '使用変数:q,o
    '引数(R0)	上位4bit=キャラクタ(RND(14))
    '		下位4bit=方向(RND(4))
    '戻値(R0)	FF=GameOver/FE=retry_RND(4)/FD=error/00=no error
    push	{LR}
    push	{r1-r10}
    mov	r7,r1		'R7=実VRAM先頭アドレス
    mov	r6,#08
    lsl	r6,r6,#08
    add	r6,#FC
    add	r6,r7		'R6=#8FC=Y(=o)
    add	r5,r6,#02	'R5=#8FE=Z(=q)
    lsr	r2,r0,#04
    mov	r8,r2		'R8=キャラクタ(RND(14))
    mov	r2,#03
    and	r0,r2
    'mov	r9,r0		'R9=方向(RND(4))
    mov	r2,#00
    ldrh	r4,[r5,r2]	
    sub	r4,#20		
    add	r4,r7
    sub	r1,r0,#1	'RND=1	上
    beq	@Q_EAT		'R1=0
    mov	r1,#1F
    cmp	r0,#02		'RND=2	左
    beq	@Q_EAT		'R1=31
    mov	r1,#21
    cmp	r0,#03		'RND=3	右
    beq	@Q_EAT		'R1=33
    mov	r1,#40		'R1=64 RND=0	下
    @Q_EAT
    mov	r0,#FF
    ldrb	r2,[r4,r1]	'R2=Q+V
    cmp	r2,#04
    bne	@Q_NL_CK		
    mov	r2,#8F
    strb	r2,[r4,r1]		
    mov	r2,r8
    add	r2,#81
    mov	r1,#20
    strb	r2,[r4,r1]		
    bla	@Q_EXIT
    
    @Q_NL_CK
    mov	r0,#FE
    cmp	r2,#00
    bne	@Q_EXIT			
    add	r3,r4,r1
    sub	r3,#20		
    mov	r1,#00
    gosub	@Q_CHECK
    cmp	r0,#00
    bne	@Q_EXIT
    mov	r1,#1F
    gosub	@Q_CHECK
    cmp	r0,#00
    bne	@Q_EXIT
    mov	r1,#21
    gosub	@Q_CHECK
    cmp	r0,#00
    bne	@Q_EXIT
    mov	r1,#40
    gosub	@Q_CHECK
    cmp	r0,#00
    bne	@Q_EXIT
    mov	r1,r8		'R8=キャラクタ(RND(14))
    add	r1,#81
    add	r4,#20
    strb	r1,[r4,#00]		
    add	r3,#20		
    sub	r3,r3,r7
    mov	r2,#00
    strh	r3,[r5,r2]		
    
    ldrh	r3,[r6,r2]		
    add	r3,r7
    sub	r3,#20		
    
    mov	r1,#00
    gosub	@Q_CHECK
    cmp	r0,#00
    bne	@Q_TAIL
    mov	r1,#1F
    gosub	@Q_CHECK
    cmp	r0,#00
    bne	@Q_TAIL
    mov	r1,#21
    gosub	@Q_CHECK	
    cmp	r0,#00
    bne	@Q_TAIL
    mov	r1,#40
    gosub	@Q_CHECK
    cmp	r0,#00
    bne	@Q_TAIL
    mov	r0,#FD		'error
    BLA	@Q_EXIT
    @Q_TAIL
    mov	r0,#00
    mov	r2,r3
    add	r2,#20
    strb	r0,[r2,#00]	
    add	r3,r1
    sub	r3,r3,r7
    mov	r2,#00
    strh	r3,[r6,r2]	'O=O+[I]
    @Q_EXIT
    pop	{r1-r10}
    pop	{PC}
    ret
    'sub
    @Q_CHECK
    mov	r0,#00
    ldrb	r2,[r3,r1]	'R2=Q+V-r1	
    cmp	r2,#80
    ble	@Q_CHK_RET		
    cmp	r2,#8F
    bge	@Q_CHK_RET		
    mov	r0,#FE		'rnd(4) retry
    @Q_CHK_RET
    ret
    


    MixJuiceでのダウンロードURLは下記になります。
    91x(1) http://tagiyasoft.blog.jp/91x1.bin
    91x(2) http://tagiyasoft.blog.jp/91x2.bin

    以下のように入力してD/Lしてください。
    NEW
    ? MJ GET http://tagiyasoft.blog.jp/91x1.bin
    ? MJ GET http://tagiyasoft.blog.jp/91x2.bin
    

    ブラウザでD/LしてIchigoJamに転送する場合は、通信ソフトでバイナリ送信をしてください。
    (例:TeraTermの場合は、メニューの[ファイル]-[ファイル送信]で当該ファイルを送信します)

  • 参考ゲーム
    QIX

  • タイトル
    UFOキャプチャー(電子工作マガジン2018年SUMMER号掲載)

  • 開発環境
    IchigojamBASIC1.2.1

  • 内容
    UFOを操作してキャラクタをキャプチャ(捕獲)するゲームです。
  • UFOcapture
  • 遊び方
    UFOの横方向と縦方法の移動位置を入力するとUFOがキャラクタを捕獲します。
    キャラクタは1度に7個まで捕獲することができます。
    捕獲したキャラクタは画面右の捕獲エリアに並べて保管されます。
    この時、同じキャラクタを3つ以上並べると並んだキャラクタが消え、得点が得られます。
    多数消し、連鎖消しにより高得点が得られます。

  • 操作方法
    「ヨコ:」と表示されたら、UFOの横方向の移動位置(画面上部の数字)を入力しEnterを押します。
    「タテ:」と表示されたら、UFOの縦方法の移動位置(画面左右の数字)を入力しEnterを押します。
    するとUFOが移動してキャラクタを捕獲します。

  • プログラムのしくみ
    変数表
    [0]~[48]キャラクタの配置
    [50]~[56]捕獲したキャラクタ
    I,Jループ用一時変数
    XUFO移動横位置
    YUFO移動縦位置
    C捕獲配列のキャラクタコード
    D捕獲配列の次のキャラクタコード
    R捕獲配列の同一キャラクタ連続数
    Z捕獲している数
    L連鎖フラグ
    A表示キャラクタの増分
    Sスコア

    各行の処理
    1行初期画面表示
    2行UFO移動位置の入力
    3行UFO左移動、捕獲アニメーション、捕獲配列へキャラを転送
    4行捕獲ビーム消去、UFO右移動、捕獲配列のキャラ連続チェック
    5行最上段のキャラチェック、キャラせり上げ、最下段補充
    6行ループ
    7行1段補充&描画
    8行連続キャラ消し、加点
    9行捕獲エリア描画

  • プログラムの具体的な入力方法
    プログラムリスト中の「□」はスペース1個です。(例:「□□□」はスペース3個)
    カードの枠線および、UFOは「左ALT+(SHIFT)+キー」で入力します。
    左ALT+SHIFT+H
    左ALT+SHIFT+I
    左ALT+SHIFT+Q
    左ALT+SHIFT+R
    左ALT+0(ゼロ)
    左ALT+8
    左ALT+1

  • プログラムの改造
    現時点で空きメモリが0バイトなので改造は難しいと思いますが、1行目の枠線表示をしないようにすれば、メモリに空きができるので改造がしやすくなります。
    7行のRND文で表示キャラクタを決めています。キャラクタの種類を増減したい場合は、RND文の"6"を増減してください。別のキャラクタを表示するようにするには"235"を変更してください。
    UFOの移動アニメーション速度を変更したい場合は、WAIT文(5ヶ所)の数値を変更してください。

  • プログラム
    1 cls:clv:fori=0to6:j=i*2:LC0,j+6:?i;"│":lc17,j+6:?"│";i,"□□│□□□│":?"□│":lc17,j+7:?"│□□□□□│□□□│":lcj+3,0:?i:gsb7:next:lc0,19:?"□└---------------┘□□□□□└---┘"
    2 lc20,0:?"SCORE:";s:lc0,20:?chr$(12):input"ヨコ:",x:input"タテ:",y:x=abs(x%7):y=abs(y%7)
    3 fori=10toxstep-1:lci*2+4,2:?"□□□":lci*2+2,2:?"←○→":wait9:next:lcx*2+3,4:?"^":fori=0toy:lcx*2+3,i*2+6:?"^":wait9:next:fori=yto0step-1:c=[i*7+x]:ifc[56-z]=c:[i*7+x]=0:z=z+1
    4 lcx*2+3,i*2+6:?chr$(0):wait9:next:lcx*2+3,4:?chr$(0):fori=xto11:lci*2,2:?"□□□":lci*2+2,2:?"←○→":wait9:next:gsb9:c=[50]:r=0:l=0:fori=1to7:d=[50+i]:ifd=cr=r+(c!=0)elsec=d:gosub8:r=0
    5 next:fori=0to6:i=i+[i]:next:ifi<7fori=0to6:forj=0to6:[i*7+j]=[i*7+j+7]:lcj*2+3,i*2+6:?chr$([i*7+j]):next:next:gsb7
    6 goto2
    7 forj=0to6:[i*7+j]=rnd(6+a)+235:lcj*2+3,i*2+6:?chr$([i*7+j]):next:rtn
    8 ifr<2rtnelse:forj=i-1to0step-1:[50+j]=[49+j-r]*(j-r>0):next:i=0:z=z-r-1:s=s+r*r*5/20*10+l*20:l=1:a=s/100
    9 forj=0to6:lc25,j*2+6:?chr$([50+j]):wait5:next:if![49]rtnelselc25,4:?chr$([49]):lc0,21:?chr$(12);"GAME OVER"
    

    MixJuiceでのダウンロードURLは下記になります。
    UFOcapture http://tagiyasoft.blog.jp/UFOcapture.bin

    以下のように入力してD/Lしてください。
    NEW
    ? MJ GET http://tagiyasoft.blog.jp/UFOcapture.bin
    

    ブラウザでD/LしてIchigoJamに転送する場合は、通信ソフトでバイナリ送信をしてください。
    (例:TeraTermの場合は、メニューの[ファイル]-[ファイル送信]で当該ファイルを送信します)

  • チェックサムプログラムとは
    「マイコンゲームの本 3」掲載の「チェック・サム プログラム」の項より引用します。

    チェック・サムとは
    ダンプリストを見ながらマシン語を打ち込む場合、打ち込みミスなどから、何度もリストとにらめっこしなくてはなりません。そのたびにリストの最初から最後まで調べるのでは、2回もやれば、よぼど根性のある人でもいやになります。
    そんなとき、プログラム(データ)をいくつかのブロックに分けて、そのブロック無いの数値を全部足した値をリストに付けておけば、そのリストを打ち込んだ人は、ブロックごとの数値を足してリストに付いている数値と比べればどのブロックが違っているか人目でわかります。後はそのブロックについてのみ、調べればよいことになります。

    すなわち、機械語プログラムを手入力する際、入力ミスを見つけやすくするための方法の一つとして、チェックサムという方法が使われていました。

  • 機械語プログラムについて dumplist
    右の写真は、ダンプリスト(機械語プログラムリスト)の例です。
    1970~80年代のマイコン雑誌には、このようなダンプリストが何ページにも渡って掲載され、プログラムによっては、全てを1文字の間違いもなく入力しないと正しく実行されませんでした。
    (実際はデータ部や変数部があるので「1文字も間違いなく」というのは正しい表現ではありませんが)
    まだインターネットはおろかパソコン通信ですら一般的ではなかったため、マイコン雑誌に掲載されたプログラム(主にゲーム)で遊ぶには、プログラムを入力するか、雑誌社の販売するカセットテープを買うしかありませんでした。
    (昨今ではコードの手入力を「写経」と呼ぶそうですが)

    現在はプログラムの投稿雑誌は姿を消し、雑誌のプログラムを手入力することはほとんど無くなりました。

  • BASICマガジンの復活で
    しかし、近年、BASICマガジンが復活したことで、雑誌に機械語リストが載ることが出てきました。
    そこで機械語プログラムの入力補助ツールとして、チェックサムプログラムを作ることにしました。

  • 仕様
    今回作ったチェックサムプログラムはIchigoJam用です。
    現在のIchigoJamの仕様では、機械語プログラムが可能なエリアが、最大で#700~#1001の約2KBになります。
    ですので、横サムのみ表示し、縦サムは省略しました。
    横サムは8バイトのサム(合計値)の下位1バイトを表示します。
    このサム値をソースリストに添付のサム値と照合して入力間違いを探します。

  • プログラムリスト
    プログラムは16進表示とBASE16のキャラクタ表示の2種類です。

    1行プログラムになっていますので、プログラムを入力(環境によっては貼り付け)後にEnterすれば、チェックサムプログラムが実行されます。
    保存しておきたい場合は、行頭に行番号を付けてSAVEしてください。

    チェックサムプログラム(16進表示)
    input"start address ",t:input"end address ",e:fora=ttoestep8:?hex$(a,3);:s=0:forx=0to7:v=peek(a+x):?" ";hex$(v,2);:s=(s+v)&#FF:next:?" :";hex$(s,2):next
    

    チェックサムプログラム(BASE16キャラクタ表示)
    input"start address ",t:input"end address ",e:fora=ttoestep8:?hex$(a,3);:s=0:forx=0to7:v=peek(a+x):?" ";chr$(64+(v>>4)&#F);chr$(64+v&#F);:s=(s+v)&#FF:next:?" :";hex$(s,2):next

  • チェック例
    下記のプログラムをチェックしてみます。
    (以前、BASE16の説明用に作ったプログラムです)

    1. プログラムの公開方法
      プログラムを公開する場合に、下記の様にチェックサムを併記します。

      サンプルプログラム
      10 poke #700,#0b,#22,#12,#02,#df,#32,#50,#18,#20,#30,#03,#78,#f0,#2b,#05,#d0,#20,#38,#03,#78,#f0,#2b,#01,#d0,#20,#30,#03,#70,#01,#3a,#10,#0a
      20 poke #720,#08,#28,#f0,#d1,#52,#18,#01,#20,#00,#23,#13,#54,#01,#30,#21,#28,#fb,#d1,#70,#47
      80 cls:x=15
      90 lc x,15:?chr$(#f0)
      100 k=inkey()
      110 if k!=0 then lcx,15:?" ":x=x+((k-1)%3-1)
      120 lc rnd(33),0:?"*"
      130 a=usr(#700,0)
      140 goto90
      
      チェックサム
      700 : BA
      708 : BB
      710 : BF
      718 : 18
      720 : 7C
      728 : 04
      730 : A1
      (チェックサム作成プログラムは後述します)

    2. プログラムのチェック方法
      プログラムを入力した後、POKE文のみ実行します。
      やり方としては、
      1. POKE文の後ろに"END"を付けて実行する。
        (上記例では「30 END」を追加する)
      2. まず、POKE文のみを入力して実行する。
      などの方法が考えられます。

      次にチェックサムプログラムを実行します。
      (BASE16エンコードされている場合は、BASE16キャラクタ表示版のプログラムを実行します)

      実行結果
      start address #700
      end address #733
      700 0B 22 12 02 DF 32 50 18 :BA
      708 20 30 03 78 F0 2B 05 D0 :BB
      710 20 38 03 78 F0 2B 01 D0 :BF
      718 20 30 03 70 01 3A 10 0A :18
      720 08 28 F0 D1 52 18 01 20 :7C
      728 00 23 13 54 01 30 21 28 :04
      730 FB D1 70 47 D6 10 38 00 :A1
      

      左端の3桁はアドレス、次に8バイトのメモリダンプ、右端がサム値になります。
      右端のサム値と、公開されているサム値を照合します。
      違いがあった場合は、該当する範囲のアドレス内容に違いがありますので、入力したプログラムリストを見直してください。

      ※注意
      最終行のサム値(上記例では#730~#737番地)は正しくない場合があります。
      1行プログラムにした仕様上の問題点ですので御了承ください。

  • 機械語プログラムにチェックサムを付けて公開する方へ
    メモリ内に機械語プログラムがある状態で、下記のプログラムを実行します。

    チェックサム作成プログラム
    input"start address ",t:input"end address ",e:fora=ttoestep8:?hex$
    orx=0to7:v=peek(a+x):s=(s+v)&#FF:next:?" : ";hex$(s,2):next

    実行するとチェックサムが作成されますので、プログラムリストに併記して公開してください。

  • タイトル
    pypyズラシ(電子工作マガジン2018年SPRING号掲載)

  • 開発環境
    IchigojamBASIC1.2.1

  • 内容
    画面のキャラクタを左右にずらし、縦横4個以上繋げて消すゲームです。
    5秒以内に4個繋がりを作ってください。
    目指せ20連鎖!
  • pypy
  • 遊び方
    RUNすると画面に5種類のキャラクタが8×8個並び、キャラクタの横に"> <"のマークが出ます。
    "> <"がある高さのキャラクタを左右にずらすことができます。
    左右にずらした時に端にあったキャラクタは反対側から現れます。
    キャラクタをずらして縦横に4個以上繋がるとキャラクタが消えます。
    一度の操作で異なる繋がりを消すと「連鎖(COMBO)」します。
    キャラクタが消えて宙に浮いたキャラクタは下に落ち、新たにキャラクタが上から落ちてきます。
    キャラクタが落ちてきて4個以上繋がった場合も「連鎖」が継続します。

    点数は「消えたキャラクタの数×連鎖回数」です。
    連鎖すればするほど高得点になります。

  • 操作方法
    [↑]キー"> <"マーク上移動
    [↓]キー"> <"マーク下移動
    [←]キー左ずらし
    [→]キー右ずらし

  • プログラムのしくみ
    機械語部分(プログラム1)とBASIC部分(プログラム2)に分かれています。
    機械語ルーチンは、繋がったキャラクタを消去する部分と、キャラクタが落ちる部分、キャラクタが消えている場所を返す部分の3つの処理が含まれています。
    BASICルーチンは、画面表示、キー入力、横ずらし、サウンド等の処理をしています。
    プログラム領域の最後(#FFC~#FFF)にハイスコアと最大連鎖を書き込んでいますので、プログラムをSAVEすることで電源を切ってもハイスコアを記憶し続けることができます。

  • 変数表
    Yハイスコア記録
    Sスコア
    Z最大連鎖数記録
    L最大連鎖数
    R連鎖数
    W連鎖の有無フラグ
    Gキャラ落ちの有無フラグ
    Aキャラの繋がり数(4以上/0=繋がり無し)
    Bキャラ種類の増分
    Hキャラ補充フラグ(0=補充無し/1=補充有り)
    Kキー入力
    X"> <"マーク位置
    C"> <"マーク表示フラグ(1=表示/0=消去)
    O,D,E,F,P,Iずらし用一時変数

    プログラム2
    1行コメント文
    2行初期化、文字表示
    3行キャラクタ画面表示
    4行キャラ落下
    5行4個繋がりの消去
    6~8行連鎖処理
    9行キャラ補充
    10行最大連鎖更新
    11行タイマクリア
    12行キー入力、時間切れチェック
    13行左右ずらし
    14~16行"> <"マーク移動
    17~18行画面キャラ表示サブルーチン
    19行"> <"マーク表示サブルーチン
    20行ゲームオーバー処理、ハイスコア更新
    21行最大連鎖記録更新
    22行記録保存

    機械語サブルーチン(プログラム1)
    USR(#700,0)4個以上の繋がり消去引数:無し/戻値:繋がって消えたキャラ数
    USR(#77C,0)キャラクタの空白位置引数:0/戻値:キャラクタの空白位置(#920からの増分)
    USR(#77C,1)キャラクタ落下引数:1/戻値:落下の有無(0=無/1=有)
  • プログラムの具体的な入力方法
    プログラム1は機械語サブルーチンになっていますので、間違えないように入力してください。
    入力間違いがあるとエラーメッセージが出ずに、IchigoJamが操作不能になってしまう可能性があります。
    ですので、プログラムを入力したら、まずSAVEしてからRUNするようにしてください。
    もしIchigoJamが操作不能になってしまった場合は電源を入れ直してください。
    (保存していないプログラムは消えてしまいます)
    また、最終行にプログラム2の保存番号を書くと(例:LRUN2)、プログラム1実行後すぐにプログラム2を読み込んで実行することができます。

  • プログラムの改造
    • プログラム1
      20行の配列は、表示するキャラクタのコード番号です。
      お気に入りキャラや見やすいキャラクタに変更する場合はコード番号を変更してください。
      自作キャラを使用する場合は、キャラクタコード#F8~#FFに設定してください。

    • プログラム2
      12行の"IFK>300"はタイマ値です。300より大きくするとタイマが長くなり、小さくすると短くなります。
      6行は連鎖時のサウンドです。自由に変更できます。
      プログラム領域の最後(#FFC~#FFF)をハイスコアと最大連鎖の保存に使用していますので、プログラムがその領域にかからないように4byte以上残しておいてください。

  • プログラム1
    10 'pypyズラシ-1
    20 CLP:[0]=#720:[1]=#728:[2]=#730:[3]=#738:[4]=#740:[5]=#748:[6]=#758:[7]=#760
    30 FORI=0TO8:COPY#7C0+I*8,[I],8:NEXT
    40 POKE #700,0,181,254,180,8,38,54,2,14,68,146,39,63,1,15,68
    50 POKE #710,0,37,1,32,48,112,117,112,0,35,124,93,248,44,28,219
    60 POKE #720,1,51,242,92,0,32,184,84,17,28,32,57,0,240,28,248
    70 POKE #730,17,28,32,49,0,240,24,248,81,30,0,240,21,248,81,28
    80 POKE #740,0,240,18,248,48,120,131,66,234,219,48,120,4,43,9,218
    90 POKE #750,49,92,124,84,1,56,251,209,48,112,1,53,255,32,40,64
    100 POKE #760,0,40,214,209,254,188,0,189,120,92,160,66,3,209,48,120
    110 POKE #770,1,48,48,112,49,84,112,71,0,0,0,0,254,180,6,28
    120 POKE #780,0,32,146,37,45,1,13,68,208,36,41,93,142,66,7,209
    130 POKE #790,31,39,39,64,8,47,14,220,0,47,12,208,32,28,12,224
    140 POKE #7A0,248,41,8,219,35,28,32,51,234,92,0,42,3,209,233,84
    150 POKE #7B0,42,85,1,32,208,36,1,60,231,209,254,188,112,71,0,0
    160 LRUN(プログラム2の保存番号)
    

    プログラム2
    1 'pypyズラシ-2
    2 CLS:CLV:COPY#8FC,#FFC,4:LC15,0:?"HI  SCORE:";Y:LC15,1:?"MAX COMBO:";Z:LC15,4:?"SCORE:0":LC15,10:?"TIME :":C=1:GSB@A
    3 @G:GSB@D
    'DAN OCHI
    4 @H:G=G|USR(#77C,1):W=0
    'SAME CHECK
    5 @L:A=USR(#700,0):IF!AGOTO@C
    6 R=R+1:S=S+A*R:LC21,4:?S:LC15,7:?R;"COMBO! ":W=1:IFR=10PLAY"T100L32O4EGO5ECDG":WAIT30ELSEIFR=20PLAY"T100L32O5FFFFRERGRF":WAIT30ELSEBEEP30-R,10
    7 IFS<25000B=S/5000
    8 WAIT30:GOTO@L
    9 @C:IFWGOTO@HELSEGSB@D:IFHGOTO@H
    10 IFR>LL=R
    11 IFGCLT:G=0:CLK:BEEP10,20
    'KEY
    12 @K:K=TICK():LC21,10:?DEC$(300-K,3):IFK>300GOTO@TELSEK=INKEY():IFK=0GOTO@K
    13 R=0:C=1:GSB@A:IFK=28||K=29O=K-28:D=1-2*O:E=O*7+1:F=8-7*O:P=SCR(E,X+1):FORI=ETOFSTEPD:LCI,X+1:?CHR$(SCR(I+D,X+1)):NEXT:LCF,X+1:?CHR$(P):GOTO@G
    14 IFK=30&&X>0C=0:GSB@A:X=X-1:C=1:GSB@A
    15 IFK=31&&X<7C=0:GSB@A:X=X+1:C=1:GSB@A
    16 GOTO@K
    'DISP
    17 @D:H=0
    18 @E:I=USR(#77C,0):IFIPOKE#920+I,RND(5)+#F8+B:H=1:CLT:GOTO@EELSERTN
    '>< DISP
    19 @A:LC0,X+1:?CHR$(C*62):LC9,X+1:?CHR$(C*60):RTN
    20 @T:LC0,10:?"GAME OVER":?:IFS>YY=S:?"HI-SCORE!",Y
    21 IFL>ZZ=L:?"MAX-COMBO!",Z
    22 COPY#FFC,#8FC,4
    

    プログラム1(アセンブラ表記)
    '--- same check
    	push	{LR}
    	push	{r1-r7}
    	mov	r6,#8
    	lsl	r6,r6,8
    	add	r6,r1	'r6=Array(#800)
    	mov	r7,#92
    	lsl	r7,r7,4
    	add	r7,r1	'r7=VRAM(#920)
    	mov	r5,#00	'check from #920
    @loop1		'a=r3,b=r4,r5=LoopCounter,[]=r6,VRAM=r7
    	mov	r0,1
    	strb	r0,[r6,0]	'[0]=1
    	strb	r5,[r6,1]	'[1]=LoopCounter
    	mov	r3,0		'r3=0	a=0
    	ldrb	r4,[r7,r5]	'b=scr(i,j)
    	cmp	r4,#FA
    	blt	@lbl1		'if b<#FA @lbl1
    @lbl2		'VRAM範囲チェックループ
    	add	r3,1		'a=a+1
    	ldrb	r2,[r6,r3]	'r2=[a]
    	mov	r0,0
    	strb	r0,[r7,r2]	'lcu,v:?chr$(0)
    	mov	r1,r2
    	sub	r1,#20		'@chk_up(r2-#20)
    	gosub	@sub1
    	mov	r1,r2
    	add	r1,#20		'@chk_dn(r2+#20)
    	gosub	@sub1
    	sub	r1,r2,#1	'@chk_L(r2-#1)
    	gosub	@sub1
    	add	r1,r2,#1	'@chk_R(r2+#1)
    	gosub	@sub1
    	ldrb	r0,[r6,0]
    	cmp	r3,r0
    	blt	@lbl2		'if a<[0] goto @lbl2
    	ldrb	r0,[r6,0]	'result(combo count)=[0]
    	cmp	r3,#4
    	bge	@lbl3		'if a>=4 @lbl3 (combo)
    @loop2		'キャラ復元
    	ldrb	r1,[r6,r0]
    	strb	r4,[r7,r1]	'poke VRAM+[[0]],b
    	sub	r0,1		'[0]=[0]-1
    	bne	@loop2
    	strb	r0,[r6,0]	'[0]=0
    @lbl1
    	add	r5,1
    	mov	r0,#FF
    	and	r0,r5
    	cmp	r0,#0		'check VRAM=#920-#A1F
    	bne	@loop1		'if r0 != #A1* @loop1
    
    @lbl3
    	pop	{r1-r7}
    	pop	{PC}		'return
    
    @sub1		'周囲同キャラチェック
    	ldrb	r0,[r7,r1]	'r0=scr(u,v-1)
    	cmp	r0,r4
    	bne	@sub_ret
    	ldrb	r0,[r6,0]
    	add	r0,1
    	strb	r0,[r6,0]	'[0]=[0]+1
    	strb	r1,[r6,r0]	'[[0]]=r1
    @sub_ret
    	ret
    '--- padding
    	nop
    	nop
    	nop
    	nop
    '--- drop	'r0=dlop flag(0=no/1=yes):r1=ochi moto:r2=ochi saki:r4=LoopCounter,r5=VRAM
    	push	{r1-r7}
    	mov	r6,r0		'1=drop/0=null search
    	mov	r0,0		'drop flag clear
    	mov	r5,#92		'#920
    	lsl	r5,r5,4
    	add	r5,r1		'r5=VRAM=#920
    	mov	r4,#D0		'loop for #920+#D0 to #920+#0
    @d_loop1
    	ldrb	r1,[r5,r4]	'r1=peek(r5+r4)
    	'-- null search
    	cmp	r6,r1		
    	bne	@d_lbl2		'if peek(r5+r4)!=0 || r6!=0 goto @d_lbl2
    	mov	r7,#1F
    	and	r7,r4
    	cmp	r7,#8
    	bgt	@d_lbl1
    	cmp	r7,0
    	beq	@d_lbl1		'if r7=0 goto @d_lbl2
    	mov	r0,r4
    	bla	@d_lbl3
    	'--
    @d_lbl2
    	cmp	r1,#FA
    	blt	@d_lbl1		'if r1<#FA goto @d_lbl1
    	mov	r3,r4
    	add	r3,#20
    	ldrb	r2,[r5,r3]	'r2=peek(r5+r4+#20)
    	cmp	r2,0
    	bne	@d_lbl1		'if r2!=0 goto @d_lbl1
    	strb	r1,[r5,r3]	'poker5+r3,r1
    	strb	r2,[r5,r4]	'poker5+r4,r2
    	mov	r0,1		'drop flag set
    	mov	r4,#D0		'loop for #920+#D0 to #920+#0
    @d_lbl1
    	sub	r4,1		'count down
    	bne	@d_loop1
    @d_lbl3
    	pop	{r1-r7}
    	ret
    

    MixJuiceでのダウンロードURLは下記になります。
    zurasi1 http://tagiyasoft.blog.jp/zurasi1.bin
    zurasi2 http://tagiyasoft.blog.jp/zurasi12.bin

    以下のように入力してD/Lしてください。
    NEW
    ? MJ GET http://tagiyasoft.blog.jp/zurasi1.bin
    ? MJ GET http://tagiyasoft.blog.jp/zurasi2.bin
    

    ブラウザでD/LしてIchigoJamに転送する場合は、通信ソフトでバイナリ送信をしてください。
    (例:TeraTermの場合は、メニューの[ファイル]-[ファイル送信]で当該ファイルを送信します)

  • 参考ゲーム
    ぷよぷよズラシ
  • ぷよぷよ

  • タイトル
    マインスイーパーlatte (電子工作マガジン2017年WINTER号掲載)

  • 開発環境
    IchigoJamBASIC1.2.1

  • 内容
    マインスイーパーです。

  • マインスイーパーlatte
  • 遊び方
    フィールドの中から爆弾を探すゲームです。 爆弾に隣接しているマスは隣接している爆弾の数が表示されるので、それをヒントに全てのマスを開けてください。

  • 操作方法
    横方向(X軸)と縦方向(Y軸)を入力してマスを開きます。 それぞれ1~8の数字を入力し、Enterします。 全て開けられれば成功、爆弾を開けてしまうと失敗です。 最後にかかった時間が表示されます。

  • プログラムのしくみ

    各関数の説明
    bm.clrフィールド用メモリクリア
    bm.set爆弾配置
    bm.disp画面表示
    引数 0:爆弾を伏せて表示 1:爆弾を表示
    返値 開いていないマスの数
    kyinキー入力
    引数 xy:"X"または"Y"の文字 pos:文字表示Y座標
    返値 入力された数値
    searchマスを開く
    引数 入力したX,Y座標
    返値 0:爆弾以外を開いた 0以外:爆弾を開いた
    main初期設定、画面表示
    残りマス=爆弾数、もしくは爆弾を開いてしまうまでループ
    結果表示

    変数表(グローバル変数のみ)
    B爆弾の数
    Tゲーム開始時のタイム
    mメモリ(配列)先頭アドレス
    x,y入力した座標
    n残りマス数
    s入力座標が爆弾かどうか

  • プログラムの具体的な入力方法
    可読性を良くするためスペースでインデントしていますが、行頭のスペースは入力しなくても動作します。

  • プログラムの改造
    変数"B"は爆弾の数です。増減して難易度を変更することができます。

  • (プログラム1)
    var B=6;
    function bm(f){
     this.clr=function(){
      var i=0;
      while(i<100 ){
       if((i>10)*(i<89 )*((i%10)%9!=0)){ mem(m+i,0xF4); }
       else{ mem(m+i,0); }
       i=i+1;
      }
     };
     this.set=function(){
      var i=B, r;
      while(i){
       r=(rnd(8)+1)*10+rnd(8)+1;
       if(mem(m+r)==0xF4){
        mem(m+r,0xF6);
        i=i-1;
       }
      }
     };
     this.disp=function(f){
      var i=1, c, n=0;
      cls();
      log("\\X12345678\nY\n");
      while(i<9){
       var j=0;
       log(i);
       while(j<9){
        c=mem(m+i*10+j);
        if((c>0)*(c<9 )){ c=c+0x30; }
        else{
         if((c>9)*(f==0)){ c=0xF4; }
        }
        log(chr(c));
        if(c==0xF4){ n=n+1; }
        j=j+1;
       }
       log("\n");
       i=i+1;
      }
      return(n);
     };
    }
    
    function kyin(xy,pos){
     lc(0,pos);
     log(xy,"= ");
     var k=input();
     if((k<1 )*(k>8)){ k=0; }
     return(k);
    }
    
    function search(u,v){
     var sp=m+100;	//stack pointer
     var src=v*10+u;	//search position
     var z=mem(m+src);	//search position char
     if(((u%10)%9==0)*((v%10)%9==0)){ return(0); }	//out side
     if(z<=9){ return(0); }	//number
     if(z==0xF6){ return(z); }	//bomb
    
     var indx=0;
     mem(sp,1);	//[0]=1
     mem(sp+1,src);	//[[0]]=[1]=src
    
     var x, y, z, j, count=0;
     while(indx9){
          mem(sp, mem(sp)+1);
          mem(sp+mem(sp),j);
         }
         if(z==0xF4){ mem(m+j,0); }
         x=x+1;
        }	//while(x
        y=y+1;
       } 	//while(y
      }
      mem(m+src,count);
     }	//while(co
     return(0);
    }
    
    //main
    var T=tick();
    var m=mem(" ");
    var bomb=new bm();
    var x=0, y=0, n=1, s=0;
    bomb.clr();
    bomb.set();
    n=bomb.disp(0);
    while((n!=B)*(s==0)){
     x=kyin("X",12);
     y=kyin("Y",13); 
     if(x*y){
      s=search(x,y);
     }
     n=bomb.disp(0);
    }
    bomb.disp(1);
    if(s){ log("\n\nGAME OVER\n"); }
    if(n==B){ log("\n\nCONGRATULATION!\n\n"); }
    log("TIME: ",(tick()-T)/1000,"sec\n");
    

    MixJuiceでのダウンロードURLは下記になります。
    mine_latte http://tagiyasoft.blog.jp/mine_latte.bin

    以下のように入力してD/Lしてください。
    NEW
    ? MJ GET http://tagiyasoft.blog.jp/mine_latte.bin
    

    ブラウザでD/LしてIchigoJamに転送する場合は、通信ソフトでバイナリ送信をしてください。
    (例:TeraTermの場合は、メニューの[ファイル]-[ファイル送信]で当該ファイルを送信します)

  • 参考ゲーム
    マインスイーパー

↑このページのトップヘ