;========================================================================================
;  spr1016test.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/
;========================================================================================

;----------------------------------------------------------------
;spr1016test.x
;	XEiJの拡張機能をテストします。以下の設定で実行してください。
;	・スプライトの枚数1016
;	・4096個のパターン
;	・768x512でスプライトを表示
;	・ラスタあたりのスプライトの枚数1016
;	・sprdrv.xを組み込む
;	何かキーを押すと終了します。
;	X68000実機では動きません。
;更新履歴
;	2025-04-07
;		初版。
;	2025-04-10
;		IOCS _SP_REGSTのスプライト番号の変更に追従しました。
;----------------------------------------------------------------

	.include	control2.mac
	.include	doscall.mac
	.include	fefunc.mac
	.include	forvar.mac
	.include	iocscall.mac
	.include	misc.mac
	.include	sprc.equ

;画面モードを変更する
	move.l	#14<<16|3,-(sp)		;ファンクションキー表示なし
	DOS	_CONCTRL
	addq.l	#4,sp
	move.w	d0,-(sp)
	move.l	#16<<16|0,-(sp)		;768x512グラフィックなし
	DOS	_CONCTRL
	addq.l	#4,sp
	move.w	d0,-(sp)

;スプライト画面を初期化する
	move.l	#'SPRD',d1		;拡張機能を使用する
	move.l	#2<<1|1,d2		;パターン4096個、テキストエリア移動あり
	IOCS	_SP_INIT

;軌道を作る
;	x=16+floor(OX+AX*sin(AF*t)-BX*sin(BF*t))
;	y=16+floor(OY+AY*cos(AF*t)+BY*cos(BF*t))
N	equ	1016			;要素数
M	equ	23			;分割数
PI	fset	3.14159265358979323846	;円周率
TI	fequ	2.0*PI/(M*N)		;t/位置番号
OX	fequ	376.0			;中心X
OY	fequ	248.0			;中心Y
RX	fequ	360.0			;全体の半径X
RY	fequ	240.0			;全体の半径Y
AF	fequ	6.0			;大円の周波数
BF	fequ	23.0			;小円の周波数
PA	fequ	5.0			;大円の割合
PB	fequ	2.0			;小円の割合
AX	fequ	RX*PA/(PA+PB)		;大円の半径X
AY	fequ	RY*PA/(PA+PB)		;大円の半径Y
BX	fequ	RX*PB/(PA+PB)		;小円の半径X
BY	fequ	RY*PB/(PA+PB)		;小円の半径Y
	.data
	.even
ti:	.dc.d	TI
af:	.dc.d	AF
bf:	.dc.d	BF
ax:	.dc.d	AX
bx:	.dc.d	BX
ox:	.dc.d	OX
ay:	.dc.d	AY
by:	.dc.d	BY
oy:	.dc.d	OY
	.bss
	.even
;軌道(位置番号*4→座標)
orbit:
	.dc.w	2*M*N
	.text
	lea.l	orbit(pc),a0		;軌道
	moveq.l	#0,d7			;d7=i 位置番号
	do
		move.l	d7,d0			;d0=i
		FPACK	__LTOD			;d0d1=i
		movem.l	ti(pc),d2-d3		;d2d3=ti
		FPACK	__DMUL			;d0d1=ti*i=t
		move.l	d0,d4
		move.l	d1,d5			;d4d5=t
		movem.l	af(pc),d2-d3		;d2d3=af
		FPACK	__DMUL			;d0d1=af*t
		movea.l	d0,a2
		movea.l	d1,a3			;a2a3=af*t
		move.l	d4,d0
		move.l	d5,d1			;d0d1=t
		movem.l	bf(pc),d2-d3		;d2d3=bf
		FPACK	__DMUL			;d0d1=bf*t
		movea.l	d0,a4
		movea.l	d1,a5			;a4a5=bf*t
		FPACK	__SIN			;d0d1=sin(bf*t)
		movem.l	bx(pc),d2-d3		;d2d3=bx
		FPACK	__DMUL			;d0d1=bx*sin(bf*t)
		move.l	d0,d4
		move.l	d1,d5			;d4d5=bx*sin(bf*t)
		move.l	a2,d0
		move.l	a3,d1			;d0d1=af*t
		FPACK	__SIN			;d0d1=sin(af*t)
		movem.l	ax(pc),d2-d3		;d2d3=ax
		FPACK	__DMUL			;d0d1=ax*sin(af*t)
		move.l	d4,d2
		move.l	d5,d3			;d2d3=bx*sin(bf*t)
		FPACK	__DSUB			;d0d1=ax*sin(af*t)-bx*sin(bf*t)
		movem.l	ox(pc),d2-d3		;d2d3=ox
		FPACK	__DADD			;d0d1=ox+ax*sin(af*t)-bx*sin(bf*t)
		FPACK	__DFLOOR		;d0d1=floor(ox+ax*sin(af*t)-bx*sin(bf*t))
		FPACK	__DTOL			;d0=floor(ox+ax*sin(af*t)-bx*sin(bf*t))
		add.l	#16,d0			;d0=16+floor(ox+ax*sin(af*t)-bx*sin(bf*t))=x
		move.l	d0,d6			;d6=x
		move.l	a4,d0
		move.l	a5,d1			;d0d1=bf*t
		FPACK	__COS			;d0d1=cos(bf*t)
		movem.l	by(pc),d2-d3		;d2d3=by
		FPACK	__DMUL			;d0d1=by*cos(bf*t)
		move.l	d0,d4
		move.l	d1,d5			;d4d5=by*cos(bf*t)
		move.l	a2,d0
		move.l	a3,d1			;d0d1=af*t
		FPACK	__COS			;d0d1=cos(af*t)
		movem.l	ay(pc),d2-d3		;d2d3=ay
		FPACK	__DMUL			;d0d1=ay*cos(af*t)
		move.l	d4,d2
		move.l	d5,d3			;d2d3=by*cos(bf*t)
		FPACK	__DADD			;d0d1=ay*cos(af*t)+by*cos(bf*t)
		movem.l	oy(pc),d2-d3		;d2d3=oy
		FPACK	__DADD			;d0d1=oy+ay*cos(af*t)+by*cos(bf*t)
		FPACK	__DFLOOR		;d0d1=floor(oy+ay*cos(af*t)+by*cos(bf*t))
		FPACK	__DTOL			;d0=floor(oy+ay*cos(af*t)+by*cos(bf*t))
		add.l	#16,d0			;d0=16+floor(oy+ay*cos(af*t)+by*cos(bf*t))=y
		move.w	d6,(a0)+		;x
		move.w	d0,(a0)+		;y
		addq.l	#1,d7			;i++
	while	<cmp.l	#M*N,d7>,lo

;パレットを設定する
;	パレットブロック1〜15、パレットコード1〜15の225色を使う
;	j=0〜224	色番号
;	h=floor(HJ*j)
;	s=31
;	v=floor(VO+VR*cos(VF*TJ*j))
	.data
	.even
hj:	.dc.d	192.0/225.0
vftj:	.dc.d	AF*2.0*PI/225.0
vr:	.dc.d	10.0
vo:	.dc.d	20.0
;色番号→パレットブロック
color_to_block:
	forvar	i,0,224,<.dc.b (i/15)+1>
;色番号→パレットコード
color_to_code:
	forvar	i,0,224,<.dc.b (i.mod.15)+1>
	.text
	lea.l	color_to_block(pc),a4	;色番号→パレットブロック
	lea.l	color_to_code(pc),a5	;色番号→パレットコード
	moveq.l	#0,d7			;d7=j 色番号
	do
		move.l	d7,d0			;d0=j
		FPACK	__LTOD			;d0d1=j
		move.l	d0,d4
		move.l	d1,d5			;d4d5=j
		movem.l	hj(pc),d2-d3		;d2d3=hj
		FPACK	__DMUL			;d0d1=hj*j
		FPACK	__DFLOOR		;d0d1=floor(hj*j)=h
		FPACK	__DTOL			;d0=h
		move.l	d0,d6			;d6=h
		move.l	d4,d0
		move.l	d5,d1			;d0d1=p
		movem.l	vftj(pc),d2-d3		;d2d3=vf*tj
		FPACK	__DMUL			;d0d1=vf*tj*j=vf*t
		FPACK	__COS			;d0d1=cos(vf*t)
		movem.l	vr(pc),d2-d3		;d2d3=vr
		FPACK	__DMUL			;d0d1=vr*cos(vf*t)
		movem.l	vo(pc),d2-d3		;d2d3=vo
		FPACK	__DADD			;d0d1=vo+vr*cos(vf*t)
		FPACK	__DFLOOR		;d0d1=floor(vo+vr*cos(vf*t))=V
		FPACK	__DTOL			;d0=v
		move.l	d6,d1			;d1=h
		swap.w	d1			;d1=h<<16
		move.w	#31<<8,d1		;d1=h<<16|s<<8
		move.b	d0,d1			;d1=h<<16|s<<8|v
		IOCS	_HSVTORGB		;d0=カラーコード
		move.w	d0,d3			;d3=カラーコード
		moveq.l	#0,d2
		move.b	(a4,d7.w),d2		;d2=b パレットブロック
		moveq.l	#0,d1
		move.b	(a5,d7.w),d1		;d1=c パレットコード
		if	<tst.w d7>,ne
			bset.l	#31,d1
		endif
		IOCS	_SPALET
		addq.w	#1,d7			;p++
	while	<cmp.w	#225,d7>,lo

;パターンを定義する
	.data
	.even
;要素番号*2→文字
elem_to_moji:
	.dc.b	'亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威'
	.dc.b	'尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭院陰隠韻吋右'
	.dc.b	'宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅'
	.dc.b	'悦謁越閲榎厭円園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応押旺横欧殴王翁襖鴬鴎黄岡'
	.dc.b	'沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩'
	.dc.b	'貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害'
	.dc.b	'崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫橿梶鰍潟割'
	.dc.b	'喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾'
	.dc.b	'換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願'
	.dc.b	'企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠'
	.dc.b	'疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救朽求汲泣灸球究窮笈級糾給旧牛去居巨'
	.dc.b	'拒拠挙渠虚許距鋸漁禦魚亨享京供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰'
	.dc.b	'凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶'
	.dc.b	'寓遇隅串櫛釧屑屈掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景'
	.dc.b	'桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸'
	.dc.b	'拳捲検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖'
	.dc.b	'狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向后喉坑垢'
	.dc.b	'好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講'
	.dc.b	'貢購郊酵鉱砿鋼閤降項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込此頃今困坤墾婚恨懇昏'
	.dc.b	'昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載'
	.dc.b	'際剤在材罪財冴坂阪堺榊肴咲崎埼碕'
;要素番号→パレットコード
elem_to_code:
	forvar	i,0,N-1,<.dc.b ((i*225/N).mod.15)+1>
	.text
	lea.l	-(4+2*16+4*32)(sp),sp	;フォントサイズ、フォントデータ、パターンデータ
	lea.l	elem_to_moji(pc),a3	;要素番号*2→文字
	lea.l	elem_to_code(pc),a5	;要素番号→パレットコード
	moveq.l	#0,d4			;要素番号
	do
	;フォントデータを得る
		move.w	(a3)+,d1		;文字
		moveq.l	#0,d2			;16x16
		movea.l	sp,a1			;フォントサイズ、フォントデータ
		IOCS	_FNTGET
	;パレットコードを用意する
		move.b	(a5)+,d5		;パレットコード
	;フォントデータからパターンデータを作る
		lea.l	4(sp),a0		;フォントデータ
		lea.l	4+2*16(sp),a1		;パターンデータ
	;左半分
		moveq	#16-1,d3
		for	d3
			move.b	(a0)+,d0		;上→下
			addq.l	#1,a0
		;	moveq.l	#0,d1
			moveq.l	#8-1,d2
			for	d2
				lsl.l	#4,d1
				add.b	d0,d0
				if	cs
					or.b	d5,d1
				endif
			next
			move.l	d1,(a1)+		;左上→左下=右上
		next
		lea.l	-2*16(a0),a0		;下→上
	;右半分
		moveq	#16-1,d3
		for	d3
			addq.l	#1,a0			;上→下
			move.b	(a0)+,d0
		;	moveq.l	#0,d1
			moveq.l	#8-1,d2
			for	d2
				lsl.l	#4,d1
				add.b	d0,d0
				if	cs
					or.b	d5,d1
				endif
			next
			move.l	d1,(a1)+		;左下=右上→右下
		next
	;パターンを定義する
		move.l	d4,d1			;パターン番号=要素番号
		moveq.l	#1,d2			;16x16
		lea.l	4+2*16(sp),a1		;パターンデータ
		IOCS	_SP_DEFCG
		addq.w	#1,d4			;要素番号++
	while	<cmp.w #N,d4>,lo
	lea.l	4+2*16+4*32(sp),sp

;カーソル表示OFF
	IOCS	_B_CUROFF

;スプライト表示ON
	IOCS	_SP_ON

;動かす
	.data
	.even
;要素番号*2→キャラクタ
elem_to_char:
	forvar	i,0,N-1,<.dc.w ((i&$F00)<<4)|(((i*225/N)/15+1)<<8)|(i&$FF)>
	.text
	lea.l	orbit(pc),a2		;軌道の先頭→要素0の座標のアドレス
	movea.l	a2,a3			;軌道の先頭
	move.l	#4*M*N,d6		;軌道の長さ
	adda.l	d6,a3			;軌道の末尾
	moveq.l	#0,d2
	moveq.l	#0,d3
	moveq.l	#0,d4
	movea.l	#$80000000,a5
	do
		lea.l	elem_to_char(pc),a4	;要素番号*2→キャラクタ
		movea.l	a2,a1			;要素の座標のアドレス
		moveq.l	#0,d1			;要素0はVDISPの立ち下がりを待つ
		moveq.l	#0,d7			;要素番号
		do
			move.w	d7,d1			;スプライト番号(連番)
			move.w	(a1)+,d2		;X座標
			move.w	(a1)+,d3		;Y座標
			move.w	(a4)+,d4		;キャラクタ
			moveq.l	#3,d5			;プライオリティ
			IOCS	_SP_REGST
			move.l	a5,d1			;要素0以外はVDISPの立ち下がりを待たない
			lea.l	4*(M-1)(a1),a1		;要素の座標のアドレス+=分割数*4
			if	<cmpa.l a3,a1>,hs	;末尾に達した
				suba.l	d6,a1			;巻き戻す
			endif
			addq.w	#1,d7			;要素番号++
		while	<cmp.w #N,d7>,lo
		addq.l	#4,a2			;要素0の座標のアドレス+=4
		if	<cmpa.l a3,a2>,hs	;末尾に達した
			suba.l	d6,a2			;巻き戻す
		endif
		bsr	inkey0
	while	eq			;何かキーが押されるまで繰り返す

;スプライト表示OFF
	IOCS	_SP_OFF

;カーソル表示ON
	IOCS	_B_CURON

;画面モードを復元する
	move.w	#16,-(sp)
	DOS	_CONCTRL
	addq.l	#4,sp
	move.w	#14,-(sp)
	DOS	_CONCTRL
	addq.l	#4,sp

;終了
	DOS	_EXIT

;----------------------------------------------------------------
;文字コードが0でないキーを入力する。押されていなくても待たない
;>d0.l:文字コード。0=押されていない
inkey0::
	dostart
		IOCS	_B_KEYINP		;キーバッファから取り除く
		break	<tst.b d0>,ne		;文字コードが0でないキーが押されたとき終了
	start
		IOCS	_B_KEYSNS		;キーバッファを先読みする
	while	<tst.l d0>,ne		;何か押されているとき繰り返す
	and.l	#$000000FF,d0		;文字コード
	rts
