@@ -139,46 +139,92 @@ void MODEL2_FUNC_NAME(int32_t scanline, const extent_t& extent, const m2_poly_ex
139
139
float dvoz = extent.param [2 ].dpdx ;
140
140
int x;
141
141
142
- tex_x_mask = (tex_mirr_x ? ( tex_width * 2 ) : tex_width) - 1 ;
143
- tex_y_mask = (tex_mirr_y ? ( tex_height * 2 ) : tex_height) - 1 ;
142
+ tex_x_mask = tex_width - 1 ;
143
+ tex_y_mask = tex_height - 1 ;
144
144
145
145
colorbase = state->m_palram [(colorbase + 0x1000 )] & 0x7fff ;
146
146
147
147
colortable_r += ((colorbase >> 0 ) & 0x1f ) << 8 ;
148
148
colortable_g += ((colorbase >> 5 ) & 0x1f ) << 8 ;
149
149
colortable_b += ((colorbase >> 10 ) & 0x1f ) << 8 ;
150
150
151
- for (x = extent.startx ; x < extent.stopx ; x++, uoz += duoz, voz += dvoz, ooz += dooz)
151
+ for (x = extent.startx ; x < extent.stopx ; x++, uoz += duoz, voz += dvoz, ooz += dooz)
152
152
{
153
153
float z = recip_approx (ooz) * 256 .0f ;
154
154
int32_t u = uoz * z;
155
155
int32_t v = voz * z;
156
156
int tr, tg, tb;
157
- u16 t;
157
+ u32 t, tex1, tex2, tex3, tex4, frac1, frac2, frac3, frac4;
158
+ #if defined(MODEL2_TRANSLUCENT)
159
+ u32 alp, alp1, alp2, alp3, alp4;
160
+ #endif
158
161
u8 luma;
159
- int u2;
160
- int v2;
162
+ int u2, u2n ;
163
+ int v2, v2n ;
161
164
162
165
#if defined(MODEL2_CHECKER)
163
- if ( ((x^ scanline) & 1 ) == 0 )
166
+ if (((x ^ scanline) & 1 ) == 0 )
164
167
continue ;
165
168
#endif
166
- u2 = (u >> 8 ) & tex_x_mask;
167
- v2 = (v >> 8 ) & tex_y_mask;
168
-
169
- if (tex_mirr_x && u2 >= tex_width)
170
- u2 = (tex_width * 2 - 1 ) - u2;
171
-
172
- if (tex_mirr_y && v2 >= tex_height)
173
- v2 = (tex_height * 2 - 1 ) - v2;
174
-
175
- t = get_texel ( tex_x, tex_y, u2, v2, sheet );
176
-
169
+ u2 = u >> 8 ;
170
+ v2 = v >> 8 ;
171
+
172
+ if (tex_mirr_x && ((u2 & tex_width) != 0 )) // Only flip if even number of tilings
173
+ {
174
+ u2 = (u2 ^ tex_x_mask) & tex_x_mask;
175
+ u2n = std::max (0 , u2 - 1 ); // Ensure sample is inside texture
176
+ }
177
+ else
178
+ {
179
+ u2 &= tex_x_mask;
180
+ u2n = std::min (u2 + 1 , (int ) tex_x_mask); // Ensure sample is inside texture
181
+ }
182
+ if (tex_mirr_y && ((v2 & tex_height) != 0 )) // Only flip if even number of tilings
183
+ {
184
+ v2 = (v2 ^ tex_y_mask) & tex_y_mask;
185
+ v2n = std::max (0 , v2 - 1 ); // Ensure sample is inside texture
186
+ }
187
+ else
188
+ {
189
+ v2 &= tex_y_mask;
190
+ v2n = std::min (v2 + 1 , (int ) tex_y_mask); // Ensure sample is inside texture
191
+ }
192
+
193
+ frac1 = u & 0xFF ;
194
+ frac2 = 0x100 - frac1;
195
+ frac3 = v & 0xFF ;
196
+ frac4 = 0x100 - frac3;
197
+ tex1 = get_texel (tex_x, tex_y, u2, v2, sheet);
198
+ tex2 = get_texel (tex_x, tex_y, u2n, v2, sheet);
199
+ tex3 = get_texel (tex_x, tex_y, u2, v2n, sheet);
200
+ tex4 = get_texel (tex_x, tex_y, u2n, v2n, sheet);
177
201
#if defined(MODEL2_TRANSLUCENT)
178
- if ( t == 0x0f )
202
+ alp1 = (tex1 + 1 ) >> 4 ;
203
+ alp2 = (tex2 + 1 ) >> 4 ;
204
+ alp3 = (tex3 + 1 ) >> 4 ;
205
+ alp4 = (tex4 + 1 ) >> 4 ;
206
+ alp = alp1 * frac2 * frac4 + alp2 * frac1 * frac4 + alp3 * frac2 * frac3 + alp4 * frac1 * frac3;
207
+ if ( alp >= 0x8000 )
179
208
continue ;
209
+ // Anti Alpha Highlighted Edges
210
+ tex1 &= alp1 - 1 ;
211
+ tex2 &= alp2 - 1 ;
212
+ tex3 &= alp3 - 1 ;
213
+ tex4 &= alp4 - 1 ;
214
+ u32 maxValidTex = std::max (std::max (std::max (tex1, tex2), tex3), tex4);
215
+ if (alp1)
216
+ tex1 = maxValidTex;
217
+ if (alp2)
218
+ tex2 = maxValidTex;
219
+ if (alp3)
220
+ tex3 = maxValidTex;
221
+ if (alp4)
222
+ tex4 = maxValidTex;
180
223
#endif
181
- luma = (u32 )lumaram[lumabase + (t << 3 )] * object.luma / 256 ;
224
+ t = tex1 * frac2 * frac4 + tex2 * frac1 * frac4 + tex3 * frac2 * frac3 + tex4 * frac1 * frac3;
225
+
226
+ // Bilinear combination has 16 bits of precision, and the table needs t to be shifted by 3 on the left
227
+ luma = (u32 )lumaram[lumabase + (t >> 13 )] * object.luma / 256 ;
182
228
183
229
// Virtua Striker sets up a luma of 0x40 for national flags on bleachers, fix here.
184
230
luma = std::min ((int )luma,0x3f );
0 commit comments