gs2bg.s
29.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
/*---------------------------------------------------------------------
Copyright (C) 1997, Nintendo.
File gs2bg.s
Coded by Yoshitaka Yasumoto. Mar 10, 1997.
Modified by
Comments
$Id: gs2bg.s,v 1.1.1.1 2002/05/02 03:29:12 blythe Exp $
---------------------------------------------------------------------*/
#!Reserved (0,11,12,17,18,19,20,23,24,25,26,27,30,31)
#!Reserved (v0,v1,v27,v28,v29,v30,v31)
#----------------------------------------------------------------------------
# case_G_BG_COPY:
#
# typedef struct {
# u16 imageX; /*テクスチャの左上位置 X 座標 (u10.5)*/
# u16 imageW; /*テクスチャの幅 (u10.2)*/
# s16 frameX; /*転送されるフレームの左上位置 (s10.2)*/
# u16 frameW; /*転送されるフレームの幅 (u10.2)*/
# u16 imageY; /*テクスチャの左上位置 Y 座標 (u10.5)*/
# u16 imageH; /*テクスチャの高さ (u10.2)*/
# s16 frameY; /*転送されるフレームの左上位置 (s10.2)*/
# u16 frameH; /*転送されるフレームの高さ (u10.2)*/
# u64 *imagePtr; /*DRAM 上のテクスチャソースアドレス */
# u16 imageLoad;
# u8 imageFmt;
# u8 imageSiz;
# u16 imagePal;
# u16 imageFlip;
#
# /* 初期化ルーチン XXXX で設定される */
# u16 tmemH; /*一度にロードできる TMEM 高さ (s13.2) */
# u16 tmemW; /* LoadBlock の時 imageW の TMEM 幅 Word 数
# LoadTile の時 frameW の TMEM 幅 Word 数 */
# u16 tmemLoadSH; /* LoadBlock/Tile コマンドのパラメータSH */
# u16 tmemLoadTH; /* LoadBlock/Tile コマンドのパラメータTH */
# u16 tmemSizeW; /* image 1 ライン分の imagePtr のバイト数/4 */
# u16 tmemSize; /* TMEM のロード 1 回分のバイト数 */
# } uObjTmem_t;
#
# +---------------+---------------+---------------+---------------+
# | imageX | imageW | frameX | frameW |
# +---------------+---------------+---------------+---------------+
# | imageY | imageH | frameY | frameH |
# +---------------+---------------+---------------+---------------+
# | imagePtr | imageLoad |imgFmt |imgSiz |
# +---------------+---------------+---------------+---------------+
# | 0 |imgPal | 0 |imgFlip| tmemH | tmemW |
# +---------------+---------------+---------------+---------------+
# | tmemLoadSH | tmemLoadTH | tmemSizeW | tmemSize |
# +---------------+---------------+---------------+---------------+
#
# BG 用転送処理
#----------------------------------------------------------------------------
case_G_BG_COPY:
#---------------------------------------------------------------------
# uObjBg データのアドレスを物理アドレスに変換し,
# DMA 転送をかける.
#---------------------------------------------------------------------
AssignForDMAproc
jal AdrsFixup
_li (dmem_adrs, RSP_INPUT_BG) # 64bit alignment
jal DMAread
_li (dma_len, 39) # dram_adrs は AdrsFixup で設定される
#---------------------------------------------------------------------
# DMA 転送終了を待ち. その間にパラメータのロードを行なう.
# 転送終了後 Object のジオメトリデータおよびイメージデータを取得.
#---------------------------------------------------------------------
Assign(scissor, v2)
#ifdef UCODE_S2DEX2
llv scissor[4], oRSP_SCISSOR_XL(vecptr) # [2|3] = [SXL|SXH]
jal DMAwait
llv scissor[12], oRSP_SCISSOR_YL(vecptr) # [6|7] = [SYL|SYH]
#else
llv scissor[4], RSP_STATEP_SCISSOR_XL(zero) # [2|3] = [SXL|SXH]
jal DMAwait
llv scissor[12], RSP_STATEP_SCISSOR_YL(zero) # [6|7] = [SYL|SYH]
#endif
EndAssignForDMAproc
#---------------------------------------------------------------------
# シザリング処理
#
# imageXr = imageX; /* X-Flip 処理用 imageX */
# if (0 > (pixel = frameX - ScissorXL)){ /* pixel は負 */
# imageX -= pixel;
# frameX -= pixel;
# frameW += pixel;
# }
# if (0 > (pixel = frameY - ScissorYU)){
# imageY -= pixel;
# frameY -= pixel;
# frameH += pixel;
# }
# if (0 < (pixel = frameX + frameW - ScissorXR)){ /* pixel は正 */
# frameW -= pixel;
# imageXr+= pixel;
# }
# if (0 < (pixel = frameY + frameH - ScissorXL)){
# frameH -= pixel;
# }
# if (frameW <= 0 || frameH <= 0) return;
# if (X-Flip == ON) imageX = imageXr;
#
# 結果として以下のようになる
# imgfrXY[0|4] = imageX, imageY
# imgfrXY[2|6] = frameX, frameY
# frameWH[3|7] = frameW, frameH
#---------------------------------------------------------------------
Assign(flip, 1)
FixedAssign(sptr, 20)
Assign(frameXY, v3)
Assign(imageX, v4)
Assign(imageY, v5)
Assign(imageWH, v6)
Assign(frameWH, v7)
Assign(bgparam, v8)
Assign(pixel0, v9)
Assign(pixel1, v10)
Assign(imageXY, v11)
#
# BG のジオメトリデータと imageFlip のロード
#
lqv bgparam[0], RSP_BG_IMAGEX(sptr)
lbu flip, RSP_INPUT_BG+RSP_BG_IMAGEFLIP(zero)
#
# imageXY の桁あわせ (u10.5)->(u10.2) に変換
#
vmudm imageXY, bgparam, _0x2000
#
# pixel0, pixel1 に以下の値を代入
# pixel0[-|-| fx-ScXL | fW-ScXH |-|-| fY-ScYL | fH-ScYH ]
# pixel1[-|-|-| fx+fW-ScXH |-|-|-| fY+fH-ScYH ]
#
vsub pixel0, bgparam, scissor
vmadn pixel1, vone, bgparam[2h]
#
# imageWH の作成
# [0|1|2|3] に imageW
# [4|5|6|7] に imageH
#
vadd imageWH, vzero, bgparam[1h]
#
# 小数位の丸め
#
vand imageXY, imageXY, _0xfffc
#
# pixel0,pixel1 を 0 でクランプする. これによりシザリング
# 不要時には, pixel0, pixel1 は 0 となる
#
# if (pixel0 > 0) pixel0 = 0;
# if (pixel1 < 0) pixel1 = 0;
#
vlt pixel0, vzero, pixel0[2h]
vge pixel1, vzero, pixel1[3h]
#
# pixel0, pixel1 値を各パラメータに加算し値の調整を行なう.
# シザリング不要時は pixelN=0 なので影響を与えない.
#
# もし imageY が imageH を超えたら
# ラップさせる必要がある
# imageY-imageH が正なら imageY = imageY-imageH とする
# しかし imageX, imageW は元からラップしているため
# X ラップ時に imageY を +1 する必要があるので自然にまかせる
#
vsub frameXY, bgparam, pixel0 # imageXY[0|4] frameXY[2|6]
vsub imageXY, imageXY, pixel0
vmadn imageY, imageWH, _0xffff
# vge vtmp, imageY, _0x0000 # ストール回避のため移動(*)
# vmrg imageY, imageY, imageXY # ストール回避のため移動(*)
vadd frameWH, bgparam, pixel0
vmadn frameWH, pixel1, _0xffff # frameWH[3|7]
#
# X-Flip 時の imageX 計算処理
# もし X-Flip なら imageX を操作する.
#
# bne flip, zero, bgSKIPFlip # ストール回避のため移動(*)
# vadd imageX, imageXY, pixel1 # ストール回避のため移動(*)
# vmov imageX[0], imageXY[0] # ストール回避のため移動(*)
#bgSKIPFlip: # ストール回避のため移動(*)
#
# 描画するフレーム幅が存在するかどうかの判定
# もしシザリングによって描画領域が無くなった場合は終了する
#
# if (frameW <= 0 || frameH <= 0) return;
#
vge vtmp, vzero, frameWH
cfc2 sys0, $vcc
bne flip, zero, bgSKIPFlip # ストール回避のため移動(*)
vadd imageX, imageXY, pixel1 # ストール回避のため移動(*)
vmov imageX[0], imageXY[0] # ストール回避のため移動(*)
bgSKIPFlip: # ストール回避のため移動(*)
andi sys0, sys0, 0x88
vge vtmp, imageY, _0x0000 # ストール回避のため移動(*)
bne sys0, zero, GfxDone
vmrg imageY, imageY, imageXY # ストール回避のため移動(*)
EndAssign(scissor, v2)
EndAssign(bgparam, v8)
EndAssign(imageWH, v6)
EndAssign(pixel0, v9)
EndAssign(pixel1, v10)
EndAssign(imageXY, v11)
#---------------------------------------------------------------------
# SetTile コマンド (LOADTILE=7) の設定
#
# gDPSetTile((*glistp) ++, G_IM_FMT_RGBA, G_IM_SIZ_16b,
# line, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
# +----------------+----------------+----------------+----------------+
# | Command=0x35 |Fmt=0|Sz=2| | Line | Tmem adrs=0 |
# +----------------+----------------+----------------+----------------+
# | |Tile=7| 0 |
# +----------------+----------------+----------------+----------------+
#
# LOADBLOCK なら line = 0
# LOADTILE なら line = frameWT = bg.b.tmemW
#
#---------------------------------------------------------------------
Assign(line, 2)
Assign(cmd0, 3)
Assign(cmd1, 4)
Assign(mask, 5)
lhu line, RSP_INPUT_BG+RSP_BG_TMEMW(zero)
lb mask, RSP_INPUT_BG+RSP_BG_IMAGELOAD_MASK(zero)
lui cmd0, 0x3510
sll line, line, 9
and mask, line, mask
or cmd0, cmd0, mask
sw cmd0, 0(outp) # CMD.0=0x35100000
slv _TX_LOADTILE, 4(outp) # CMD.1=G_TX_LOADTILE<<24
EndAssign(mask, 5)
#---------------------------------------------------------------------
# SetTileSize コマンド (RENDERTILE=0) の設定
#
# gDPSetTileSize((*glistp)++, G_TX_RENDERTILE, 0, 0, 0, 0);
#---------------------------------------------------------------------
slv _SETTILESIZE, 8(outp) # CMD.0=0x32000000
sw zero, 12(outp) # CMD.1=0x00000000
#---------------------------------------------------------------------
# SetTile コマンド (RENDERTILE=0) の設定
#
# gDPSetTile((*glistp)++, imageFmt, imageSiz, tmemW, 0,
# G_TX_RENDERTILE, imagePal,
# G_TX_MIRROR, 15, G_TX_NOLOD, G_TX_MIRROR, 15, G_TX_NOLOD);
#
# +----------------+----------------+----------------+----------------+
# | Command=0x35 |Fmt=0|Sz=2| | Line | Tmem adrs=0 |
# +----------------+----------------+----------------+----------------+
# | |Tile=0| Pal |0|1| 1111 | 0000 |0|1| 1111 | 0000 |
# +----------------+----------------+----------------+----------------+
#
# LOADBLOCK なら line = 0
# LOADTILE なら line = frameWT = bg.b.tmemW
#---------------------------------------------------------------------
Assign(Dfmt, 5)
Assign(Dsiz, 6)
Assign(Dpal, 7)
#
# Cmd 0 に必要なパラメータの取得
# Fmt と Siz のロード
#
lbu Dfmt, RSP_INPUT_BG+RSP_BG_IMAGEFMT(zero)
lbu Dsiz, RSP_INPUT_BG+RSP_BG_IMAGESIZ(zero)
#
# Cmd 1 に必要なパラメータの取得
# Pal と [19:0] の定数値 cmd1 のロード
# cmd1 = 0x0007c1f0 (MaskS=MaskT=15 Mirror
#
lbu Dpal, RSP_INPUT_BG+RSP_BG_IMAGEPAL(zero)
lw cmd1, RSPOBJ_SETTILE_MIRROR(zero)
#
# Cmd 0 の組み立て
#
sll cmd0, Dfmt, 2
or cmd0, cmd0, Dsiz
sll cmd0, cmd0, 19
or cmd0, cmd0, line
#
# Cmd1 の組み立て
#
sll sys0, Dpal, 20
or cmd1, cmd1, sys0
#
# Cmd0, Cmd1 のストア
#
sw cmd0, 16(outp)
sbv _SETTILE, 16(outp)
sw cmd1, 20(outp)
#
# outp バッファポインタ加算
#
addi outp, outp, 24
EndAssign(line, 2)
EndAssign(cmd0, 3)
EndAssign(cmd1, 4)
EndAssign(Dfmt, 5)
EndAssign(Dpal, 7)
#---------------------------------------------------------------------
# Texture アドレスの計算およびシフト値の取得
#
# tword = 8 / sizeof(pixel); // 1word中のピクセル数
# tmemS = imageX % (tword * 32); // テクスチャシフト量
# imgXT = imageX / (tword * 32); // Word 数
# imagePtr = imagePtr + imageY * tmemSizeW + imgXT;
# // テクスチャの先頭位置
#
# imageX の値からテクスチャのソースアドレス imagePtr と
# テクスチャのシフト値 tmemS を求める
#
# tmemS = (imageX & TableA[imageSiz]) * 8;
# imgXT = imageX / TableB[imageSiz]; // Word 単位
# (imageX は (s13.2) なのでそのままでは tmemS は (s13.2)
# となるため 8 倍して 桁あわせを行なう)
# (imgXT を imagePtr の計算の都合上 (s14.1) で求める)
#
# imageSiz pixel/1word tmemS の値 imgXT の値
# 4b(0) 16 imageX & (16*4-1) (imageX*0x0400)>>16
# 8b(1) 8 imageX & ( 8*4-1) (imageX*0x0800)>>16
# 16b(2) 4 imageX & ( 4*4-1) (imageX*0x1000)>>16
# 32b(3) 2 imageX & ( 2*4-1) (imageX*0x2000)>>16
#
# imageY は (s13.2) なので /4 で (s15.0) にする.
# また, Word から byte に直すために 8 倍し, offset 値とする.
#
# tmemWT = line
# imagePtr = imagePtr + (tmemWT * (imageY/4) + imgXT) * 8;
#---------------------------------------------------------------------
Assign(imagePtr, 2)
Assign(imageOrg, 3)
Assign(table, v2)
Assign(tmemSizeWv, v6)
Assign(tmemSv, v8)
Assign(imgXTv, v9)
Assign(tmemSHv, v10)
Assign(imagePtrL, v11)
Assign(imagePtrH, v12)
#
# imageSiz の値からテーブル引きを行なう.
#
sll Dsiz, Dsiz, 3 # Delay 内で処理される
addi Dsiz, Dsiz, RSPBG_IMAGEX_TO_TMEM
ldv table[0], 0(Dsiz)
#
# tmemSizeW のロード
# tmemSizeW: tmemSizeWv[1]
#
lsv tmemSizeWv[2], RSP_BG_TMEMSIZEW(sptr) # [1]
#
# imageY/4 の計算
#
vmudm imageY, imageY, _0x4000 # 1/4 の乗算
#
# tmemS の計算 (tmemS = imageX & TableA[imageSiz])
# imageX: imageX[0]
# TableA: table[0]
# tmemS: tmemSv[0]
#
vand tmemSv, table, imageX[0] # [0] (s14.1) で求める
#
# tmemSH の計算 (LoadTile 用のパラメータ) その 1
# tmemSH = ((imageX & TableA) + frameW) / TableB
# 必要な部分のみをロードするために必要
# 取りあえず被除数のみの計算
#
vmadn tmemSHv, vone, frameWH[3] # [0]
#
# imgXT の計算 (imgXT = imageX / TableB[imageSiz])
# imageX: imageX[0]
# TableB: table[1]
# imgXT: imgXTv[1]
#
vmudl imgXTv, table, imageX[0] # [1] Word 数 x2
#
# (tmemSizeW * (imageY/4) + imgXT) の計算
# imgXTY : ACC[1]
# tmemSizeW: tmemSizeWv[1]
# imageY : imageY[4]
#
vmadn imagePtrL, tmemSizeWv, imageY[4] # [1]
beq flip, zero, bgSKIP0
vmadh imagePtrH, vzero, _0x0000 # [1]
#
# Flip 処理 その 2
# もし X Flip なら tmemS = - (tmemS + frameW - 1)
#
vsub tmemSv, vone, tmemSHv # [0]
bgSKIP0:
#
# tmemSH の計算 (LoadTile 用のパラメータ) その 2
# tmemSH = ((imageX & TableA) + frameW) / TableB
# TableB の乗算: 結果は tmemSHv[1] へ
#
vmudl tmemSHv, table, tmemSHv[0] # [2]
#
# tmemSv の桁あわせ (s13.2)->(s10.5)
# および tmemSv[1] のクリア=> TxtrRectangle の T の値=0
#
vmudm tmemSv, tmemSv, _0x0008 # [0] (s13.2)->(s10.5)
vmadn tmemSv, vconst, _0x0000 # [0] (s13.2)->(s10.5)
vmov tmemSv[1], vzero[0]
#
# imagePtr の取得
#
ssv imagePtrL[2], oRSPOBJ_VSCRATCH+2(vecptr)
ssv imagePtrH[2], oRSPOBJ_VSCRATCH+0(vecptr)
lw imagePtr, oRSPOBJ_VSCRATCH+0(vecptr)
#
# imagePtr の値をロードし, 物理アドレスに変換する
# 結果は $19/gfx1 に代入される
#
lw gfx1, RSP_INPUT_BG+RSP_BG_IMAGEPTR(zero)
jal AdrsFixup
#
# Offset 値をアドレスに加算する
# imagePtr = imagePtr + (imagePtr) * 4;
#
srl imagePtr, imagePtr, 1 # 下位 bit をクリアする
sll imagePtr, imagePtr, 3
#ifdef UCODE_S2DEX2
add imagePtr, imagePtr, gfx1
_mov (imageOrg, gfx1)
#else
add imagePtr, imagePtr, $19
_mov (imageOrg, $19)
#endif
EndAssign(flip, 1)
EndAssign(Dsiz, 6)
EndAssign(table, v2)
EndAssign(imageX, v4)
EndAssign(imagePtrL, v11)
EndAssign(imagePtrH, v12)
#---------------------------------------------------------------------
# Texture アドレスの計算およびシフト値の取得およびカウンタ類の初期化
#
# frmXH = frameX + frameW - 1; /* コピーモードだから -1*/
# frmYL = frameY
# count = frameH
# line1 = imageH - imageY; /* Part 1 で処理するライン数 */
# if (imgXT > 0) line1 -= 4; /* Part 2,3 を行なう場合 4 減 */
# if (line1 > frameH) line1 = frameH; /* Part 1 で終了する場合 */
#---------------------------------------------------------------------
Assign(count, 1)
Assign(line1, 4)
Assign(imgH, 5)
Assign(imgY, 6)
Assign(imgXT, 7)
Assign(frmXL, 8)
Assign(frmYL, 9)
Assign(frmXH, 10)
Assign(frameXH, v2)
#
# frmXH の計算 frmXH = frameX + frameW - 1
#
vadd frameXH, frameXY, frameWH[3] # [2]
vmadn frameXH, vone, _0xffff # [2]
#
# ベクトルレジスタからスカラーレジスタへのデータ移動
# およびデータのロード
# imgH = Bg 構造体からロードする
# imgY = imageY[8] 現在のイメージソースの Y 座標/4
# imgXT = imgXTv[2] imageX の Word 換算値
# frmXL = frameXY[4] フレームの左端 X 座標
# frmXH = frameXH[4] フレームの右端 X 座標
# frmYL = frameXY[12] フレームの上端 Y 座標
# count = frameWH[14] 描画するべき総ライン数
# tmemSizeW = Bg 構造体からロードする
#
lhu imgH, RSP_INPUT_BG+RSP_BG_IMAGEH(zero)
mfc2 imgY, imageY[8]
mfc2 imgXT, imgXTv[2]
mfc2 frmXL, frameXY[4]
mfc2 frmYL, frameXY[12]
mfc2 frmXH, frameXH[4]
mfc2 count, frameWH[14]
#
# frmXL,frmXH を 12bit シフトさせ, TextureRectangle のパラ
# メータ位置に合わせる.
# ただし, frmXH の場合は, CMD=G_TXRECT もつけておく
#
# 以下のプログラムで分岐による nop 命令が多発するので
# この部分の処理をその代りに入れる (*)印
#
sll frmXL, frmXL, 12
# sll frmXH, frmXH, 12 # (*)
# lui sys1, G_TEXRECT<<8 # (*)
# or frmXH, frmXH, sys1 # (*)
#
# imgH, imgY のサブピクセルのクリア
#
andi imgH, imgH, 0xfffc
sll imgY, imgY, 2 # 1/4 値なので 4 倍する
#
# Part1 では現在の imagePtr から image の下端までを
# 描画する. この処理によって何ライン描画されるを求める.
# ただし Part1 の途中で描画が終了してしまう場合は, frmH 分
# のみを描画する.
#
# line1 = imgH - imgY; // 下端までの行数
# if (line1 <= 0) return; // 処理行数があるか ?
# if (imgXT > 0) line1 -= 4; // 端数があるなら -4
# if (line1 > frmH) line1 = frmH; // 途中で終るならfrmH行
#
sub line1, imgH, imgY
blez line1, GfxDone
sll frmXH, frmXH, 12 # (*) nop
blez imgXT, bgSKIP1
lui sys1, G_TEXRECT<<8 # (*) nop
addi line1, line1, -4
bgSKIP1: sub sys0, line1, count # frmH = count なので OK
blez sys0, bgSKIP2
or frmXH, frmXH, sys1 # (*) nop
_mov (line1, count) # line1 = frmH を代入
bgSKIP2:
EndAssign(imgY, 6)
EndAssign(imgH, 5)
EndAssign(imgXTv, v9)
EndAssign(imageY, v5)
EndAssign(frameXY, v3)
EndAssign(frameWH, v7)
EndAssign(frameXH, v2)
#---------------------------------------------------------------------
# RDP コマンドの固定部分の作成
# ループ内に入る前に計算可能な部分を出来るだけ作成しておく.
#---------------------------------------------------------------------
Assign(tmemSH, 5)
Assign(tmemTH, 6)
Assign(tmemSizeW, 13)
Assign(setTimg, 14)
Assign(loadTx0, 15)
Assign(loadTx1, 16)
#
# RDP コマンドのパラメータを取得する
#
# loadTx0 は LoadBlock の時正の値 0x33, LoadTile の時
# 負の値 0xf4 となるので loadTx0 の符号判定で Branch
# が可能
#
# SH の値として
# LoadBlock ならアプリが用意した値を使用し,
# LoadTile なら ucode 内で計算した値を使用する.
#
lb loadTx0, RSP_INPUT_BG+RSP_BG_IMAGELOAD_HEAD(zero)
#ifdef ASSERT
# loadTx0 が規定値以外なら Assert
addi sys0, loadTx0, -0x33
beq sys0, zero, bgAssert1
addi sys0, loadTx0, (0x100-0xf4)
beq sys0, zero, bgAssert1
nop
jal AssertHandler
bgAssert1:
#endif
lhu tmemSizeW, RSP_INPUT_BG+RSP_BG_TMEMSIZEW(zero)
lhu tmemTH, RSP_INPUT_BG+RSP_BG_TMEMLOADTH(zero)
#ifdef ASSERT
# tmemTH==0 の場合, 初期化ルーチンをコールしていない
# と考えられる. この場合も ASSERT
bne tmemTH, zero, bgAssert2
nop
jal AssertHandler
nop
bgAssert2:
#endif
bgez loadTx0, bgSKIP3
lhu tmemSH, RSP_INPUT_BG+RSP_BG_TMEMLOADSH(zero)
mfc2 tmemSH, tmemSHv[4]
sll tmemSH, tmemSH, 2
addi tmemSH, tmemSH, -1
bgSKIP3:
#
# SetTextureImage の 1st コマンドの作成
#
# +----------+----------+----------+----------+
# | Cmd=0x3d |Fm0|S2| | | line |
# +----------+----------+----------+----------+
# | D R A M address |
# +----------+----------+----------+----------+
#
# line = tmemSizeW*2-1
#
sll setTimg, tmemSizeW, 1 # (tmemSizeW*2-1)
addi setTimg, setTimg, -1
lui sys0, 0x3d10 # SetTimg cmd=0x3d,RGBA16
or setTimg, setTimg, sys0
#
# LoadBlock/LoadTile の 1st コマンドおよび SH,TH 値の作成
#
# +----------+----------+----------+----------+
# | Cmd=0x3? | 0 | 0 |
# +----------+----------+----------+----------+
# | |T=7| SH | TH |
# +----------+----------+----------+----------+
#
# loadTx0 は LoadBlock の時正の値 0x33
# LoadTile の時負の値 0xf4 となる
#
sll loadTx0, loadTx0, 24
ori tmemSH, tmemSH, 0x7000 # LOADTILE=7
sll tmemSH, tmemSH, 12
EndAssign(tmemSHv, v10)
#---------------------------------------------------------------------
# もし Part 1 で処理すべき行数が 0 なら, Part 2 へ
#
# if (line1 <= 0) goto part2;
# count -= line1;
#---------------------------------------------------------------------
#
# 行数のチェック, カウンタの減算
#
blez line1, bgSKIP_PART2
sub count, count, line1
#---------------------------------------------------------------------
# ====== Part 1 開始 ======
#---------------------------------------------------------------------
# 残りのライン数の計算および残りラインが端数となった場合における
# 各ステップ値の変更
#
# do {
# line1 -= tmemH;
# if (line1 < 0){
# tmemH += line1;
# tmemSize += line1 * tmemSizeW;
# }
# frmYH = frmYL + tmemH;
#---------------------------------------------------------------------
bgSKIP_PART1:
Assign(tmemH, 21)
Assign(tmemSize, 29)
Assign(frmYH, 28)
#
# ステップ値の初期化
# バグ対応のためへんてこなコードになっている 不覚!!
#
lhu tmemSize, RSP_INPUT_BG+RSP_BG_TMEMSIZE(zero)
bgez loadTx0, bgSKIP_PART1A
lhu tmemH, RSP_INPUT_BG+RSP_BG_TMEMH(zero)
lhu sys0, RSP_INPUT_BG+RSP_BG_TMEMLOADSH(zero)
sll tmemSize, tmemSize, 16
or tmemSize, tmemSize, sys0
bgSKIP_PART1A:
#
# LoadBlock/LoadTile の 2nd コマンドの作成
#
or loadTx1, tmemSH, tmemTH
#
# 残りライン数の計算 line1 -= tmemH
# および端数チェック
# まだラインが充分に残っているなら Branch
#
bgLoop1: sub line1, line1, tmemH
bgez line1, bgLoop1Skip1
#
# ステップ値の計算
# tmemH += line1;
# tmemSize += line1 * tmemSizeW;
#
Assign(line1vL, v2)
Assign(line1vH, v3)
mtc2 line1, line1vL[2]
vmudn line1vL, tmemSizeWv, line1vL[1] # SL*TH [1]
vmadh line1vH, vzero, _0x0000
ssv line1vL[2], oRSPOBJ_VSCRATCH+2(vecptr)
ssv line1vH[2], oRSPOBJ_VSCRATCH+0(vecptr)
lw sys0, oRSPOBJ_VSCRATCH+0(vecptr)
add tmemH, tmemH, line1
bgez loadTx0, bgLoop1Skip0A
add tmemSize, tmemSize, sys0
EndAssign(line1vL, v2)
EndAssign(line1vH, v3)
#
# コマンドに応じた SH,TH の変更
# LoadBlock の場合, tmemSH = tmemSize/2-1
# LoadTile の場合, tmemTH = tmemH-1
#
#---- LoadTile
addi sys0, tmemH, -1
j bgLoop1Skip1
or loadTx1,tmemSH, sys0
#---- LoadBlock
bgLoop1Skip0A: addi sys0, tmemSize, -2
ori sys0, sys0, 0xe000
sll sys0, sys0, 11
or loadTx1, sys0, tmemTH
#
# 下端の Y 座標計算 frmYH = frmYL + tmemH - 1;
#
bgLoop1Skip1: add frmYH, frmYL, tmemH
addi frmYH, frmYH, -1
#---------------------------------------------------------------------
# RDP コマンドの出力
#
# gDPLoadSync((*glistp) ++);
# gDPSetTextureImage((*glistp) ++,
# G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, imagePtr);
# gDPLoadBlock((*glistp) ++,
# G_TX_LOADTILE, 0, 0, tmsize, tmemStride);
# gDPPipeSync((*glistp) ++);
# gSPTextureRectangle((*glistp) ++, frmXL, frmYL, frmXH, frmYH,
# G_TX_RENDERTILE, tmemS, 0, 1024<<2, 1024);
#---------------------------------------------------------------------
# LoadSync
sbv _LOADSYNC, 0(outp) # RDP cmd 前半設定
# SetTImg
sw setTimg, 8(outp)
sw imagePtr, 12(outp)
# LoadBlock/LoadTile
sw loadTx0, 16(outp)
sw loadTx1, 20(outp)
# PipeSync
sbv _PIPESYNC, 24(outp)
# TextureRectangle
or sys0, frmXH, frmYH
sw sys0, 32(outp)
or sys0, frmXL, frmYL
sw sys0, 36(outp)
slv tmemSv[0], 40(outp)
slv _COPYMODESCALE, 44(outp)
jal OutputClose
addi outp, outp, 48
#---------------------------------------------------------------------
# frmYL = frmYH + 1;
# imagePtr += tmemSize;
# } while (line1 > 0);
# if (count <= 0) return;
# }
#---------------------------------------------------------------------
addi frmYL, frmYH, 1
bgtz line1, bgLoop1
add imagePtr, imagePtr, tmemSize
blez count, GfxDone
# nop # (*) 次命令の移動により不要となる
EndAssign(tmemH, 21)
EndAssign(tmemSize, 29)
EndAssign(frmYH, 28)
bgSKIP_PART2:
#---------------------------------------------------------------------
# 端数部のロード及び描画
#
# /* Part 2,3 の処理 */
# if (imgXT > 0){
#
# もし端数部があるなら Part2,3 の処理を行なう.
# 端数が 0 なら Part4 へ飛ぶ
#---------------------------------------------------------------------
#
# 前命令の nop を消去するために移動させる (*)印
#
# blez imgXT, bgSKIP_PART4 # (*)
#---------------------------------------------------------------------
# ====== Part 2 開始 ======
#---------------------------------------------------------------------
# まず残った部分のロードを行なう
#
# gDPLoadSync((*glistp) ++);
# gDPSetTextureImage((*glistp) ++,
# G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, imagePtr);
# gDPSetTile((*glistp) ++, G_IM_FMT_RGBA, G_IM_SIZ_16b,
# 0, 0, G_TX_LOADTILE-1, 0, 0, 0, 0, 0, 0, 0);
# gDPLoadBlock((*glistp) ++,
# G_TX_LOADTILE-1, 0, 0, tmemW-imgXT, 0);
# gDPPipeSync((*glistp) ++);
#
#---------------------------------------------------------------------
Assign(length, 21)
Assign(loadhead, 29)
#
# LoadSync コマンドの出力
# 分岐遅延内で outp へ出力しているが outp
# を増加させなければ問題なし
#
sbv _LOADSYNC, 0(outp)
blez imgXT, bgSKIP_PART4 # (*)
#
# SetTextureImage コマンドの出力
#
sw setTimg, 8(outp)
sw imagePtr, 12(outp)
#
# SetTile (LOADTILE-1) コマンドの出力
#
lui sys0, 0x3510
sw sys0, 16(outp) # CMD.0=0x35100000
lui sys1, 0x0600
sw sys1, 20(outp) # CMD.1=(G_TX_LOADTILE-1)<<24
#
# LoadBlock コマンドの出力
#
# +----------+----------+----------+----------+
# | Cmd=0x33 | 0 | 0 |
# +----------+----------+----------+----------+
# | |T=6| Word数*4-1 | 0 |
# +----------+----------+----------+----------+
# ここでは, 常に image 1行分をロードする
# そのため LoadBlock を使用する.
#
# ロードするのは 1 行分なので DxT は 0 で良い.
# Word数=(tmemSizeW/2-imgXT/2) を求める. この値は
# 後に使用する. (= Part3 のロード先 TMEM 位置)
# 4 倍し 1 を減ずる.
#
lui loadhead, 0x3300
sw loadhead, 24(outp)
srl imgXT, imgXT, 1
srl length, tmemSizeW, 1
sub length, length, imgXT
sll sys0, length, 14
addi sys0, sys0, -0x1000
or sys0, sys0, sys1
sw sys0, 28(outp)
#
# PipeSync コマンドの出力
#
sbv _PIPESYNC, 32(outp)
EndAssign(tmemSizeW, 13)
#---------------------------------------------------------------------
# ====== Part 3 開始 ======
#---------------------------------------------------------------------
# 1 行分のデータに足りない分を image 先頭からロードし, TMEM 内で合成
# する.
#
# gDPSetTextureImage((*glistp) ++,
# G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, imageOrg);
# gDPSetTile((*glistp) ++, G_IM_FMT_RGBA, G_IM_SIZ_16b,
# 0, tmemW-imgXT, G_TX_LOADTILE-1, 0, 0, 0, 0, 0, 0, 0);
# gDPLoadBlock((*glistp) ++,
# G_TX_LOADTILE-1, 0, 0, imgXT, 0);
#---------------------------------------------------------------------
#
# SetTextureImage コマンドの出力
#
sw setTimg, 40(outp)
sw imageOrg, 44(outp)
#
# SetTile (LOADTILE-1) コマンドの出力
#
lui sys0, 0x3510
sw sys0, 48(outp) # CMD.0=0x35100000
sh length, 50(outp)
lui sys1, 0x0600
sw sys1, 52(outp) # CMD.1=(G_TX_LOADTILE-1)<<24
#
# LoadBlock (LOADTILE-1) コマンドの出力
#
sw loadhead, 56(outp)
sll sys0, imgXT, 14 # word から pixel に変換
addi sys0, sys0, -0x1000
or sys0, sys0, sys1
sw sys0, 60(outp)
EndAssign(length, 21)
EndAssign(loadhead, 29)
#---------------------------------------------------------------------
# 1 行分を描画する
# COPYMODE なので frmYH = frmYL でも問題なし
#
# gDPPipeSync((*glistp) ++);
# gSPTextureRectangle((*glistp) ++, frmXL, frmYL, frmXH, frmYL,
# G_TX_RENDERTILE, tmemS, 0, 1024<<2, 1024);
#---------------------------------------------------------------------
# outp 加算
addi outp, outp, 88
# PipeSync
sbv _PIPESYNC, 64-88(outp)
#
# TextureRectangle コマンド前半
#
or sys0, frmXH, frmYL
sw sys0, 72-88(outp)
or sys0, frmXL, frmYL
sw sys0, 76-88(outp)
#
# TextureRectangle コマンド後半
#
slv tmemSv[0], 80-88(outp)
jal OutputClose
slv _COPYMODESCALE, 84-88(outp)
#---------------------------------------------------------------------
# カウンタ類加算, 終了判定
#
# frmYL = frmYL + 4;
# count -= 4;
# if (count <= 0) return;
# }
#---------------------------------------------------------------------
#
# frmYL = frmYL + 1;
#
addi frmYL, frmYL, 4
#
# count -= 4;
# if (count <= 0) return;
#
addi count, count, -4
blez count, GfxDone
bgSKIP_PART4:
#---------------------------------------------------------------------
# ====== Part 4 開始 ======
#---------------------------------------------------------------------
# image ソースデータの取得
#---------------------------------------------------------------------
#
# image += imgXT * 8;
#
sll sys0, imgXT, 3
add imagePtr, imageOrg, sys0
EndAssign(imgXT, 7)
EndAssign(imageOrg, 3)
#---------------------------------------------------------------------
# 残りラインを一気に処理する
# 処理ライン数を残っているライン数にし, 残りライン数を 0 にする.
# その後 Part1 の呼び出し.
#---------------------------------------------------------------------
_mov (line1, count)
j bgSKIP_PART1
_li (count, 0)
EndAssign(count, 1)
EndAssign(line1, 4)
EndAssign(tmemSH, 5)
EndAssign(tmemTH, 6)
EndAssign(imagePtr, 2)
EndAssign(sptr, 20)
EndAssign(setTimg, 14)
EndAssign(loadTx0, 15)
EndAssign(loadTx1, 16)
EndAssign(frmXL, 8)
EndAssign(frmXH, 10)
EndAssign(frmYL, 9)
EndAssign(tmemSizeWv, v6)
EndAssign(tmemSv, v8)
/*======== End of gs2bg.s ========*/