MicroPythonプログラムをX-BASICにすれば、Cに変換コンパイルし、高速に実行できます。X68000 Z 実機で、MicroPython と X-BASICのコード変換、X68K関数の記述方法についてまとめました。
MicroPython開発ディスクの作り方、Cコンパイラ開発ディスクの作り方
- X68000 Z 資料
- X68000 Z ツール入手先
- X-BASICの起動
- X-BASIC サンプルプログラム(マウス左ボタンで線をひく)
- MicroPython
- MicroPython から X-BASIC への変換
- 行番号を追加するPythonプログラム
- X-BASIC 起動・終了
- X-BASIC と MicroPython の比較
- X68K関数(X-BASIC / MicroPython / XC)対応表
- 描画関数
- Python特有の処理
- 解説動画の作り方
X68000 Z 資料
参考にした記事はこちらです。
- X68000 Z 公式サイト(サポート>マニュアル)
- はじめての X68000 Z (note)
- X68000 の開発環境(Qiita)
- X68000 zで音楽を流す(MachiaWorks)
- OhX、OhMZなど
- X68K:IOCS
- iocsコール
- X-BASICリファレンス
- X-BASIC マニュアル
X68000 Z ツール入手先
- DiskExplorer(XDFファイル作成)
- ブランクXDFファイル (出典Twitter)
- X68000 LIBRARY 各種リソース
- MicroPython ダウンロード(yunkya2)
- 使えるSDカード(SDHC 最大32GB FAT32)
- zombie.x(削除ファイル抽出)
- X-BASIC to C コンバータ bas2c (yunkya2)
X-BASICの起動
X68000Z システムディスク(ビジュアルシェル)から
- BASICをダブルクリック > BASICフォルダが開きます
- BASIC.Xをダブルクリック
コマンドプロンプトから
- basic
X-BASIC サンプルプログラム(マウス左ボタンで線をひく)
10 int x,y,xx,yy,dx,dy,right,left
20 screen 1,3,1,1 30 x=0 : y=0
40 print("Draw line with Mouse. Exit=Move to bottom") 50 while y<500 60 mspos(xx,yy) 70 msstat(dx,dy,left,right) 80 if left<>0 then { 90 line(x,y,xx,yy,xx)
100 } 110 x = xx : y = yy
120 endwhile
上のプログラムを入力し、
- run
するとマウスを動かして画面に線をひくことができます。エラーが出た場合
- list
でプログラムを表示し、カーソルを移動させて修正できます。
上のプログラムの説明
int x,y | 変数の定義(文字列は str、自然数は float) |
screen 1,3,1,1 | 768 x 512 x 16色(31kHz) mode |
x=0 : y=0 | :で区切ると複数行を1行で書ける(マルチステートメント) |
while y<500 endwhile |
y が500より小さい間、繰り返す |
mspos(xx,yy) | マウス座標取得 |
msstat(dx,dy,left,right) | マウスボタン、マウス移動値取得 |
line(x,y,xx,yy,c) | 色cで線をひく |
- save "xxx.bas"
でプログラムを保存できます(xxxは好きな名前)
- load "xxx.bas"
でプログラムを読み出せます。BASICの終了は
- system
です。
もっと複雑なサンプルプログラムはこちらを御覧ください。
MicroPython
- X-BASICよりも複雑なプログラムが簡単につくれます。
- ファイル処理、256バイトより長い文字列処理ができます。
- ただ実行速度はX-BASICより遅いです。
- MicroPythonの使い方はこちらをご覧ください
MicroPython から X-BASIC への変換
MicroPythonのプログラムをX-BASICに変換し、Cコンパイルすれば、高速に実行できます。試作プログラムは MicroPythonで開発し、速度が遅ければ、X-BASICに変換するのがよいでしょう。コード変換は次のように行うとよいです。
- MicroPythonプログラムの行頭に行番号を追加する。修正は ED エディタ
- Basicを起動し、load "ファイル"で読み込むとエラーが出て読み込みが止まる。
- list でエラー行の手前まで表示されるので、system で終了し、ED エディタでエラー行を修正。
- 下の MicroPython と X-BASIC の対応表を参考に修正していく
行番号を追加するPythonプログラム
MicroPython のプログラムを読み込んで、行番号を追加し、単純な変換まで行うPythonプログラムです。src= に変換元のPythonファイル名、dst=に変換後のBASICファイル名を書いて実行(micropyt addlno.py)すれば、Pythonの各行に、行番号を追加します。
簡単なキーワードの変換も行います。単純な変換なので間違えることもあります。
この処理を行ったあと、手作業で変換すると楽です。
import os src = 'xxxx.py' #変換元のPythonファイル名に変更してください dst = 'xxxx.bas' #変換後のBasicファイル名に変更してください no = 10 fr=open(src,'r') fw=open(dst,'w') for ln in fr: if len(ln)<=1: ln = '/*\n' x = ln.find('#') if x>=0: ln =ln[0:x]+'/*'+ln[x+1:-1]+'\n' while ln.find('if')>=0: x = ln.find('==') if x>=0: ln =ln[0:x]+'='+ln[x+2:] continue x = ln.find('!=') if x>=0: ln =ln[0:x]+'<>'+ln[x+2:] continue break while ln.find('<<')>=0: x = ln.find('|') if x>=0: ln =ln[0:x]+' or '+ln[x+1:-1]+'\n' continue x = ln.find('&') if x>=0: ln =ln[0:x]+' and '+ln[x+1:-1]+'\n' continue x = ln.find('<<') if x>=0: ln =ln[0:x]+' shl '+ln[x+2:-1]+'\n' while ln.find('>>')>=0: x = ln.find('|') if x>=0: ln =ln[0:x]+' or '+ln[x+1:-1]+'\n' continue x = ln.find('&') if x>=0: ln =ln[0:x]+' and '+ln[x+1:-1]+'\n' continue x = ln.find('>>') if x>=0: ln =ln[0:x]+' shr '+ln[x+2:-1]+'\n' while ln.find('0x')>=0: x = ln.find('0x') if x>=0: ln =ln[0:x]+'&h'+ln[x+2:-1]+'\n' while ln.find('%')>=0: x = ln.find('%') if x>=0: ln =ln[0:x]+' mod '+ln[x+1:-1]+'\n' x = ln.find('return') if x>=0: ln =ln[0:x+6]+'('+ln[x+6:-1]+')\n' x = ln.find('def') if x>=0: ln =ln[0:x]+'func'+ln[x+3:-2]+'\n' ss=str(no)+' '+ln print(ss) fw.write(ss) no+=10 fr.close() fw.close()
X-BASIC 起動・終了
basic /*BASIC起動*/
list /*プログラム表示、修正*/ run /*実行*/ save "ファイル名.bas" /*保存*/ load "ファイル名.bas" /*読み出し*/ exit() /*BASIC終了*/
X-BASIC と MicroPython の比較
参考にした資料
起動、終了
basic | micropyt | 起動 |
system (F10キー) | Ctrl+D | 終了 |
対応表
/* コメント | # コメント |
return(1) | return 1 |
print a,b,c | print(a,b,c) |
if a=1 and b<>0 then{ }else{ } | if a==1 and b!=0: else: |
for i=0 to 9 next | for i in range(10): |
10 mod 8 | 10 % 8 |
(x shl 4) or ( (y and &hf0) shr 4) |
(x << 4) | ( (y & 0xf0) >> 4) |
s = chr$(34)+"abc"+chr$(34) | s = '"'+'abc"' |
func str xxx(x;int) endfunc 型宣言が必要。省略はint |
def xxx(x): 型宣言がない。代入によって型が変化する |
str 文字は 256 バイトが最大 | 文字数は無制限 |
フォルダのファイルを取得できない |
import os os.listdir('フォルダ名') #フォルダのファイル取得 |
error off error on で囲まないと fopen でエラー終了 | open |
変数、配列
int a = 1 /*型必要、定数のみ書ける*/
float b: b = 1/2. /*:はマルチ*/ str c:c = “ABC”+chr$(34) /*Max256文字*/ print a,b,c /*()かっこ不要*/ |
a = 1 #型宣言不要 b = 1/2 c = 'ABC”' print(a,b,c) #( )が必要 |
|
a=1:b=2 /*:マルチステートメント*/ |
a,b = 1,2 #複数代入可 | |
int a(3)={5,1,3,4) /*宣言より要素が1多い 最初はa(0)=5,a(3)=4*/ print a(0) |
a=[5,1,3,4] print(a[0]) |
|
int a(3)={1,1,1,1) | a = [1]*4 | |
要素数を変更できない | a = list() #空 | |
int a(4)={0,1,2,3,4) | a = list(range(5)) | |
str a(3)={"a","textbook","of","x-basic"} | a = "a textbook of Python".split() | |
できない | a[-1] #配列の一番最後、負は後ろから数える | |
できない | a[0:2] #最初から2つ | |
できない | a[1:3] #2番目から2つ。Pythonは開始:終了で指定 | |
要素数を変更できない | a.append(2) #aの最後に2を追加 |
型変換
float x:x=val(a) int x:x=atoi(a) |
x = float(a) x = int(a) |
|
str s:s = str$(1/3.) str s:s = hex$(a) right$("000"+hex$(a),4)
|
s = str(1/3) #数値を文字列にする s = hex(a) #16進数 s ='{:04x}'.format(a) #16進数4桁 s ='{:02x}{:02x}'.format(a,a) #16進数2桁を2つ並べる |
for ループ
for i=0 to 9 next |
for i in range(10): | |
dim int a(3)={5,1,3,4} for i=0 to 3 d=a(i) next |
a = [5, 1, 3, 4] for d in a:
|
|
if else
if (a = 1) and (b <> 0) then { print "a1 bx" }else if a=1 then { print "NO" } |
if (a == 1) and (b != 0): print("a1 bx") elif a==1: print("NO")
|
数値計算
float a:a=pi(1.) /*円周率x1*/ float a:a=sqr(2.) |
import math a = math.pi #円周率 a = math.sqrt(2) #ルート |
|
(rr shl 8) or (gg shr 2) | (rr << 8) | (gg>>2) | |
&hFFFF | 0xFFFF #16進数 | |
a = 10 mod 8 /*余り*/ | a = 10 % 8 |
文字の結合、検索
str s:s="abc"+"def" str s:s="abc"+str$(1.2)
int a:a=strlen(s) |
s = "abc" + "def" s = "abc"+str(1.2) #数値は文字にしてから結合 a = len(a) #文字の長さ、半角も全角も1文字 |
|
str s="abcabc" | s = "abc"*2 | |
str a="abcdef" instr(1,a,"cd") /*結果は3 最初の数字は検索開始(最初は1)*/ instr(1,a,"x")/*結果は0*/ |
a = "abcdef" a.find("cd") #結果は 2 a.find("x") #結果は-1 |
|
関数
float a while 1 input "> ",a print a, myabs(a) endwhile func float /*func は後ろにおく*/ myabs(x;float): if x<0 then return(-x) return(x) /*値を返さなくても()が必要*/ endfunc |
def myabs(x): if x<0: return -x return x #( )は不要 while True: a = float(input("> ")) print(a, myabs(a)) |
|
不要。関数外の変数も読み書きできる 関数の引数に256文字の文字をいれると落ちることがある。 サイズが大きい変数は関数外定義がよい |
a=1 def f(): global a #関数外の変数 print a |
|
関数のデフォルト引数はない
|
def f(a,b=2,c=3):#デフォルト引数 return a + b + c f(1,1,1) #答えは3 f(1) #答えは6 f(1,c=2) #答えは5 |
|
関数を変数にいれることはできない |
def f1(): print("f1") def f2(): print("f2") def F(y): #関数を変数にいれられる y() F(f2) F(f1) |
|
ファイル, OS処理
int fp str s[256] fp=fopen("test.txt","c") /*cは新規作成する*/ fwrites("111\n 222\n 333\n",fp) /*¥nは改行にならない*/ fclose(fp) fp=fopen("test.txt","r") freads(s,fp) fclose(fp) print s
|
import os print(os.getcwd()) f= open('test.txt','w') f.write('111\n 222\n 333\n') f.close() f = open('test.txt','r') s = f.read() f.close() print(s) |
|
int fp str s[256]/*256文字以内しか使えない*/ error off /*ファイルがなくても中断しない fp=fopen("test.txt","r") while freads(s,fp)>0 print s endwhile fclose(fp) error on
|
import os f = open('autoexec.bat','r') for line in f: printf(line) f.close() |
|
error off /*ファイルなくても中断しない frename("変更前ファイル名","変更後ファイル名") fdelete("ファイル名") error on |
import os os.rename('変更前ファイル名','変更後ファイル名') os.remove('ファイル名') os.listdir('フォルダ名') |
|
exit(0) |
import sys sys.exit() #プログラムの終了 |
X68K関数(X-BASIC / MicroPython / XC)対応表
XC | ||||
不要 | from x68k import * # | #include <basic0.h> | 先頭にいれれば、x68k. を省略できる。 | |
cls | x68k.iocs(x68k.i.B_CLR_ST, 2) | cls() | テキスト画面消去 | |
wipe() | basicと同じ | グラフィック画面消去 | ||
window(x1,y1,x2,y2) | basicと同じ | クリッピング | ||
x68k.crtmod(16, 1) | 768 x 512 x 16色(31kHz) | |||
x68k.crtmod(14, 1) | 255 x 255 x 65536色 | |||
screen 1,2,1,1 | screen(1,2,1,1) | 512 x 512 x 256色 x 2面 | ||
screen 1,3,1,1 | x68k.crtmod(12, 1) | screen(1,3,1,1) | 512 x 512 x 65536色 x 1面 | |
ky$=inkey$ | key= x68k.iocs(x68k.i.B_KEYINP) |
unsigned char ky[258]; b_inkeyS(ky); |
キーを入力待ちして取得 | |
ky$=inkey$(0) | key= x68k.iocs(x68k.i.B_KEYSNS) |
unsigned char ky[258]; b_inkey0(ky); |
キー取得(入力待ちしない) | |
key= x68k.iocs(x68k.i.B_SFTSNS) | シフトキー取得(入力待ちしない) | |||
key= x68k.iocs(x68k.i.B_BITSNS, group) | キー取得(入力待ちしない) | |||
x68k.dos(x68k.d.KFLUSH, b'¥x00¥x06¥x00¥xfe') | キーバッファクリア | |||
beep |
x68k.dos(x68k.d.INPOUT, b'\x00\x07') |
beep(); | ビープ音を鳴らす | |
vpage(1) | x68k.iocs(x68k.i.G_CLR_ON) | basicと同じ | グラフィック表示する(3:2面重ねる) | |
apage(a) | basicと同じ | 描画先(a=0,1..) | ||
locate x,y | x68k.iocs(x68k.i.B_LOCATE, x, y) | locate(x,y) | カーソルを(x,y)に移動 | |
xxyy = x68k.iocs(x68k.i.B_LOCATE, -1) | カーソル位置を取得 | |||
x68k.iocs(x68k.i.B_COLOR, d1=pal) | 文字の色 pal: 0=black, 1=cyan, 2=yellow, 3=white | |||
locate 0,0,1 | x68k.iocs(x68k.i.OS_CURON) | b_csw(1); | カーソル表示 | |
locate 0,0,0 | x68k.iocs(x68k.i.OS_CUROF) | b_csw(0); | カーソルを消す | |
mouse(0) | x68k.iocs(x68k.i.MS_INIT) | basicと同じ | マウス初期化 | |
mouse(1) | x68k.iocs(x68k.i.MS_CURON) | basicと同じ | マウスカーソルON | |
mouse(2) | x68k.iocs(x68k.i.MS_CUROF) | basicと同じ | マウスカーソルOFF | |
mcr=mouse(3) | mcr=x68k.iocs(x68k.i.MS_STAT) | basicと同じ | マウスカーソルの状態 | |
msarea(x1,y1,x2,y2) | x68k.iocs(x68k.i.MS_LIMIT,
(x1 << 16) | y1, (x2 << 16) | y2) |
basicと同じ | マウスの範囲設定 | |
setmspos(x,y) | x68k.iocs(x68k.i.MS_CURST,
(x << 16) | y) |
basicと同じ
|
マウス位置指定 | |
mspos(x,y) | pos = x68k.iocs(x68k.i.MS_CURGT) | mspos(&x,&y); | マウス位置取得
(x=(pos >> 16) & 0xffff, y=pos & 0xffff) |
|
msstat(dx, dy, lbtn, rbtn) | stat = x68k.iocs(x68k.i.MS_GETDT) | msstat(&dx, &dy, &lbtn, &rbtn); | マウス移動、ボタン取得 (dx, dy, lbtn, rbtn) | |
x68k.iocs(x68k.i.SKEY_MOD,-1) | ソフトキーボード ON | |||
x68k.iocs(x68k.i.SKEY_MOD,0) | ソフトキーボード OFF | |||
x68k.iocs(x68k.i.TPALET,pal,-2) | テキストパレット初期化 | |||
x68k.iocs(x68k.i.TPALET,pal,color) | テキストパレット設定(colorは16bit:g5r5b5+0, pal=0-3, 7,8(マウスポインタ)) | |||
x68k.iocs(x68k.i.TPALET,pal,-1) | テキストパレット取得 | |||
x68k.iocs(x68k.i.GPALET,pal,-2) | グラフィックパレット初期化 | |||
x68k.iocs(x68k.i.GPALET,pal,color) | グラフィックパレット設定(colorは16bit:g5r5b5+0, pal=0-15) | |||
x68k.iocs(x68k.i.GPALET,pal,-1) | グラフィックパレット取得 | |||
hsv(h,s,v) | x68k.iocs(x68k.i.HSVTORGB, (h<<16)|(s<<8)|v) | basicと同じ | HSVからRGB変換(h:0-191 0=R 64=G 128=B 32=Y 96=C 160=M s,v:0-31) | |
なし | FILEBUF inf; FILES(&inf,"*.*",atr); |
atr=0x10(フォルダ)、0x20(ファイル)をカレントから1つ取得 | ||
なし | FILEBUF inf; NFILES(&inf); |
続きのファイルを取得、取得できたらreturn 0 |
描画関数
XC | |||
不要 | g=GVRam(0) | グラフィック画面 | |
不要 | tx=TVRam(0) | テキスト画面 | |
line(x1,y1,x2,y2,pal) line(x1,y1,x2,y2,pal,dot) |
g.line(x1,y1,x2,y2,pal) g.line(x1,y1,x2,y2,pal,dot) |
line(x1,y1,x2,y2, pal,'NASI') line(x1,y1,x2,y2, pal,dot) |
x1,y1-x2,y2に線をひく。palは色 点線(dot=-1は実線,0は透明) |
box(x1,y1,x2,y2,pal) box(x1,y1,x2,y2,pal,dot) |
g.box(x1,y1,x2,y2,pal) g.box(x1,y1,x2,y2,pal,dot) |
box(x1,y1,x2,y2, pal,'NASI') box(x1,y1,x2,y2, pal,dot) |
x1,y1-x2,y2の四角形を描く。palは色 点線の四角(dot=-1は実線,0は透明) |
fill(x1,y1,x2,y2,pal) | g.fill(x1,y1,x2,y2,pal) | basicと同じ | x1,y1-x2,y2の四角形を塗りつぶす。palは色 |
circle(x,y,r,pal) circle(x,y,r,from,to) |
g.circle(x,y,r,pal) g.circle(x,y,r,from,to) |
circle(x,y,r,pal, 'NASI', 'NASI', 'NASI') | 中心x,y,半径rの円を描く。palは色 円弧(from,toは角度0-360) |
get(x1,y1,x2,y2,mm) | get(x1,y1,x2,y2, mm, sizeof(mm)) | 四角領域の画像を配列に記憶 | |
put(x1,y1,x2,y2,mm) | put(x1,y1,x2,y2, mm, sizeof(mm)) | 配列に記憶した画像を描画 | |
symbol(x,y,str, h,v,f,col,a) | basicと同じ | 文字描画 (hv:水平垂直倍率 f:フォント a:角度) |
FM音源
- OPMDRV3.X が必要です。比較的新しいゲームの sysフォルダにはいっています。
m_init() | ||
m_alloc(t,sz) | x68k.iocs(x68k.i.OPMDRV,0x01,(t<<16)|sz) | tトラック用に sz バイト確保 |
m_asign(ch,t) | x68k.iocs(x68k.i.OPMDRV,0x02,(t<<16)|ch) | tトラックをch チャンネル |
m_free(t) | x68k.iocs(x68k.i.OPMDRV,0x07,t) | tトラックの残りバイト数 |
m_trk(t,mml) | トラックに音を設定 | |
m_tempo(te) | x68k.iocs(x68k.i.OPMDRV,0x05,te) | テンポ te=32-200 |
m_play()/*全再生*/ m_play(c1,c2..c8) |
x68k.iocs(x68k.i.OPMDRV,0x08,pack('L',c),0,0) | cチャンネル再生1-25 |
Python特有の処理
以下のMicroPythonの処理は、X-BASICに変更するのが難しいので、使わないようにするのがよいです。
リストの代入と複製
a = [ 1, 2, 3] b = a #bはaと同じ a[1]=0 #a を修正 b #b も修正されてる b = a.copy() #浅いコピー(完全なコピーではない) a[1]=10 #a を修正 b #b は aをコピーしたときの値 id(a) id(b) #id(a) と id(b)が同じとき、中味は同じ
辞書
- リストの中身を文字列で指定する仕組み
age = {"yamada":18, "tanaka":19} age age["yamada"] age["sato"]=20 #"sato"が追加される age "okada" in age #"okada"がはいっているか?
try except (エラー処理)
- 数字以外が入力されたときにエラー終了しないようにする
while True: x = input("*** ") try: x = float(x) except: print("Not number") continue print(x) break
- while True は無限ループです。Tは大文字
- エラーが発生すると、except から実行されます。except: は必ず必要で、何もしないときは pass と書きます
- continue は、while ループの先頭にもどります
- break で、whileループを抜けます
内容:
- X68000 Z 資料
- X68000 Z ツール入手先
- X-BASICの起動
- X-BASIC サンプルプログラム(マウス左ボタンで線をひく)
- MicroPython
- MicroPython から X-BASIC への変換
- 行番号を追加するPythonプログラム
- X-BASIC 起動・終了
- X-BASIC と MicroPython の比較
- X68K関数(X-BASIC / MicroPython / XC)対応表
- 描画関数
- Python特有の処理
- 解説動画の作り方
解説動画の作り方
この記事のひとコマ解説GIFは、フリーソフト9VAeきゅうべえの「ひとコマ機能」で作成しています。
9VAeきゅうべえのダウンロード
- Android / Chromebook:9VAeきゅうべえAndroid版、9VAeDangla
- iPad / iPhone:9VAeDanga (Apple)、9VAePro (Apple)
- Win / Mac / Linux:無料ソフトでアニメを作ってみよう - Qiita
- Amazon Fire : 9VAeきゅうべえFire版 (Amazon)
- 9VAeのボタン説明、メニュー/キー
- 9VAeきゅうべえで、キャプチャー画面に、矢印や説明を加え、ページに「ひとコマ」設定するだけで作れます。
- FFmpeg を使って Youtube 動画にすることもできます。
画面キャプチャ方法
|
||
|
||
|
ライブラリ> Screenshots |
|
|
|
アルバム> スクリーンショット |
|
ファイル |
|
|
スクリーンショット |
|
|
ダウンロード |
|
|
アニメGIF、動画出力
- 「ファイルメニュー>アニメGIF出力」または「動画出力」で、好きなサイズのアニメGIF または MP4動画 が作成できます。
Win / RaspberryPi / Linux版 でMP4動画を作るには FFmpeg が必要。Youtube解説 - スマホの場合、端末内の「9VAe」フォルダの中に出力されます。フォトアプリで、「端末内の写真>9VAe」で見ることができます。
- アニメGIFは、背景を透明にできます。音がいれられません。
- MP4動画には音が入れられます。Youtubeに投稿できます。Youtubeに投稿する場合、1秒30コマ、高さ720 または 1080 で出力するとよいでしょう。
9VAeをつかえば素材動画が作れる
- 9VAeきゅうべえを使えば、オリジナルの素材動画が簡単に作れます。
- Openclipart や FreeSVG などフリーのSVGイラストをつかって動くキャラクタが作れます。
- 動画編集ソフトで動画に合成できます。
OS |
9VAeで作成する素材動画 |
|
---|---|---|
連番PNG または MP4 |
||
PowerDirector |
GIF または MP4 |
作り方
- もっと長いアニメを作ることもできます。以下をご覧ください。
9VAeきゅうべえに関する質問
- 9VAeに関する質問(Yahoo知恵袋)
- よくある質問(Qiita)
- 本記事の文章、図、アニメは複製自由です。教材、解説記事にご利用ください。