# wat80ppc bg_rotnscl.s; wat2wasm bg_rotnscl.wat (module (import "console" "log" (func $log (param i32))) (import "js" "mem" (memory $mem 1)) # n回の呼び出し毎にデバッグ値を出力する (global $dbgcnt (mut i32) i32.push 0 ) (func $dbgval (param $val i32) global.push dbgcnt i32.push 0x3F i32.and if else # dbgcnt & 0x3F == 0 push val call log end global.push dbgcnt i32.push 1 i32.add global.pop dbgcnt ) # # 回転拡大縮小機能 # 回転位置、回転角、拡大縮小率による # (func $bg_rotnscl_ovt (export "bg_rotnscl_ovt") (param $w i32) # 生成サイズ (param $h i32) (param $c i32) # 回転中心位置 (param $r i32) (param $oc i32) # 回転オフセット位置 (param $or i32) (param $v i32) # 回転角(256:360deg.) (param $t i32) # 拡大縮小率(t/256) (local $it i32) (local $hx16 i32) # hxy: 水平方向サンプリングxy間隔 (local $hy16 i32) (local $vx16 i32) # vxy: 垂直方向サンプリングxy間隔 (local $vy16 i32) (local $_vx16 i32) # サンプリング開始位置(右下) (local $_vy16 i32) # テーブルから cos, sin を得る 0x800000 - 0x8007FF: table (cos:4 sin:4) x 256 push v i32.push 3 i32.shl # [ (v << 3) pop_push it push it # [ (v << 3) (v << 3) # hxy: 水平方向サンプリングxy間隔 i32.push 0x800000 # 0x800000 i32.add # [ (v << 3) ((v << 3) + 0x800000) i32.push 0x8007F8 i32.and # [ (v << 3) *cos(v) pop_push it push it i32.push 4 i32.add # [ (v << 3) *cos(v) *sin(v) i32.load push t i32.mul i32.push 8 i32.shr_s pop hy16 # hy16 = sin(v) * (t / 256) <16bit.16bit> i32.load push t i32.mul i32.push 8 i32.shr_s pop hx16 # hx16 = cos(v) * (t / 256) <16bit.16bit> # vxy: 垂直方向サンプリングxy間隔 i32.push 0x800200 # 0x800000 + (PI/2):64 << 3 i32.add # [ ((v << 3) + 0x800200) i32.push 0x8007F8 i32.and # [ *cos(v + 64) pop_push it push it i32.push 4 i32.add # [ *cos(v + 64) *sin(v + 64) i32.load push t i32.mul i32.push 8 i32.shr_s pop vy16 # vy16 = sin(v + 64) * (t / 256) <16bit.16bit> i32.load push t i32.mul i32.push 8 i32.shr_s pop vx16 # vx16 = cos(v + 64) * (t / 256) <16bit.16bit> # _vx16, _vy16: サンプリングxy開始点 push c push hx16 push oc i32.mul i32.sub push vx16 push or i32.mul i32.sub pop _vx16 # _vx16 = c - hx16 * oc - vx16 * or <16bit.16bit> push r push hy16 push oc i32.mul i32.sub push vy16 push or i32.mul i32.sub pop _vy16 # _vy16 = r - hy16 * oc - vy16 * or <16bit.16bit> push w push h push hx16 push hy16 push vx16 push vy16 push _vx16 push _vy16 call bg_rotnscl_ss ) # # 回転拡大縮小機能 # サンプリング開始位置とサンプリング間隔による # (func $bg_rotnscl_ss (export "bg_rotnscl_ss") (param $w i32) # 生成サイズ (param $h i32) (param $hx16 i32) # hxy: 水平方向サンプリングxy間隔 (param $hy16 i32) (param $vx16 i32) # vxy: 垂直方向サンプリングxy間隔 (param $vy16 i32) (param $_vx16 i32) # サンプリング開始位置(右下) (param $_vy16 i32) (local $_hx16 i32) # サンプリング位置カウンタ (local $_hy16 i32) (local $dest_adr i32) (local $x i32) # 描画先アドレス push w push h i32.mul i32.push 2 i32.shl pop dest_adr # dest_adr = (w * h) << 2 vloop: loop # 垂直方向ループ # 水平方向カウンタを初期化 push w pop x # x = w # サンプリング位置を垂直方向に進め、水平方向の初期位置としてセット push _vx16 push vx16 i32.add pop_push _vx16 # _vx16 += vx16 pop _hx16 # _hx16 = _vx16 push _vy16 push vy16 i32.add pop_push _vy16 # _vy16 += vy16 pop _hy16 # _hy16 = _vy16 hloop: loop # 水平方向ループ push dest_adr i32.push 4 i32.sub pop_push dest_adr # [ (dest_adr -= 4) # サンプリング位置を水平方向に進める(水平成分) push _hx16 push hx16 i32.add i32.push 0x3FFFFFF # 水平方向パターンリピート i32.and pop_push _hx16 # [ dest_adr (_hx16 += hx16) i32.push 16 i32.shr_u # [ dest_adr _hx # サンプリング位置を水平方向に進める(垂直成分) push _hy16 push hy16 i32.add i32.push 0x3FFFFFF # 垂直方向パターンリピート i32.and pop_push _hy16 # [ dest_adr _hx (_hy16 += hy16) i32.push 16 i32.shr_u i32.push 10 i32.shl # [ dest_adr _hx (_hy << 10) # サンプリングアドレス計算 i32.add i32.push 2 i32.shl # [ dest_adr (_hx + (_hy << 10)) << 2) i32.push 0x400000 i32.add # [ dest_adr src_adr # サンプリング&描画 i32.load # [ dest_adr color i32.store # [ push x i32.push 1 i32.sub pop_push x jp_nz hloop # (x -= 1) != 0 and loop end push dest_adr jp_nz vloop # dest_adr != 0 and loop end ) ) __END__