HSP | 数値以外のデータからビット単位で切り抜いたり書き込んだり色々

HSP | 数値以外のデータからビット単位で切り抜いたり書き込んだり色々

追加:低機能化することにより高速化を実現した新バージョンが登場!!→【HSP】ビット単位の 読み出し 書き込み モジュール【修正版】
以前作っていたモジュールはぐちゃぐちゃになりましたので、ちゃんと考えて作成してみたところ、全然違う用途の命令や関数ができました。しかし、これらを組み合わせれば、前回やろうとしていたことができます。

// ビット単位でデータ操作
// by kerupani129 (http://blogs.yahoo.co.jp/kerupani/)
// 注意
// インデックス1・2というのは、下のように考える
// 例:インデックス1が 2 、インデックス2が 3 の所から4ビット
// ┌─ 1バイト目─┐┌─ 2バイト目─┐  3ビット ┌──┐
//  □□□□□□□□  □□□□□□□□  □■■■■□□□
#module "kerupanium_bit"
// 計算楽にするため用
#defcfunc advance int _p1,int _p2
// 繰り上げ(?)
// val=advance(p1,p2)
// p1=0~ : 元の数
// p2=0~ : これが0で無いときにp1に1足す
advance_a=_p1
if _p2!0 : advance_a+
return advance_a
// 基本の命令
#defcfunc bit_peek val _p1,int _p2,int _p3
// バッファから1bit読み出し
// val=bit_peek(p1,p2,p3)
// p1=変数 : 内容を読み出す元の変数名
// p2=0~ : バッファのインデックス1(1byte単位)
// p3=0~7 :           〃          2(1bit単位)
return (peek(_p1,_p2)>>_p3)&1
#deffunc bit_poke val _p1,int _p2,int _p3,int _p4
// バッファに1bit書き込み
// bit_poke p1,p2,p3,p4
// p1=変数 : バッファを割り当てた変数名
// p2=0~ : バッファのインデックス1(1byte単位)
// p3=0~7 :           〃          2(1bit単位)
// p4=0~1 : バッファに書き込む値(1bit単位)
if bit_peek(_p1,_p2,_p3)!_p4 : poke _p1,_p2,peek(_p1,_p2)^(1<<_p3)
return
#deffunc bit_expand var _p1,int _p2,int _p3
// ビットブロック(?)の再確保
// bit_power p1,p2,p3
// p1=変数 : 対象となる変数
// p2=0~ : 再確保サイズ1(1byte単位)
// p3=0~7 :      〃     2(1bit単位)
//
// statに、何byte確保したかの数値が返る
expand_len=advance(_p2,_p3)
memexpand _p1,expand_len
return expand_len
#deffunc bit_copy var _p1,var _p2,int _p3,int _p4,int _p5,int _p6,int _p7,int _p8
// ビットブロック(?)のコピー
// bit_copy p1,p2,p3,p4,p5,p6,p7,p8
// p1=変数 : コピー先の変数
// p2=変数 : コピー元の変数
// p3=0~ : コピーするサイズ1(1byte単位)
// p4=0~7 :        〃       2(1bit単位)
// p5=0~ : コピー先の変数メモリオフセット1(1byte単位)
// p6=0~7 :               〃              2(1bit単位)
// p7=0~ : コピー元の変数メモリオフセット1(1byte単位)
// p8=0~7 :               〃              2(1bit単位)
; この命令はとりあえずアバウトに作りました。
; いつか修正します。すいません。
repeat _p3*8+_p4
bit_poke _p1,_p5+(_p6+cnt)/8,(_p6+cnt)\8,bit_peek(_p2,_p7+(_p8+cnt)/8,(_p8+cnt)\8)
loop
return
#deffunc bit_set var _p1,int _p2,int _p3,int _p4,int _p5,int _p6
// ビットブロック(?)のクリア
// bit_set p1,p2,p3,p4,p5,p6
// p1=変数 : 書き込み先の変数
// p2=0~1 : クリアする値(1bit)
// p3=0~ : クリアするサイズ1(1byte単位)
// p4=0~7 :        〃       2(1bit単位)
// p5=0~ : 書き込み先の変数メモリオフセット1(1byte単位)
// p6=0~7 :                〃               2(1bit単位)
; この命令はとりあえずアバウトに作りました。
; いつか修正します。すいません。
repeat _p3*8+_p4
bit_poke _p1,_p5+(_p6+cnt)/8,(_p6+cnt)\8,_p2
loop
return
#global

※前回作っていたものとは全然違うソースなのでまったく互換性はありません。

使用できる命令一覧 (各命令の説明は、モジュールのソースにあるコメントをご覧ください)
bit_peek関数 : peekのビット単位版
bit_poke命令 : pokeのビット単位版。ただし、1ビットのデータしか書き込めない
bit_expand命令 : memexpandのビット単位版。指定したビット数分がぎりぎり入るバイト数に
bit_copy命令 : memcpyのビット単位版。現在は仮の命令になってます ※1 ※2
bit_set命令 : memsetのビット単位版。現在は仮の命令になってます ※1 ※2
※1…いちおう動作はするものの、適当に作ってあるために処理に時間がかかると思われる命令です。今後に修正する予定です。
※2…実際に使用するときには直前でbit_expandを使うようにしてください。(memexpandを使う要領で)
追加予定命令
bit_power命令 : 2のべき乗。前のから書き換え中。
bit_and : and演算
bit_or : or演算
bit_xor : xor演算
bit_shift : シフト
bit_write : pokeで文字列を指定したときのビット単位版みたいなやつ
前回作ったモジュールで追加予定だったbit_mid命令は、bit_copy命令を使うことで代用できます。(文法が変わりますのでご注意ください。っていったってもともと完成してなかった命令だからいいか…。)
追加予定命令は、すべて5バイト以上のデータに対応させます。
つまり、普通なら、HSPだと32ビット整数をビット演算するしかできないけれど、その操作が可能になるということです。これらの命令ができれば、足し算引き算や掛け算割り算もできるようになるわけで、HSPで32ビット以上の整数の四則演算が可能になります。(本当にそっちを実用にするなら、32ビット以上の整数のデータを、文字列の数字に変えて表示できるような命令も必要ですね。でもまあ後でそれは作ることにします。)
いちおうサンプルっぽい物体

a=10
repeat 4
mes bit_peek(a,0,cnt)
loop
mes ""
bit_poke a,0,0,1
bit_poke a,0,2,1
repeat 4
mes bit_peek(a,0,cnt)
loop
bit_set a,0,0,2,0,1
mes ""
repeat 4
mes bit_peek(a,0,cnt)
loop
mes ""
;bit_power b,9
;mes b
;mes ""
bit_copy c,a,0,4,0,0,0,0
repeat 4
mes bit_peek(c,0,cnt)
loop

ほんのちょっとは動作確認しましたが、数によってバグが起きるのであれば、具体的にどのような数を指定して、どのように使用したか、を加えて「こんなバグが起きた」というのをコメントで教えてくれると助かります。
4日間でかけてる間にcopyとsetと追加予定命令の処理の仕方考えようと思います。
では。
↓あなたのクリックでHSPでの演算が変わる!! (か?!)