misc/spr256test.s
;========================================================================================
; spr256test.s
; Copyright (C) 2003-2023 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/
;========================================================================================
;----------------------------------------------------------------
;
; spr256test.x
; XEiJのスプライト256枚表示機能の動作を確認します。
; 他のエミュレータでもスプライト256枚表示機能があれば動くかも知れません。
; X68000実機では動きません。
;
; 最終更新
; 2023-02-09
;
; 作り方
; has060 -i include -o spr256test.o -w spr256test.s
; lk -o spr256test.x spr256test.o
;
; 使い方
; XEiJの改造メニューでスプライト256枚表示をONにします。
; XEiJの改造メニューでラスタあたりのスプライトの枚数を256に変更します。
; 必要ならばリセットします。
; spr256test.xを実行します。
; 何かキーを押すと終了します。
;
; 更新履歴
; 2023-02-09
; 初版。
;
;----------------------------------------------------------------
.include control2.mac
.include doscall.mac
.include fefunc.mac
.include iocscall.mac
.include mfp.equ
.include misc.mac
.include push2.mac
.include vicon.equ
;開始
;512x512
moveq.l #0,d1
IOCS _CRTMOD
;カーソルOFF
IOCS _B_CUROFF
;スーパーバイザモード
supervisormode
;スプライト初期化
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
;スプライト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
;スプライトを表示する
; スプライトパターンを定義する前に表示して定義している様子を見せる
; スプライト番号とパターン番号は同じ
; スプライト番号の上位4ビットをパレットブロックとする
moveq.l #0,d7 ;スプライト番号/パターン番号
lea.l $00EB0000,a0 ;スプライトスクロールレジスタ
movea.l #16,a6 ;Y座標
do
movea.l #16,a5 ;X座標
do
move.w a5,(a0)+ ;X座標
move.w a6,(a0)+ ;Y座標
move.w d7,d0
and.w #$00F0,d0 ;パレットブロック
lsl.w #4,d0
move.b d7,d0 ;パターン番号
move.w d0,(a0)+ ;パレットブロック<<8|パターン番号
move.w #3,(a0)+ ;プライオリティ
addq.l #1,d7 ;スプライト番号
adda.l #16,a5 ;X座標
while <cmpa.l #16+16*16,a5>,lo
adda.l #16,a6 ;Y座標
while <cmpa.l #16+16*16,a6>,lo
;スプライトパターンを定義する
; パターン番号0~255に漢字を定義する
; パターン番号の下位4ビットをパレットコードとする。ただし0を1に読み替える
move.l #'亜',d1
moveq.l #8,d2
IOCS _FNTADR
movea.l d0,a6 ;a6=フォントアドレス
moveq.l #0,d7 ;d7=パターン番号
do
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.l d7,d1 ;パターン番号
moveq.l #1,d2 ;パターンサイズ
lea.l sprbuf,a1 ;パターンデータ
IOCS _SP_DEFCG
addq.l #1,d7
while <cmp.l #256,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周期遅れにするか
GAP equ 30 ;文字の間隔
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 ;垂直帰線期間を待つ
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
;ユーザモード
usermode
;768x512
; moveq.l #16,d1
moveq.l #0,d1
IOCS _CRTMOD
;カーソル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