misc/pat4096test.s
;========================================================================================
; pat4096test.s
; Copyright (C) 2003-2025 Makoto Kamada
;
; This file is part of the XEiJ (X68000 Emulator in Java).
; You can use, modify and redistribute the XEiJ if the conditions are met.
; Read the XEiJ License for more details.
; https://stdkmd.net/xeij/
;========================================================================================
;----------------------------------------------------------------------------------------
; pat4096test.x
; XEiJの256枚のスプライトと4096個のパターンをテストします。
; 改造メニューの256枚のスプライトチェックボックスと4096個のパターンチェックボックスをONにしてリセットしてから実行します。
; 何かキーを押すと終了します。
; X68000実機では動きません。
;----------------------------------------------------------------------------------------
.include control2.mac
.include doscall.mac
.include fefunc.mac
.include iocscall.mac
.include mfp.equ
.include misc.mac
.include push2.mac
.include vicon.equ
;開始
;画面モードを変更
move.w #3,-(sp) ;ファンクションキー表示なし
move.w #14,-(sp)
DOS _CONCTRL
move.w d0,function_mode
move.w #2,-(sp) ;512x512グラフィックなし
move.w #16,-(sp)
DOS _CONCTRL
move.w d0,screen_mode
addq.l #8,sp
;カーソルOFF
IOCS _B_CUROFF
;スーパーバイザモード
supervisormode
;パターン4096枚定義ON
move.w #$0005,$00EB0812
move.w #$0000,$00EB0814
;スプライト初期化
IOCS _SP_INIT
;スプライト128~255をクリア
lea.l $00EB0000+8*128,a0
moveq.l #0,d0
moveq.l #128-1,d1
for d1
move.l d0,(a0)+
move.l d0,(a0)+
next
;バンク1~15をクリア
moveq.l #0,d0
move.w #$0100,d2
do
move.w d2,$00EB0814
lea.l $00EB8000,a0
move.w #32768/8-1,d1
for d1
move.l d0,(a0)+
move.l d0,(a0)+
next
add.w #$0100,d2
while <cmp.w #$0F00,d2>,ls
;スプライト表示ON
IOCS _SP_ON
;パレットを設定する
; パレットコード$x0は黒。パレットコード$x1~$xFの240色を用いる
; n=0~239
; t=n/240
; H=floor(192*t)
; S=31
; V=31 floor(15+8*cos(2*pi*t)+0.5)
lea.l VICON_TSPALET,a0 ;パレットレジスタ
suba.l a1,a1 ;a1=n
do
clr.w (a0)+ ;パレットコード$x0は黒
moveq.l #15-1,d7 ;パレットコード$x1~$xF
for d7
move.l #240,d0
FPACK __LTOD ;d0-d1=240
move.l d0,d2
move.l d1,d3 ;d2-d3=240
move.l a1,d0
FPACK __LTOD ;d0-d1=n
FPACK __DDIV ;d0-d1=n/240=t
move.l d0,d4
move.l d1,d5 ;d4-d5=t
move.l d0,d2
move.l d1,d3 ;d2-d3=t
move.l #192,d0
FPACK __LTOD ;d0-d1=192
FPACK __DMUL ;d0-d1=192*t
FPACK __DFLOOR ;H=floor(192*t)
FPACK __DTOL
move.l d0,d6
swap.w d6
move.w #31.shl.8,d6 ;S=31
move.l d4,d0
move.l d5,d1 ;d0-d1=t
FPACK __NPI ;d0-d1=pi*t
move.l d0,d2
move.l d1,d3 ;d2-d3=pi*t
move.l #2*15,d0
FPACK __LTOD ;d0-d1=2*15
FPACK __DMUL ;d0-d1=2*pi*10*t
FPACK __COS ;d0-d1=cos(2*pi*t)
move.l d0,d2
move.l d1,d3 ;d2-d3=cos(2*pi*t)
moveq.l #8,d0
FPACK __LTOD ;d0-d1=8
FPACK __DMUL ;d0-d1=8*cos(2*pi*t)
move.l d0,d2
move.l d1,d3 ;d2-d3=8*cos(2*pi*t)
moveq.l #15,d0
FPACK __LTOD ;d0-d1=15
FPACK __DADD ;d0-d1=15+8*cos(2*pi*t)
move.l #$3FE00000,d2
moveq.l #$00000000,d3 ;d2-d3=0.5
FPACK __DADD ;d0-d1=15+8*cos(2*pi*t)+0.5
FPACK __DFLOOR ;V=floor(15+8*cos(2*pi*t)+0.5)
FPACK __DTOL
move.b d0,d6
move.l d6,d1 ;d1=H<<16|S<<8|V
IOCS _HSVTORGB
move.w d0,(a0)+
addq.l #1,a1 ;n++
next
while <cmpa.l #VICON_TSPALET+2*256,a0>,lo
;スプライトパターンを定義する
; パターン番号0~4095に漢字を定義する
; パターン番号の下位4ビットをパレットコードとする。ただし0を1に読み替える
move.l #'亜',d1
moveq.l #8,d2
IOCS _FNTADR
movea.l d0,a6 ;a6=フォントアドレス
moveq.l #0,d7 ;d7=パターン番号
do
;空白を読み飛ばす
dostart
lea.l 32(a6),a6
start
movea.l a6,a0
moveq.l #0,d0
moveq.l #8-1,d6
for d6
or.l (a0)+,d0
next
while eq
if <tst.b d7>,eq ;パターン番号が256の倍数のとき
;スプライトを表示する
; スプライトパターンを定義する前に表示して定義している様子を見せる
; スプライト番号とパターン番号は同じ
; スプライト番号の上位4ビットをパレットブロックとする
moveq.l #0,d6 ;スプライト番号/パターン番号
lea.l $00EB0000,a0 ;スプライトスクロールレジスタ
movea.l #16,a4 ;Y座標
do
movea.l #16,a5 ;X座標
do
move.w a5,(a0)+ ;X座標
move.w a4,(a0)+ ;Y座標
move.w d7,d0 ;バンク番号
move.b d6,d0 ;パレットブロック
lsl.w #4,d0
move.b d6,d0 ;パターン番号
move.w d0,(a0)+ ;バンク番号<<12|パレットブロック<<8|パターン番号
move.w #3,(a0)+ ;プライオリティ
addq.l #1,d6 ;スプライト番号
adda.l #16,a5 ;X座標
while <cmpa.l #16+16*16,a5>,lo
adda.l #16,a4 ;Y座標
while <cmpa.l #16+16*16,a4>,lo
endif
lea.l sprbuf,a0
moveq.l #15,d3
and.b d7,d3 ;パターン番号の下位4ビット
if eq
moveq.l #1,d3 ;0を1に読み替える
endif
moveq #16-1,d4
for d4
move.b (a6)+,d0 ;左半分
addq.l #1,a6
moveq.l #8-1,d2
for d2
lsl.l #4,d1
add.b d0,d0
if cs
or.b d3,d1
endif
next
move.l d1,(a0)+
next
lea.l -2*16(a6),a6
moveq #16-1,d4
for d4
addq.l #1,a6
move.b (a6)+,d0 ;右半分
moveq.l #8-1,d2
for d2
lsl.l #4,d1
add.b d0,d0
if cs
or.b d3,d1
endif
next
move.l d1,(a0)+
next
move.w d7,$00EB0814 ;バンク番号
moveq.l #0,d1
move.b d7,d1 ;パターン番号
moveq.l #1,d2 ;パターンサイズ
lea.l sprbuf,a1 ;パターンデータ
IOCS _SP_DEFCG
addq.l #1,d7
while <cmp.l #4096,d7>,lo
;軌道を作る
; {x=3sin(t)-sin(3t/2)
; {y=3cos(t)+cos(3t/2) (0≦t<4π)
; -4<=x,y<=4
; https://twitter.com/sukannpi2/status/860126933606047745
; 垂直55.458Hzなので1周30秒とすると垂直同期1664回で1周
; dt=4π/1664
; スプライトの間隔を4π/256にすると1周繋がるがテーブルを作りにくい
; 6周期遅れにするか
FLIP equ 15 ;バンクを切り替える間隔
GAP equ FLIP*2 ;文字の間隔
ORBIT_LENGTH equ GAP*256 ;軌道の位置の数
COEFF_N equ 3 ;3*sin(t)の3
COEFF_T equ 13 ;3*t/2の3 大きくすると角が増えて尖る
COEFF_S equ 2 ;3*t/2の2
COEFF_P equ 4 ;4*piの4
RADIUS_X equ 50 ;X方向の半径
RADIUS_Y equ 60 ;Y方向の半径
lea.l orbit,a0
move.l #ORBIT_LENGTH,d0
FPACK __LTOD
move.l d0,d2 ;d2-d3=ORBIT_LENGTH
move.l d1,d3
moveq.l #COEFF_P,d0
FPACK __LTOD
FPACK __NPI ;d0-d1=4*pi
FPACK __DDIV ;d0-d1=4*pi/ORBIT_LENGTH=dt
movea.l d0,a4 ;a4-a5=dt
movea.l d1,a5
move.l a4,d2 ;d2-d3=dt
move.l a5,d3
move.l #COEFF_T,d0
FPACK __LTOD ;d0-d1=3
FPACK __DMUL ;d0-d1=3*dt
move.l d0,d2 ;d2-d3=3*dt
move.l d1,d3
move.l #COEFF_S,d0
FPACK __LTOD ;d0-d1=2
exg.l d0,d2 ;d0-d1=3*dt
exg.l d1,d3 ;d2-d3=2
FPACK __DDIV ;d0-d1=3*dt/2
movea.l d0,a2 ;a2-a3=3*dt/2
movea.l d1,a3
moveq.l #0,d6 ;d6-d7=0=t
moveq.l #0,d7
moveq.l #0,d4 ;d4-d5=0=3*t/2
moveq.l #0,d5
movea.l #0,a1 ;n=0..1663
do
moveq.l #COEFF_N,d0
FPACK __LTOD ;d0-d1=3
move.l d0,d2 ;d2-d3=3
move.l d1,d3
move.l d6,d0 ;d0-d1=t
move.l d7,d1
FPACK __SIN ;d0-d1=sin(t)
FPACK __DMUL ;d0-d1=3*sin(t)
move.l d0,d2 ;d2-d3=3*sin(t)
move.l d1,d3
move.l d4,d0 ;d0-d1=3*t/2
move.l d5,d1
FPACK __SIN ;d0-d1=sin(3*t/2)
exg.l d0,d2 ;d0-d1=3*sin(t)
exg.l d1,d3 ;d2-d3=sin(3*t/2)
FPACK __DSUB ;d0-d1=3*sin(t)-sin(3*t/2)=x
move.l d0,d2 ;d2-d3=x
move.l d1,d3
move.l #RADIUS_X,d0
FPACK __LTOD ;d0-d1=60
FPACK __DMUL ;d0-d1=60*x
move.l d0,d2 ;d2-d3=60*x
move.l d1,d3
move.l #16+256-8,d0
FPACK __LTOD ;d0-d1=16+256-8
FPACK __DADD ;d0-d1=16+256-8+60*x
move.l #$3FE00000,d2 ;d2-d3=0.5
moveq.l #$00000000,d3
FPACK __DADD ;d0-d1=16+256-8+60*x+0.5
FPACK __DFLOOR ;d0-d1=floor(16+256-8+60*x+0.5)
FPACK __DTOL
ifor <tst.l d0>,lt,<cmp.l #16+512,d0>,ge
moveq.l #0,d0
endif
move.w d0,(a0)+
moveq.l #COEFF_N,d0
FPACK __LTOD ;d0-d1=3
move.l d0,d2 ;d2-d3=3
move.l d1,d3
move.l d6,d0 ;d0-d1=t
move.l d7,d1
FPACK __COS ;d0-d1=cos(t)
FPACK __DMUL ;d0-d1=3*cos(t)
move.l d0,d2 ;d2-d3=3*cos(t)
move.l d1,d3
move.l d4,d0 ;d0-d1=3*t/2
move.l d5,d1
FPACK __COS ;d0-d1=cos(3*t/2)
exg.l d0,d2 ;d0-d1=3*cos(t)
exg.l d1,d3 ;d2-d3=cos(3*t/2)
FPACK __DADD ;d0-d1=3*cos(t)+cos(3*t/2)=y
move.l d0,d2 ;d2-d3=y
move.l d1,d3
move.l #RADIUS_Y,d0
FPACK __LTOD ;d0-d1=60
FPACK __DMUL ;d0-d1=60*y
move.l d0,d2 ;d2-d3=60*y
move.l d1,d3
move.l #16+256-8,d0
FPACK __LTOD ;d0-d1=16+256-8
FPACK __DSUB ;d0-d1=16+256-8-60*y
move.l #$3FE00000,d2 ;d2-d3=0.5
moveq.l #$00000000,d3
FPACK __DADD ;d0-d1=16+256-8-60*y+0.5
FPACK __DFLOOR ;d0-d1=floor(16+256-8-60*y+0.5)
FPACK __DTOL
ifor <tst.l d0>,lt,<cmp.l #16+512,d0>,ge
moveq.l #0,d0
endif
move.w d0,(a0)+
move.l d6,d0 ;d0-d1=t
move.l d7,d1
move.l a4,d2 ;d2-d3=dt
move.l a5,d3
FPACK __DADD ;d0-d1=t+dt
move.l d0,d6 ;d6-d7=t+dt
move.l d1,d7
move.l d4,d0 ;d0-d1=3*t/2
move.l d5,d1
move.l a2,d2 ;d2-d3=3*dt/2
move.l a3,d3
FPACK __DADD ;d0-d1=3*(t+dt)/2
move.l d0,d4 ;d4-d5=3*(t+dt)/2
move.l d1,d5
addq.l #1,a1
while <cmpa.l #ORBIT_LENGTH,a1>,lo
;動かす
lea.l orbit,a4 ;a4=軌道データの配列の先頭
lea.l 4*ORBIT_LENGTH(a4),a5 ;a5=軌道データの配列の末尾
lea.l $00EB0000,a6 ;スプライト0のスプライトスクロールレジスタ
movea.l a4,a3 ;スプライト0の軌道データの位置
do
do
while <btst.b #MFP_G_VDISP_BIT,MFP_GPDR>,eq ;垂直表示期間を待つ
do
while <btst.b #MFP_G_VDISP_BIT,MFP_GPDR>,ne ;垂直帰線期間を待つ
;位置がFLIPの倍数のときバンク番号を増やす
move.l a3,d0
sub.l a4,d0
lsr.l #2,d0
divu.w #FLIP,d0
swap.w d0
if <tst.w d0>,eq
lea.l $00EB0000,a0
move.w #256-1,d0
for d0
addi.w #$1000,4(a0)
adda.l #8,a0
next
endif
movea.l a3,a1 ;軌道データ
movea.l a6,a2 ;スプライトスクロールレジスタ
move.w #256-1,d0
for d0
move.l (a1),(a2) ;軌道データをスプライトスクロールレジスタへ
lea.l -4*GAP(a1),a1 ;軌道データの位置を6戻す
if <cmpa.l a4,a1>,lo
lea.l 4*ORBIT_LENGTH(a1),a1
endif
addq.l #8,a2 ;次のスプライトのスプライトスクロールレジスタ
next
addq.l #4,a3 ;スプライト0の軌道データの位置を1進める
if <cmpa.l a5,a3>,hs
lea.l -4*ORBIT_LENGTH(a3),a3
endif
bsr inkey0
while eq
;スプライト表示OFF
IOCS _SP_OFF
;パターン4096枚定義OFF
move.w #$0000,$00EB0812
move.w #$0000,$00EB0814
;ユーザモード
usermode
;画面モードを復元
move.w screen_mode,-(sp)
move.w #16,-(sp)
DOS _CONCTRL
move.w function_mode,-(sp)
move.w #14,-(sp)
DOS _CONCTRL
addq.l #8,sp
;カーソルON
IOCS _B_CURON
;終了
DOS _EXIT
;キー入力(待たない)
;>d0.l:文字コード。0=なし
inkey0:
do
IOCS _B_KEYSNS
break <tst.l d0>,eq
IOCS _B_KEYINP
and.l #$FF,d0
while eq
rts
;キー入力(待つ)
;>d0.l:文字コード
inkey1:
do
do
IOCS _B_KEYSNS
while <tst.l d0>,eq
IOCS _B_KEYINP
and.l #$FF,d0
while eq
rts
.bss
.even
sprbuf:
.ds.l 2*16
orbit:
.ds.w 2*ORBIT_LENGTH
.even
function_mode:
.ds.w 1
screen_mode:
.ds.w 1