1+ using System . Drawing ;
2+
3+ using f3dzex2 . combiner ;
4+ using f3dzex2 . displaylist . opcodes ;
5+ using f3dzex2 . image ;
6+ using f3dzex2 . io ;
7+
8+ using fin . math ;
9+ using fin . model ;
10+
11+ using marioartist . schema . talent_studio ;
12+
13+ using OneOf ;
14+
15+ namespace marioartist . api ;
16+
17+ public static class JankTstltUtil {
18+ public static void ResetRspAndRdp ( IN64Hardware n64Hardware ) {
19+ // TODO: The way these are reset in the original game is actually really, really, really complicated
20+ var rsp = n64Hardware . Rsp ;
21+ rsp . UvType = N64UvType . LINEAR ;
22+ rsp . EnvironmentColor = Color . White ;
23+ rsp . PrimColor = Color . White ;
24+
25+ var rdp = n64Hardware . Rdp ;
26+ rdp . ForceBlending = false ;
27+ rdp . P0 = BlenderPm . G_BL_CLR_MEM ;
28+ rdp . A0 = BlenderA . G_BL_0 ;
29+ rdp . M0 = BlenderPm . G_BL_CLR_IN ;
30+ rdp . B0 = BlenderB . G_BL_1 ;
31+ rdp . P1 = BlenderPm . G_BL_CLR_MEM ;
32+ rdp . A1 = BlenderA . G_BL_0 ;
33+ rdp . M1 = BlenderPm . G_BL_CLR_IN ;
34+ rdp . B1 = BlenderB . G_BL_1 ;
35+ rdp . CycleType = CycleType . TWO_CYCLE ;
36+
37+ rdp . UseCoverageForAlpha = true ;
38+ }
39+
40+ public static void SetAdditiveBlending ( IN64Hardware n64Hardware ) {
41+ var rsp = n64Hardware . Rsp ;
42+ rsp . UvType = N64UvType . LINEAR ;
43+ rsp . UvType = N64UvType . STANDARD ;
44+ rsp . EnvironmentColor = Color . White ;
45+ rsp . PrimColor = Color . White ;
46+
47+ var rdp = n64Hardware . Rdp ;
48+ rdp . ForceBlending = true ;
49+ rdp . P0 = BlenderPm . G_BL_CLR_MEM ;
50+ rdp . A0 = BlenderA . G_BL_A_IN ;
51+ rdp . M0 = BlenderPm . G_BL_CLR_IN ;
52+ rdp . B0 = BlenderB . G_BL_1MA ;
53+ rdp . P1 = BlenderPm . G_BL_CLR_MEM ;
54+ rdp . A1 = BlenderA . G_BL_A_IN ;
55+ rdp . M1 = BlenderPm . G_BL_CLR_IN ;
56+ rdp . B1 = BlenderB . G_BL_1MA ;
57+ rdp . CycleType = CycleType . TWO_CYCLE ;
58+
59+ rdp . UseCoverageForAlpha = false ;
60+ }
61+
62+ public static void SetCombiner (
63+ IN64Hardware n64Hardware ,
64+ bool withTexture0 ,
65+ bool withAlpha ,
66+ OneOf < uint , Color > ? patternSegmentedOffsetOrColor = null ,
67+ PatternMaterialType patternMaterialType = PatternMaterialType . BLEND_1X1 ) {
68+ var rdp = n64Hardware . Rdp ;
69+ var rsp = n64Hardware . Rsp ;
70+
71+ // Based on decomp, early in function at 0x801150e8
72+ rsp . PrimLodFraction = 1f * 0x7f / 0x100 ;
73+
74+ ushort shift = patternMaterialType switch {
75+ PatternMaterialType . BLEND_2X2
76+ or PatternMaterialType . MULTIPLY_2X2 => 0xf ,
77+ _ => 0 ,
78+ } ;
79+
80+ rsp . UvType = patternMaterialType == PatternMaterialType . SPHERICAL
81+ ? N64UvType . SPHERICAL
82+ : N64UvType . STANDARD ;
83+ rdp . Tmem . GsSpTexture ( BitLogic . ConvertDoubleToBinaryFraction ( 1 ) ,
84+ BitLogic . ConvertDoubleToBinaryFraction ( 1 ) ,
85+ 0 ,
86+ TileDescriptorIndex . TX_LOADTILE ,
87+ withTexture0
88+ ? TileDescriptorState . ENABLED
89+ : TileDescriptorState . DISABLED ) ;
90+
91+ switch ( withTexture0 , patternSegmentedOffsetOrColor ) {
92+ case ( true , not null ) : {
93+ if ( patternSegmentedOffsetOrColor . Value . TryPickT0 (
94+ out var patternSegmentedOffset ,
95+ out var color ) ) {
96+ rdp . Tmem . SetImageSimple (
97+ patternSegmentedOffset ,
98+ N64ColorFormat . RGBA ,
99+ BitsPerTexel . _16BPT ,
100+ 32 ,
101+ 32 ,
102+ F3dWrapMode . REPEAT ,
103+ F3dWrapMode . REPEAT ,
104+ 1 ,
105+ shift ) ;
106+
107+ rdp . SetCombinerCycleParams (
108+ FromBlendingTexture0AndTexture1WithEnvColorAndShade (
109+ patternMaterialType ,
110+ withAlpha ) ) ;
111+
112+ // From decomp, 0x801162a4 onwards
113+ var ( envValue , envAlpha ) = patternMaterialType switch {
114+ PatternMaterialType . BLEND_1X1
115+ or PatternMaterialType . BLEND_2X2 => ( 0xc8 , 0xff ) ,
116+ PatternMaterialType . MULTIPLY_1X1
117+ or PatternMaterialType . MULTIPLY_2X2 => ( 0xd7 , 0xff ) ,
118+ PatternMaterialType . SPHERICAL => ( 0xff , 0x30 ) ,
119+ } ;
120+ rsp . EnvironmentColor = Color . FromArgb ( envAlpha ,
121+ envValue ,
122+ envValue ,
123+ envValue ) ;
124+ } else {
125+ rdp . SetCombinerCycleParams (
126+ CombinerCycleParams
127+ . FromTexture0AndLightingAndPrimitive ( withAlpha ) ) ;
128+ rsp . PrimColor = color ;
129+ }
130+
131+ break ;
132+ }
133+ case ( true , null ) : {
134+ rdp . SetCombinerCycleParams (
135+ CombinerCycleParams . FromTexture0AndShade ( withAlpha ) ) ;
136+ break ;
137+ }
138+ case ( false , not null ) : {
139+ if ( patternSegmentedOffsetOrColor . Value . TryPickT0 (
140+ out var patternSegmentedOffset ,
141+ out var color ) ) {
142+ rdp . Tmem . SetImageSimple (
143+ patternSegmentedOffset ,
144+ N64ColorFormat . RGBA ,
145+ BitsPerTexel . _16BPT ,
146+ 32 ,
147+ 32 ,
148+ F3dWrapMode . REPEAT ,
149+ F3dWrapMode . REPEAT ,
150+ 0 ,
151+ shift ) ;
152+
153+ rdp . SetCombinerCycleParams (
154+ CombinerCycleParams . FromTexture0AndShade ( withAlpha ) ) ;
155+ } else {
156+ rdp . SetCombinerCycleParams (
157+ CombinerCycleParams . FromPrimitiveAndLighting ( withAlpha ) ) ;
158+ rsp . PrimColor = color ;
159+ }
160+
161+ break ;
162+ }
163+ default : {
164+ rdp . SetCombinerCycleParams (
165+ CombinerCycleParams . FromTexture0AndShade ( withAlpha ) ) ;
166+ break ;
167+ }
168+ }
169+ }
170+
171+ // From decomp, 0x801162a4 onwards
172+ public static ( CombinerCycleParams , CombinerCycleParams )
173+ FromBlendingTexture0AndTexture1WithEnvColorAndShade (
174+ PatternMaterialType patternMaterialType ,
175+ bool withAlpha )
176+ => ( patternMaterialType switch {
177+ PatternMaterialType . BLEND_1X1 or PatternMaterialType . BLEND_2X2 =>
178+ new ( ) {
179+ ColorMuxA = GenericColorMux . G_CCMUX_TEXEL1 ,
180+ ColorMuxB = GenericColorMux . G_CCMUX_ENVIRONMENT ,
181+ ColorMuxC = GenericColorMux . G_CCMUX_TEXEL0 ,
182+ ColorMuxD = GenericColorMux . G_CCMUX_TEXEL0 ,
183+ AlphaMuxA = GenericAlphaMux . G_ACMUX_0 ,
184+ AlphaMuxB = GenericAlphaMux . G_ACMUX_0 ,
185+ AlphaMuxC = GenericAlphaMux . G_ACMUX_0 ,
186+ AlphaMuxD = withAlpha
187+ ? GenericAlphaMux . G_ACMUX_TEXEL0
188+ : GenericAlphaMux . G_ACMUX_1 ,
189+ } ,
190+ PatternMaterialType . MULTIPLY_1X1
191+ or PatternMaterialType . MULTIPLY_2X2 =>
192+ new ( ) {
193+ ColorMuxA = GenericColorMux . G_CCMUX_TEXEL1 ,
194+ ColorMuxB = GenericColorMux . G_CCMUX_ENVIRONMENT ,
195+ ColorMuxC = GenericColorMux . G_CCMUX_PRIM_LOD_FRAC ,
196+ ColorMuxD = GenericColorMux . G_CCMUX_TEXEL0 ,
197+ AlphaMuxA = GenericAlphaMux . G_ACMUX_0 ,
198+ AlphaMuxB = GenericAlphaMux . G_ACMUX_0 ,
199+ AlphaMuxC = GenericAlphaMux . G_ACMUX_0 ,
200+ AlphaMuxD = withAlpha
201+ ? GenericAlphaMux . G_ACMUX_TEXEL0
202+ : GenericAlphaMux . G_ACMUX_1 ,
203+ } ,
204+ PatternMaterialType . SPHERICAL =>
205+ new ( ) {
206+ ColorMuxA = GenericColorMux . G_CCMUX_1 ,
207+ ColorMuxB = GenericColorMux . G_CCMUX_TEXEL1 ,
208+ ColorMuxC = GenericColorMux . G_CCMUX_ENV_ALPHA ,
209+ ColorMuxD = GenericColorMux . G_CCMUX_TEXEL1 ,
210+ AlphaMuxA = GenericAlphaMux . G_ACMUX_0 ,
211+ AlphaMuxB = GenericAlphaMux . G_ACMUX_0 ,
212+ AlphaMuxC = GenericAlphaMux . G_ACMUX_0 ,
213+ AlphaMuxD = withAlpha
214+ ? GenericAlphaMux . G_ACMUX_TEXEL0
215+ : GenericAlphaMux . G_ACMUX_1 ,
216+ } ,
217+ } ,
218+ new ( ) {
219+ ColorMuxA = GenericColorMux . G_CCMUX_COMBINED ,
220+ ColorMuxB = GenericColorMux . G_CCMUX_0 ,
221+ ColorMuxC = GenericColorMux . G_CCMUX_SHADE ,
222+ ColorMuxD = GenericColorMux . G_CCMUX_0 ,
223+ AlphaMuxA = GenericAlphaMux . G_ACMUX_0 ,
224+ AlphaMuxB = GenericAlphaMux . G_ACMUX_0 ,
225+ AlphaMuxC = GenericAlphaMux . G_ACMUX_0 ,
226+ AlphaMuxD = GenericAlphaMux . G_ACMUX_COMBINED ,
227+ } ) ;
228+
229+ public static CullingMode GetCullingModeForMeshSetId ( uint meshSetId )
230+ => meshSetId switch {
231+ // HACK: Disables culling for glasses
232+ 8 => CullingMode . SHOW_BOTH ,
233+ // HACK: Disables culling for head accessories
234+ 10 => CullingMode . SHOW_BOTH ,
235+ // By default, only shows front face
236+ _ => CullingMode . SHOW_FRONT_ONLY ,
237+ } ;
238+
239+ public static CullingMode GetCullingModeForChosenPartId ( int chosenPartId )
240+ => chosenPartId switch {
241+ // HACK: Disables culling for hats
242+ 3 => CullingMode . SHOW_BOTH ,
243+ // HACK: Disables culling for accessories worn on back
244+ 6 => CullingMode . SHOW_BOTH ,
245+ // By default, only shows front face
246+ _ => CullingMode . SHOW_FRONT_ONLY ,
247+ } ;
248+
249+ public static void SetCombinerForPattern (
250+ IN64Hardware n64Hardware ,
251+ ChosenPart0 chosenPart0 ,
252+ int patternI ,
253+ bool withTexture ) {
254+ if ( ! ( patternI is 1 or 2 or 3 ) ) {
255+ return ;
256+ }
257+
258+ var isMark = patternI == 2 ;
259+ SetCombiner ( n64Hardware ,
260+ withTexture ,
261+ isMark ,
262+ OneOf < uint , Color > . FromT0 (
263+ patternI switch {
264+ 1 => chosenPart0 . Pattern0Params . ImageSegmentedAddress ,
265+ 2 => chosenPart0 . Pattern1Params . ImageSegmentedAddress ,
266+ 3 => chosenPart0 . MarkParams . ImageSegmentedAddress ,
267+ } ) ,
268+ patternI switch {
269+ 1 => chosenPart0 . Pattern0Params . MaterialType ,
270+ 2 => chosenPart0 . Pattern1Params . MaterialType ,
271+ 3 => PatternMaterialType . BLEND_1X1 ,
272+ } ) ;
273+
274+ if ( isMark ) {
275+ SetAdditiveBlending ( n64Hardware ) ;
276+ }
277+ }
278+ }
0 commit comments