| 1 | /* |
| 2 | * Glide64 - Glide video plugin for Nintendo 64 emulators. |
| 3 | * Copyright (c) 2002 Dave2001 |
| 4 | * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | * any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with this program; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ |
| 20 | |
| 21 | //**************************************************************** |
| 22 | // |
| 23 | // Glide64 - Glide Plugin for Nintendo 64 emulators |
| 24 | // Project started on December 29th, 2001 |
| 25 | // |
| 26 | // Authors: |
| 27 | // Dave2001, original author, founded the project in 2001, left it in 2002 |
| 28 | // Gugaman, joined the project in 2002, left it in 2002 |
| 29 | // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 |
| 30 | // Hiroshi 'KoolSmoky' Morii, joined the project in 2007 |
| 31 | // |
| 32 | //**************************************************************** |
| 33 | // |
| 34 | // To modify Glide64: |
| 35 | // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. |
| 36 | // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. |
| 37 | // |
| 38 | //**************************************************************** |
| 39 | // |
| 40 | // January 2004 Created by Gonetz (Gonetz@ngs.ru) |
| 41 | // |
| 42 | //**************************************************************** |
| 43 | |
| 44 | wxUint32 uc8_normale_addr = 0; |
| 45 | float uc8_coord_mod[16]; |
| 46 | |
| 47 | static void uc8_vertex () |
| 48 | { |
| 49 | Check_FrameSkip; |
| 50 | |
| 51 | if (rdp.update & UPDATE_MULT_MAT) |
| 52 | { |
| 53 | rdp.update ^= UPDATE_MULT_MAT; |
| 54 | MulMatrices(rdp.model, rdp.proj, rdp.combined); |
| 55 | } |
| 56 | |
| 57 | wxUint32 addr = segoffset(rdp.cmd1); |
| 58 | int v0, i, n; |
| 59 | float x, y, z; |
| 60 | |
| 61 | rdp.vn = n = (rdp.cmd0 >> 12) & 0xFF; |
| 62 | rdp.v0 = v0 = ((rdp.cmd0 >> 1) & 0x7F) - n; |
| 63 | |
| 64 | FRDP ("uc8:vertex n: %d, v0: %d, from: %08lx\n", n, v0, addr); |
| 65 | |
| 66 | if (v0 < 0) |
| 67 | { |
| 68 | RDP_E ("** ERROR: uc2:vertex v0 < 0\n"); |
| 69 | LRDP("** ERROR: uc2:vertex v0 < 0\n"); |
| 70 | return; |
| 71 | } |
| 72 | //* |
| 73 | // This is special, not handled in update() |
| 74 | if (rdp.update & UPDATE_LIGHTS) |
| 75 | { |
| 76 | rdp.update ^= UPDATE_LIGHTS; |
| 77 | |
| 78 | // Calculate light vectors |
| 79 | for (wxUint32 l=0; l<rdp.num_lights; l++) |
| 80 | { |
| 81 | InverseTransformVector(&rdp.light[l].dir_x, rdp.light_vector[l], rdp.model); |
| 82 | NormalizeVector (rdp.light_vector[l]); |
| 83 | #ifdef EXTREME_LOGGING |
| 84 | FRDP("light_vector[%d] x: %f, y: %f, z: %f\n", l, rdp.light_vector[l][0], rdp.light_vector[l][1], rdp.light_vector[l][2]); |
| 85 | #endif |
| 86 | } |
| 87 | } |
| 88 | //*/ |
| 89 | #ifdef __ARM_NEON__ |
| 90 | float32x4_t comb0, comb1, comb2, comb3; |
| 91 | float32x4_t v_xyzw; |
| 92 | comb0 = vld1q_f32(rdp.combined[0]); |
| 93 | comb1 = vld1q_f32(rdp.combined[1]); |
| 94 | comb2 = vld1q_f32(rdp.combined[2]); |
| 95 | comb3 = vld1q_f32(rdp.combined[3]); |
| 96 | |
| 97 | float32x4_t uc8_8_11, uc8_12_15; |
| 98 | uc8_8_11 = vld1q_f32(uc8_coord_mod+8); |
| 99 | uc8_12_15 = vld1q_f32(uc8_coord_mod+12); |
| 100 | float32x4_t unite={1.0f, 1.0f, 1.0f, 1.0f}; |
| 101 | |
| 102 | float32x4_t rdplight[12], rdpcolor[12]; |
| 103 | for (i=0; i<rdp.num_lights; i++) { |
| 104 | rdplight[i] = vld1q_f32(&rdp.light[i].x); |
| 105 | rdpcolor[i] = vld1q_f32(&rdp.light[i].r); |
| 106 | } |
| 107 | |
| 108 | #endif |
| 109 | for (i=0; i < (n<<4); i+=16) |
| 110 | { |
| 111 | VERTEX *v = &rdp.vtx[v0 + (i>>4)]; |
| 112 | x = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 0)^1]; |
| 113 | y = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 1)^1]; |
| 114 | z = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 2)^1]; |
| 115 | v->flags = ((wxUint16*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1]; |
| 116 | v->ou = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1]; |
| 117 | v->ov = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1]; |
| 118 | v->uv_scaled = 0; |
| 119 | v->a = ((wxUint8*)gfx.RDRAM)[(addr+i + 15)^3]; |
| 120 | |
| 121 | #ifdef EXTREME_LOGGING |
| 122 | FRDP ("before v%d - x: %f, y: %f, z: %f\n", i>>4, x, y, z); |
| 123 | #endif |
| 124 | #ifdef __ARM_NEON__ |
| 125 | v_xyzw = x*comb0+y*comb1+z*comb2+comb3; |
| 126 | //vst1q_f32((float*)v, v_xyzw); |
| 127 | #else |
| 128 | v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0]; |
| 129 | v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1]; |
| 130 | v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2]; |
| 131 | v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3]; |
| 132 | #endif |
| 133 | |
| 134 | #ifdef EXTREME_LOGGING |
| 135 | FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f, flags: %d\n", i>>4, v->x, v->y, v->z, v->w, v->ou, v->ov, v->flags); |
| 136 | #endif |
| 137 | v->uv_calculated = 0xFFFFFFFF; |
| 138 | v->screen_translated = 0; |
| 139 | v->shade_mod = 0; |
| 140 | #ifdef __ARM_NEON__ |
| 141 | v->x=v_xyzw[0]; |
| 142 | v->y=v_xyzw[1]; |
| 143 | v->z=v_xyzw[2]; |
| 144 | v->w=v_xyzw[3]; |
| 145 | #endif |
| 146 | |
| 147 | ///* |
| 148 | v->r = ((wxUint8*)gfx.RDRAM)[(addr+i + 12)^3]; |
| 149 | v->g = ((wxUint8*)gfx.RDRAM)[(addr+i + 13)^3]; |
| 150 | v->b = ((wxUint8*)gfx.RDRAM)[(addr+i + 14)^3]; |
| 151 | |
| 152 | if (fabs(v->w) < 0.001) v->w = 0.001f; |
| 153 | v->oow = 1.0f / v->w; |
| 154 | #ifdef __ARM_NEON__ |
| 155 | v_xyzw *= v->oow; |
| 156 | v->x_w=v_xyzw[0]; |
| 157 | v->y_w=v_xyzw[1]; |
| 158 | v->z_w=v_xyzw[2]; |
| 159 | #else |
| 160 | v->x_w = v->x * v->oow; |
| 161 | v->y_w = v->y * v->oow; |
| 162 | v->z_w = v->z * v->oow; |
| 163 | #endif |
| 164 | |
| 165 | v->scr_off = 0; |
| 166 | if (v->x < -v->w) v->scr_off |= 1; |
| 167 | if (v->x > v->w) v->scr_off |= 2; |
| 168 | if (v->y < -v->w) v->scr_off |= 4; |
| 169 | if (v->y > v->w) v->scr_off |= 8; |
| 170 | if (v->w < 0.1f) v->scr_off |= 16; |
| 171 | #ifdef EXTREME_LOGGING |
| 172 | FRDP ("r: %02lx, g: %02lx, b: %02lx, a: %02lx\n", v->r, v->g, v->b, v->a); |
| 173 | #endif |
| 174 | |
| 175 | if ((rdp.geom_mode & 0x00020000)) |
| 176 | { |
| 177 | wxUint32 shift = v0 << 1; |
| 178 | v->vec[0] = ((char*)gfx.RDRAM)[(uc8_normale_addr + (i>>3) + shift + 0)^3]; |
| 179 | v->vec[1] = ((char*)gfx.RDRAM)[(uc8_normale_addr + (i>>3) + shift + 1)^3]; |
| 180 | v->vec[2] = (char)(v->flags&0xff); |
| 181 | |
| 182 | if (rdp.geom_mode & 0x80000) |
| 183 | { |
| 184 | calc_linear (v); |
| 185 | #ifdef EXTREME_LOGGING |
| 186 | FRDP ("calc linear: v%d - u: %f, v: %f\n", i>>4, v->ou, v->ov); |
| 187 | #endif |
| 188 | } |
| 189 | else if (rdp.geom_mode & 0x40000) |
| 190 | { |
| 191 | calc_sphere (v); |
| 192 | #ifdef EXTREME_LOGGING |
| 193 | FRDP ("calc sphere: v%d - u: %f, v: %f\n", i>>4, v->ou, v->ov); |
| 194 | #endif |
| 195 | } |
| 196 | // FRDP("calc light. r: 0x%02lx, g: 0x%02lx, b: 0x%02lx, nx: %.3f, ny: %.3f, nz: %.3f\n", v->r, v->g, v->b, v->vec[0], v->vec[1], v->vec[2]); |
| 197 | FRDP("v[%d] calc light. r: 0x%02lx, g: 0x%02lx, b: 0x%02lx\n", i>>4, v->r, v->g, v->b); |
| 198 | #ifdef __ARM_NEON__ |
| 199 | float32x4_t color = {rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b, 1.0f}; |
| 200 | #else |
| 201 | float color[3] = {rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b}; |
| 202 | #endif |
| 203 | FRDP("ambient light. r: %f, g: %f, b: %f\n", color[0], color[1], color[2]); |
| 204 | float light_intensity = 0.0f; |
| 205 | wxUint32 l; |
| 206 | if (rdp.geom_mode & 0x00400000) |
| 207 | { |
| 208 | NormalizeVector (v->vec); |
| 209 | for (l = 0; l < rdp.num_lights-1; l++) |
| 210 | { |
| 211 | if (!rdp.light[l].nonblack) |
| 212 | continue; |
| 213 | light_intensity = DotProduct (rdp.light_vector[l], v->vec); |
| 214 | FRDP("light %d, intensity : %f\n", l, light_intensity); |
| 215 | if (light_intensity < 0.0f) |
| 216 | continue; |
| 217 | //* |
| 218 | if (rdp.light[l].ca > 0.0f) |
| 219 | { |
| 220 | #ifdef __ARM_NEON__ |
| 221 | float32x4_t vxyzw = (v_xyzw + uc8_8_11)*uc8_12_15 - rdplight[l]; |
| 222 | vxyzw = vxyzw*vxyzw; |
| 223 | float invlen = 65536.0f/(vxyzw[0]+vxyzw[1]+vxyzw[2]+vxyzw[3]); |
| 224 | float p_i = rdp.light[l].ca * invlen; |
| 225 | #else |
| 226 | float vx = (v->x + uc8_coord_mod[8])*uc8_coord_mod[12] - rdp.light[l].x; |
| 227 | float vy = (v->y + uc8_coord_mod[9])*uc8_coord_mod[13] - rdp.light[l].y; |
| 228 | float vz = (v->z + uc8_coord_mod[10])*uc8_coord_mod[14] - rdp.light[l].z; |
| 229 | float vw = (v->w + uc8_coord_mod[11])*uc8_coord_mod[15] - rdp.light[l].w; |
| 230 | float len = (vx*vx+vy*vy+vz*vz+vw*vw)/65536.0f; |
| 231 | float p_i = rdp.light[l].ca / len; |
| 232 | #endif |
| 233 | if (p_i > 1.0f) p_i = 1.0f; |
| 234 | light_intensity *= p_i; |
| 235 | #if __ARM_NEON__ |
| 236 | FRDP("light %d, 1/len: %f, p_intensity : %f\n", l, invlen, p_i); |
| 237 | #else |
| 238 | FRDP("light %d, len: %f, p_intensity : %f\n", l, len, p_i); |
| 239 | #endif |
| 240 | } |
| 241 | //*/ |
| 242 | #ifdef __ARM_NEON__ |
| 243 | color += rdpcolor[l] * light_intensity; |
| 244 | #else |
| 245 | color[0] += rdp.light[l].r * light_intensity; |
| 246 | color[1] += rdp.light[l].g * light_intensity; |
| 247 | color[2] += rdp.light[l].b * light_intensity; |
| 248 | #endif |
| 249 | FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]); |
| 250 | } |
| 251 | light_intensity = DotProduct (rdp.light_vector[l], v->vec); |
| 252 | FRDP("light %d, intensity : %f\n", l, light_intensity); |
| 253 | if (light_intensity > 0.0f) |
| 254 | { |
| 255 | #ifdef __ARM_NEON__ |
| 256 | color += rdpcolor[l] * light_intensity; |
| 257 | #else |
| 258 | color[0] += rdp.light[l].r * light_intensity; |
| 259 | color[1] += rdp.light[l].g * light_intensity; |
| 260 | color[2] += rdp.light[l].b * light_intensity; |
| 261 | #endif |
| 262 | } |
| 263 | FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]); |
| 264 | } |
| 265 | else |
| 266 | { |
| 267 | for (l = 0; l < rdp.num_lights; l++) |
| 268 | { |
| 269 | if (rdp.light[l].nonblack && rdp.light[l].nonzero) |
| 270 | { |
| 271 | #ifdef __ARM_NEON__ |
| 272 | float32x4_t vxyzw = (v_xyzw + uc8_8_11)*uc8_12_15 - rdplight[l]; |
| 273 | vxyzw = vxyzw*vxyzw; |
| 274 | float invlen = 65536.0f/(vxyzw[0]+vxyzw[1]+vxyzw[2]+vxyzw[3]); |
| 275 | light_intensity = rdp.light[l].ca * invlen; |
| 276 | #else |
| 277 | float vx = (v->x + uc8_coord_mod[8])*uc8_coord_mod[12] - rdp.light[l].x; |
| 278 | float vy = (v->y + uc8_coord_mod[9])*uc8_coord_mod[13] - rdp.light[l].y; |
| 279 | float vz = (v->z + uc8_coord_mod[10])*uc8_coord_mod[14] - rdp.light[l].z; |
| 280 | float vw = (v->w + uc8_coord_mod[11])*uc8_coord_mod[15] - rdp.light[l].w; |
| 281 | float len = (vx*vx+vy*vy+vz*vz+vw*vw)/65536.0f; |
| 282 | light_intensity = rdp.light[l].ca / len; |
| 283 | #endif |
| 284 | if (light_intensity > 1.0f) light_intensity = 1.0f; |
| 285 | FRDP("light %d, p_intensity : %f\n", l, light_intensity); |
| 286 | #ifdef __ARM_NEON__ |
| 287 | color += rdpcolor[l] * light_intensity; |
| 288 | #else |
| 289 | color[0] += rdp.light[l].r * light_intensity; |
| 290 | color[1] += rdp.light[l].g * light_intensity; |
| 291 | color[2] += rdp.light[l].b * light_intensity; |
| 292 | #endif |
| 293 | //FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]); |
| 294 | } |
| 295 | } |
| 296 | } |
| 297 | #ifdef __ARM_NEON__ |
| 298 | color = vminq_f32(color, unite); |
| 299 | #else |
| 300 | if (color[0] > 1.0f) color[0] = 1.0f; |
| 301 | if (color[1] > 1.0f) color[1] = 1.0f; |
| 302 | if (color[2] > 1.0f) color[2] = 1.0f; |
| 303 | #endif |
| 304 | v->r = (wxUint8)(((float)v->r)*color[0]); |
| 305 | v->g = (wxUint8)(((float)v->g)*color[1]); |
| 306 | v->b = (wxUint8)(((float)v->b)*color[2]); |
| 307 | #ifdef EXTREME_LOGGING |
| 308 | FRDP("color after light: r: 0x%02lx, g: 0x%02lx, b: 0x%02lx\n", v->r, v->g, v->b); |
| 309 | #endif |
| 310 | } |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | static void uc8_moveword () |
| 315 | { |
| 316 | wxUint8 index = (wxUint8)((rdp.cmd0 >> 16) & 0xFF); |
| 317 | wxUint16 offset = (wxUint16)(rdp.cmd0 & 0xFFFF); |
| 318 | wxUint32 data = rdp.cmd1; |
| 319 | |
| 320 | FRDP ("uc8:moveword "); |
| 321 | |
| 322 | switch (index) |
| 323 | { |
| 324 | // NOTE: right now it's assuming that it sets the integer part first. This could |
| 325 | // be easily fixed, but only if i had something to test with. |
| 326 | |
| 327 | case 0x02: |
| 328 | rdp.num_lights = (data / 48); |
| 329 | rdp.update |= UPDATE_LIGHTS; |
| 330 | FRDP ("numlights: %d\n", rdp.num_lights); |
| 331 | break; |
| 332 | |
| 333 | case 0x04: |
| 334 | if (offset == 0x04) |
| 335 | { |
| 336 | rdp.clip_ratio = sqrt((float)rdp.cmd1); |
| 337 | rdp.update |= UPDATE_VIEWPORT; |
| 338 | } |
| 339 | FRDP ("mw_clip %08lx, %08lx\n", rdp.cmd0, rdp.cmd1); |
| 340 | break; |
| 341 | |
| 342 | case 0x06: // moveword SEGMENT |
| 343 | { |
| 344 | FRDP ("SEGMENT %08lx -> seg%d\n", data, offset >> 2); |
| 345 | rdp.segment[(offset >> 2) & 0xF] = data; |
| 346 | } |
| 347 | break; |
| 348 | |
| 349 | case 0x08: |
| 350 | { |
| 351 | rdp.fog_multiplier = (short)(rdp.cmd1 >> 16); |
| 352 | rdp.fog_offset = (short)(rdp.cmd1 & 0x0000FFFF); |
| 353 | FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset); |
| 354 | } |
| 355 | break; |
| 356 | |
| 357 | case 0x0c: |
| 358 | RDP_E ("uc8:moveword forcemtx - IGNORED\n"); |
| 359 | LRDP("forcemtx - IGNORED\n"); |
| 360 | break; |
| 361 | |
| 362 | case 0x0e: |
| 363 | LRDP("perspnorm - IGNORED\n"); |
| 364 | break; |
| 365 | |
| 366 | case 0x10: // moveword coord mod |
| 367 | { |
| 368 | wxUint8 n = offset >> 2; |
| 369 | |
| 370 | FRDP ("coord mod:%d, %08lx\n", n, data); |
| 371 | if (rdp.cmd0&8) |
| 372 | return; |
| 373 | wxUint32 idx = (rdp.cmd0>>1)&3; |
| 374 | wxUint32 pos = rdp.cmd0&0x30; |
| 375 | if (pos == 0) |
| 376 | { |
| 377 | uc8_coord_mod[0+idx] = (short)(rdp.cmd1>>16); |
| 378 | uc8_coord_mod[1+idx] = (short)(rdp.cmd1&0xffff); |
| 379 | } |
| 380 | else if (pos == 0x10) |
| 381 | { |
| 382 | uc8_coord_mod[4+idx] = (rdp.cmd1>>16)/65536.0f; |
| 383 | uc8_coord_mod[5+idx] = (rdp.cmd1&0xffff)/65536.0f; |
| 384 | uc8_coord_mod[12+idx] = uc8_coord_mod[0+idx] + uc8_coord_mod[4+idx]; |
| 385 | uc8_coord_mod[13+idx] = uc8_coord_mod[1+idx] + uc8_coord_mod[5+idx]; |
| 386 | |
| 387 | } |
| 388 | else if (pos == 0x20) |
| 389 | { |
| 390 | uc8_coord_mod[8+idx] = (short)(rdp.cmd1>>16); |
| 391 | uc8_coord_mod[9+idx] = (short)(rdp.cmd1&0xffff); |
| 392 | #ifdef EXTREME_LOGGING |
| 393 | if (idx) |
| 394 | { |
| 395 | for (int k = 8; k < 16; k++) |
| 396 | { |
| 397 | FRDP("coord_mod[%d]=%f\n", k, uc8_coord_mod[k]); |
| 398 | } |
| 399 | } |
| 400 | #endif |
| 401 | } |
| 402 | |
| 403 | } |
| 404 | break; |
| 405 | |
| 406 | default: |
| 407 | FRDP_E("uc8:moveword unknown (index: 0x%08lx, offset 0x%08lx)\n", index, offset); |
| 408 | FRDP ("unknown (index: 0x%08lx, offset 0x%08lx)\n", index, offset); |
| 409 | } |
| 410 | } |
| 411 | |
| 412 | static void uc8_movemem () |
| 413 | { |
| 414 | int idx = rdp.cmd0 & 0xFF; |
| 415 | wxUint32 addr = segoffset(rdp.cmd1); |
| 416 | int ofs = (rdp.cmd0 >> 5) & 0x3FFF; |
| 417 | |
| 418 | FRDP ("uc8:movemem ofs:%d ", ofs); |
| 419 | |
| 420 | switch (idx) |
| 421 | { |
| 422 | case 8: // VIEWPORT |
| 423 | { |
| 424 | wxUint32 a = addr >> 1; |
| 425 | short scale_x = ((short*)gfx.RDRAM)[(a+0)^1] >> 2; |
| 426 | short scale_y = ((short*)gfx.RDRAM)[(a+1)^1] >> 2; |
| 427 | short scale_z = ((short*)gfx.RDRAM)[(a+2)^1]; |
| 428 | short trans_x = ((short*)gfx.RDRAM)[(a+4)^1] >> 2; |
| 429 | short trans_y = ((short*)gfx.RDRAM)[(a+5)^1] >> 2; |
| 430 | short trans_z = ((short*)gfx.RDRAM)[(a+6)^1]; |
| 431 | rdp.view_scale[0] = scale_x * rdp.scale_x; |
| 432 | rdp.view_scale[1] = -scale_y * rdp.scale_y; |
| 433 | rdp.view_scale[2] = 32.0f * scale_z; |
| 434 | rdp.view_trans[0] = trans_x * rdp.scale_x; |
| 435 | rdp.view_trans[1] = trans_y * rdp.scale_y; |
| 436 | rdp.view_trans[2] = 32.0f * trans_z; |
| 437 | |
| 438 | rdp.update |= UPDATE_VIEWPORT; |
| 439 | |
| 440 | FRDP ("viewport scale(%d, %d), trans(%d, %d), from:%08lx\n", scale_x, scale_y, |
| 441 | trans_x, trans_y, a); |
| 442 | } |
| 443 | break; |
| 444 | |
| 445 | case 10: // LIGHT |
| 446 | { |
| 447 | int n = (ofs / 48); |
| 448 | if (n < 2) |
| 449 | { |
| 450 | char dir_x = ((char*)gfx.RDRAM)[(addr+8)^3]; |
| 451 | rdp.lookat[n][0] = (float)(dir_x) / 127.0f; |
| 452 | char dir_y = ((char*)gfx.RDRAM)[(addr+9)^3]; |
| 453 | rdp.lookat[n][1] = (float)(dir_y) / 127.0f; |
| 454 | char dir_z = ((char*)gfx.RDRAM)[(addr+10)^3]; |
| 455 | rdp.lookat[n][2] = (float)(dir_z) / 127.0f; |
| 456 | rdp.use_lookat = TRUE; |
| 457 | if (n == 1) |
| 458 | { |
| 459 | if (!dir_x && !dir_y) |
| 460 | rdp.use_lookat = FALSE; |
| 461 | } |
| 462 | FRDP("lookat_%d (%f, %f, %f)\n", n, rdp.lookat[n][0], rdp.lookat[n][1], rdp.lookat[n][2]); |
| 463 | return; |
| 464 | } |
| 465 | n -= 2; |
| 466 | wxUint8 col = gfx.RDRAM[(addr+0)^3]; |
| 467 | rdp.light[n].r = (float)col / 255.0f; |
| 468 | rdp.light[n].nonblack = col; |
| 469 | col = gfx.RDRAM[(addr+1)^3]; |
| 470 | rdp.light[n].g = (float)col / 255.0f; |
| 471 | rdp.light[n].nonblack += col; |
| 472 | col = gfx.RDRAM[(addr+2)^3]; |
| 473 | rdp.light[n].b = (float)col / 255.0f; |
| 474 | rdp.light[n].nonblack += col; |
| 475 | rdp.light[n].a = 1.0f; |
| 476 | rdp.light[n].dir_x = (float)(((char*)gfx.RDRAM)[(addr+8)^3]) / 127.0f; |
| 477 | rdp.light[n].dir_y = (float)(((char*)gfx.RDRAM)[(addr+9)^3]) / 127.0f; |
| 478 | rdp.light[n].dir_z = (float)(((char*)gfx.RDRAM)[(addr+10)^3]) / 127.0f; |
| 479 | // ** |
| 480 | wxUint32 a = addr >> 1; |
| 481 | rdp.light[n].x = (float)(((short*)gfx.RDRAM)[(a+16)^1]); |
| 482 | rdp.light[n].y = (float)(((short*)gfx.RDRAM)[(a+17)^1]); |
| 483 | rdp.light[n].z = (float)(((short*)gfx.RDRAM)[(a+18)^1]); |
| 484 | rdp.light[n].w = (float)(((short*)gfx.RDRAM)[(a+19)^1]); |
| 485 | rdp.light[n].nonzero = gfx.RDRAM[(addr+12)^3]; |
| 486 | rdp.light[n].ca = (float)rdp.light[n].nonzero / 16.0f; |
| 487 | //rdp.light[n].la = rdp.light[n].ca * 1.0f; |
| 488 | #ifdef EXTREME_LOGGING |
| 489 | FRDP ("light: n: %d, pos: x: %f, y: %f, z: %f, w: %f, ca: %f\n", |
| 490 | n, rdp.light[n].x, rdp.light[n].y, rdp.light[n].z, rdp.light[n].w, rdp.light[n].ca); |
| 491 | #endif |
| 492 | FRDP ("light: n: %d, r: %f, g: %f, b: %f. dir: x: %.3f, y: %.3f, z: %.3f\n", |
| 493 | n, rdp.light[n].r, rdp.light[n].g, rdp.light[n].b, |
| 494 | rdp.light[n].dir_x, rdp.light[n].dir_y, rdp.light[n].dir_z); |
| 495 | #ifdef EXTREME_LOGGING |
| 496 | for (int t=0; t < 24; t++) |
| 497 | { |
| 498 | FRDP ("light[%d] = 0x%04lx \n", t, ((wxUint16*)gfx.RDRAM)[(a+t)^1]); |
| 499 | } |
| 500 | #endif |
| 501 | } |
| 502 | break; |
| 503 | |
| 504 | case 14: //Normales |
| 505 | { |
| 506 | uc8_normale_addr = segoffset(rdp.cmd1); |
| 507 | FRDP ("Normale - addr: %08lx\n", uc8_normale_addr); |
| 508 | #ifdef EXTREME_LOGGING |
| 509 | int i; |
| 510 | for (i = 0; i < 32; i++) |
| 511 | { |
| 512 | char x = ((char*)gfx.RDRAM)[uc8_normale_addr + ((i<<1) + 0)^3]; |
| 513 | char y = ((char*)gfx.RDRAM)[uc8_normale_addr + ((i<<1) + 1)^3]; |
| 514 | FRDP("#%d x = %d, y = %d\n", i, x, y); |
| 515 | } |
| 516 | wxUint32 a = uc8_normale_addr >> 1; |
| 517 | for (i = 0; i < 32; i++) |
| 518 | { |
| 519 | FRDP ("n[%d] = 0x%04lx \n", i, ((wxUint16*)gfx.RDRAM)[(a+i)^1]); |
| 520 | } |
| 521 | #endif |
| 522 | } |
| 523 | break; |
| 524 | |
| 525 | default: |
| 526 | FRDP ("uc8:movemem unknown (%d)\n", idx); |
| 527 | } |
| 528 | } |
| 529 | |
| 530 | |
| 531 | static void uc8_tri4() //by Gugaman Apr 19 2002 |
| 532 | { |
| 533 | Check_FrameSkip; |
| 534 | |
| 535 | if (rdp.skip_drawing) |
| 536 | { |
| 537 | LRDP("uc8:tri4. skipped\n"); |
| 538 | return; |
| 539 | } |
| 540 | |
| 541 | FRDP("uc8:tri4 (#%d - #%d), %d-%d-%d, %d-%d-%d, %d-%d-%d, %d-%d-%d\n", |
| 542 | rdp.tri_n, |
| 543 | rdp.tri_n+3, |
| 544 | ((rdp.cmd0 >> 23) & 0x1F), |
| 545 | ((rdp.cmd0 >> 18) & 0x1F), |
| 546 | ((((rdp.cmd0 >> 15) & 0x7) << 2) | ((rdp.cmd1 >> 30) &0x3)), |
| 547 | ((rdp.cmd0 >> 10) & 0x1F), |
| 548 | ((rdp.cmd0 >> 5) & 0x1F), |
| 549 | ((rdp.cmd0 >> 0) & 0x1F), |
| 550 | ((rdp.cmd1 >> 25) & 0x1F), |
| 551 | ((rdp.cmd1 >> 20) & 0x1F), |
| 552 | ((rdp.cmd1 >> 15) & 0x1F), |
| 553 | ((rdp.cmd1 >> 10) & 0x1F), |
| 554 | ((rdp.cmd1 >> 5) & 0x1F), |
| 555 | ((rdp.cmd1 >> 0) & 0x1F)); |
| 556 | |
| 557 | VERTEX *v[12] = { |
| 558 | &rdp.vtx[(rdp.cmd0 >> 23) & 0x1F], |
| 559 | &rdp.vtx[(rdp.cmd0 >> 18) & 0x1F], |
| 560 | &rdp.vtx[((((rdp.cmd0 >> 15) & 0x7) << 2) | ((rdp.cmd1 >> 30) &0x3))], |
| 561 | &rdp.vtx[(rdp.cmd0 >> 10) & 0x1F], |
| 562 | &rdp.vtx[(rdp.cmd0 >> 5) & 0x1F], |
| 563 | &rdp.vtx[(rdp.cmd0 >> 0) & 0x1F], |
| 564 | &rdp.vtx[(rdp.cmd1 >> 25) & 0x1F], |
| 565 | &rdp.vtx[(rdp.cmd1 >> 20) & 0x1F], |
| 566 | &rdp.vtx[(rdp.cmd1 >> 15) & 0x1F], |
| 567 | &rdp.vtx[(rdp.cmd1 >> 10) & 0x1F], |
| 568 | &rdp.vtx[(rdp.cmd1 >> 5) & 0x1F], |
| 569 | &rdp.vtx[(rdp.cmd1 >> 0) & 0x1F] |
| 570 | }; |
| 571 | |
| 572 | int updated = 0; |
| 573 | |
| 574 | if (cull_tri(v)) |
| 575 | rdp.tri_n ++; |
| 576 | else |
| 577 | { |
| 578 | updated = 1; |
| 579 | update (); |
| 580 | |
| 581 | draw_tri (v); |
| 582 | rdp.tri_n ++; |
| 583 | } |
| 584 | |
| 585 | if (cull_tri(v+3)) |
| 586 | rdp.tri_n ++; |
| 587 | else |
| 588 | { |
| 589 | if (!updated) |
| 590 | { |
| 591 | updated = 1; |
| 592 | update (); |
| 593 | } |
| 594 | |
| 595 | draw_tri (v+3); |
| 596 | rdp.tri_n ++; |
| 597 | } |
| 598 | |
| 599 | if (cull_tri(v+6)) |
| 600 | rdp.tri_n ++; |
| 601 | else |
| 602 | { |
| 603 | if (!updated) |
| 604 | { |
| 605 | updated = 1; |
| 606 | update (); |
| 607 | } |
| 608 | |
| 609 | draw_tri (v+6); |
| 610 | rdp.tri_n ++; |
| 611 | } |
| 612 | |
| 613 | if (cull_tri(v+9)) |
| 614 | rdp.tri_n ++; |
| 615 | else |
| 616 | { |
| 617 | if (!updated) |
| 618 | { |
| 619 | updated = 1; |
| 620 | update (); |
| 621 | } |
| 622 | |
| 623 | draw_tri (v+9); |
| 624 | rdp.tri_n ++; |
| 625 | } |
| 626 | } |