| 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 | // December 2008 Created by Gonetz (Gonetz@ngs.ru) |
| 41 | // |
| 42 | //**************************************************************** |
| 43 | |
| 44 | void uc9_rpdcmd (); |
| 45 | |
| 46 | typedef float M44[4][4]; |
| 47 | |
| 48 | struct ZSORTRDP { |
| 49 | float view_scale[2]; |
| 50 | float view_trans[2]; |
| 51 | float scale_x; |
| 52 | float scale_y; |
| 53 | } zSortRdp = {{0, 0}, {0, 0}, 0, 0}; |
| 54 | |
| 55 | //RSP command VRCPL |
| 56 | static int Calc_invw (int w) { |
| 57 | int count, neg; |
| 58 | union { |
| 59 | wxInt32 W; |
| 60 | wxUint32 UW; |
| 61 | wxInt16 HW[2]; |
| 62 | wxUint16 UHW[2]; |
| 63 | } Result; |
| 64 | Result.W = w; |
| 65 | if (Result.UW == 0) { |
| 66 | Result.UW = 0x7FFFFFFF; |
| 67 | } else { |
| 68 | if (Result.W < 0) { |
| 69 | neg = TRUE; |
| 70 | if (Result.UHW[1] == 0xFFFF && Result.HW[0] < 0) { |
| 71 | Result.W = ~Result.W + 1; |
| 72 | } else { |
| 73 | Result.W = ~Result.W; |
| 74 | } |
| 75 | } else { |
| 76 | neg = FALSE; |
| 77 | } |
| 78 | for (count = 31; count > 0; count--) { |
| 79 | if ((Result.W & (1 << count))) { |
| 80 | Result.W &= (0xFFC00000 >> (31 - count) ); |
| 81 | count = 0; |
| 82 | } |
| 83 | } |
| 84 | Result.W = 0x7FFFFFFF / Result.W; |
| 85 | for (count = 31; count > 0; count--) { |
| 86 | if ((Result.W & (1 << count))) { |
| 87 | Result.W &= (0xFFFF8000 >> (31 - count) ); |
| 88 | count = 0; |
| 89 | } |
| 90 | } |
| 91 | if (neg == TRUE) { |
| 92 | Result.W = ~Result.W; |
| 93 | } |
| 94 | } |
| 95 | return Result.W; |
| 96 | } |
| 97 | |
| 98 | static void uc9_draw_object (wxUint8 * addr, wxUint32 type) |
| 99 | { |
| 100 | Check_FrameSkip; |
| 101 | |
| 102 | wxUint32 textured, vnum, vsize; |
| 103 | switch (type) { |
| 104 | case 1: //sh tri |
| 105 | textured = 0; |
| 106 | vnum = 3; |
| 107 | vsize = 8; |
| 108 | break; |
| 109 | case 2: //tx tri |
| 110 | textured = 1; |
| 111 | vnum = 3; |
| 112 | vsize = 16; |
| 113 | break; |
| 114 | case 3: //sh quad |
| 115 | textured = 0; |
| 116 | vnum = 4; |
| 117 | vsize = 8; |
| 118 | break; |
| 119 | case 4: //tx quad |
| 120 | textured = 1; |
| 121 | vnum = 4; |
| 122 | vsize = 16; |
| 123 | break; |
| 124 | case 0: //null |
| 125 | default: |
| 126 | textured = vnum = vsize = 0; |
| 127 | break; |
| 128 | } |
| 129 | VERTEX vtx[4]; |
| 130 | for (wxUint32 i = 0; i < vnum; i++) |
| 131 | { |
| 132 | VERTEX &v = vtx[i]; |
| 133 | v.sx = zSortRdp.scale_x * ((short*)addr)[0^1]; |
| 134 | v.sy = zSortRdp.scale_y * ((short*)addr)[1^1]; |
| 135 | v.sz = 1.0f; |
| 136 | v.r = addr[4^3]; |
| 137 | v.g = addr[5^3]; |
| 138 | v.b = addr[6^3]; |
| 139 | v.a = addr[7^3]; |
| 140 | v.flags = 0; |
| 141 | v.uv_scaled = 0; |
| 142 | v.uv_calculated = 0xFFFFFFFF; |
| 143 | v.shade_mod = 0; |
| 144 | v.scr_off = 0; |
| 145 | v.screen_translated = 2; |
| 146 | if (textured) |
| 147 | { |
| 148 | v.ou = ((short*)addr)[4^1]; |
| 149 | v.ov = ((short*)addr)[5^1]; |
| 150 | v.w = Calc_invw(((int*)addr)[3]) / 31.0f; |
| 151 | v.oow = 1.0f / v.w; |
| 152 | FRDP ("v%d - sx: %f, sy: %f ou: %f, ov: %f, w: %f, r=%d, g=%d, b=%d, a=%d\n", i, v.sx/rdp.scale_x, v.sy/rdp.scale_y, v.ou*rdp.tiles[rdp.cur_tile].s_scale, v.ov*rdp.tiles[rdp.cur_tile].t_scale, v.w, v.r, v.g, v.b, v.a); |
| 153 | } |
| 154 | else |
| 155 | { |
| 156 | v.oow = v.w = 1.0f; |
| 157 | FRDP ("v%d - sx: %f, sy: %f r=%d, g=%d, b=%d, a=%d\n", i, v.sx/rdp.scale_x, v.sy/rdp.scale_y, v.r, v.g, v.b, v.a); |
| 158 | } |
| 159 | addr += vsize; |
| 160 | } |
| 161 | //* |
| 162 | VERTEX *pV[4] = { |
| 163 | &vtx[0], |
| 164 | &vtx[1], |
| 165 | &vtx[2], |
| 166 | &vtx[3] |
| 167 | }; |
| 168 | if (vnum == 3) |
| 169 | { |
| 170 | FRDP("uc9:Tri #%d, #%d\n", rdp.tri_n, rdp.tri_n+1); |
| 171 | draw_tri (pV, 0); |
| 172 | rdp.tri_n ++; |
| 173 | } |
| 174 | else |
| 175 | { |
| 176 | FRDP("uc9:Quad #%d, #%d\n", rdp.tri_n, rdp.tri_n+1); |
| 177 | draw_tri (pV, 0); |
| 178 | draw_tri (pV+1, 0); |
| 179 | rdp.tri_n += 2; |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | static wxUint32 uc9_load_object (wxUint32 zHeader, wxUint32 * rdpcmds) |
| 184 | { |
| 185 | wxUint32 type = zHeader & 7; |
| 186 | wxUint8 * addr = gfx.RDRAM + (zHeader&0xFFFFFFF8); |
| 187 | switch (type) { |
| 188 | case 1: //sh tri |
| 189 | case 3: //sh quad |
| 190 | { |
| 191 | rdp.cmd1 = ((wxUint32*)addr)[1]; |
| 192 | if (rdp.cmd1 != rdpcmds[0]) |
| 193 | { |
| 194 | rdpcmds[0] = rdp.cmd1; |
| 195 | uc9_rpdcmd (); |
| 196 | } |
| 197 | update (); |
| 198 | uc9_draw_object(addr + 8, type); |
| 199 | } |
| 200 | break; |
| 201 | case 0: //null |
| 202 | case 2: //tx tri |
| 203 | case 4: //tx quad |
| 204 | { |
| 205 | rdp.cmd1 = ((wxUint32*)addr)[1]; |
| 206 | if (rdp.cmd1 != rdpcmds[0]) |
| 207 | { |
| 208 | rdpcmds[0] = rdp.cmd1; |
| 209 | uc9_rpdcmd (); |
| 210 | } |
| 211 | rdp.cmd1 = ((wxUint32*)addr)[2]; |
| 212 | if (rdp.cmd1 != rdpcmds[1]) |
| 213 | { |
| 214 | uc9_rpdcmd (); |
| 215 | rdpcmds[1] = rdp.cmd1; |
| 216 | } |
| 217 | rdp.cmd1 = ((wxUint32*)addr)[3]; |
| 218 | if (rdp.cmd1 != rdpcmds[2]) |
| 219 | { |
| 220 | uc9_rpdcmd (); |
| 221 | rdpcmds[2] = rdp.cmd1; |
| 222 | } |
| 223 | if (type) |
| 224 | { |
| 225 | update (); |
| 226 | uc9_draw_object(addr + 16, type); |
| 227 | } |
| 228 | } |
| 229 | break; |
| 230 | } |
| 231 | return segoffset(((wxUint32*)addr)[0]); |
| 232 | } |
| 233 | |
| 234 | static void uc9_object () |
| 235 | { |
| 236 | LRDP("uc9:object\n"); |
| 237 | wxUint32 rdpcmds[3] = {0, 0, 0}; |
| 238 | wxUint32 cmd1 = rdp.cmd1; |
| 239 | wxUint32 zHeader = segoffset(rdp.cmd0); |
| 240 | while (zHeader) |
| 241 | zHeader = uc9_load_object(zHeader, rdpcmds); |
| 242 | zHeader = segoffset(cmd1); |
| 243 | while (zHeader) |
| 244 | zHeader = uc9_load_object(zHeader, rdpcmds); |
| 245 | } |
| 246 | |
| 247 | static void uc9_mix () |
| 248 | { |
| 249 | LRDP("uc9:mix IGNORED\n"); |
| 250 | } |
| 251 | |
| 252 | static void uc9_fmlight () |
| 253 | { |
| 254 | int mid = rdp.cmd0&0xFF; |
| 255 | rdp.num_lights = 1 + ((rdp.cmd1>>12)&0xFF); |
| 256 | wxUint32 a = -1024 + (rdp.cmd1&0xFFF); |
| 257 | FRDP ("uc9:fmlight matrix: %d, num: %d, dmem: %04lx\n", mid, rdp.num_lights, a); |
| 258 | |
| 259 | M44 *m = NULL; |
| 260 | switch (mid) { |
| 261 | case 4: |
| 262 | m = (M44*)rdp.model; |
| 263 | break; |
| 264 | case 6: |
| 265 | m = (M44*)rdp.proj; |
| 266 | break; |
| 267 | case 8: |
| 268 | m = (M44*)rdp.combined; |
| 269 | break; |
| 270 | } |
| 271 | |
| 272 | rdp.light[rdp.num_lights].r = (float)(((wxUint8*)gfx.DMEM)[(a+0)^3]) / 255.0f; |
| 273 | rdp.light[rdp.num_lights].g = (float)(((wxUint8*)gfx.DMEM)[(a+1)^3]) / 255.0f; |
| 274 | rdp.light[rdp.num_lights].b = (float)(((wxUint8*)gfx.DMEM)[(a+2)^3]) / 255.0f; |
| 275 | rdp.light[rdp.num_lights].a = 1.0f; |
| 276 | FRDP ("ambient light: r: %.3f, g: %.3f, b: %.3f\n", rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b); |
| 277 | a += 8; |
| 278 | wxUint32 i; |
| 279 | for (i = 0; i < rdp.num_lights; i++) |
| 280 | { |
| 281 | rdp.light[i].r = (float)(((wxUint8*)gfx.DMEM)[(a+0)^3]) / 255.0f; |
| 282 | rdp.light[i].g = (float)(((wxUint8*)gfx.DMEM)[(a+1)^3]) / 255.0f; |
| 283 | rdp.light[i].b = (float)(((wxUint8*)gfx.DMEM)[(a+2)^3]) / 255.0f; |
| 284 | rdp.light[i].a = 1.0f; |
| 285 | rdp.light[i].dir_x = (float)(((char*)gfx.DMEM)[(a+8)^3]) / 127.0f; |
| 286 | rdp.light[i].dir_y = (float)(((char*)gfx.DMEM)[(a+9)^3]) / 127.0f; |
| 287 | rdp.light[i].dir_z = (float)(((char*)gfx.DMEM)[(a+10)^3]) / 127.0f; |
| 288 | FRDP ("light: n: %d, r: %.3f, g: %.3f, b: %.3f, x: %.3f, y: %.3f, z: %.3f\n", |
| 289 | i, rdp.light[i].r, rdp.light[i].g, rdp.light[i].b, |
| 290 | rdp.light[i].dir_x, rdp.light[i].dir_y, rdp.light[i].dir_z); |
| 291 | // TransformVector(&rdp.light[i].dir_x, rdp.light_vector[i], *m); |
| 292 | InverseTransformVector(&rdp.light[i].dir_x, rdp.light_vector[i], *m); |
| 293 | NormalizeVector (rdp.light_vector[i]); |
| 294 | FRDP ("light vector: n: %d, x: %.3f, y: %.3f, z: %.3f\n", |
| 295 | i, rdp.light_vector[i][0], rdp.light_vector[i][1], rdp.light_vector[i][2]); |
| 296 | a += 24; |
| 297 | } |
| 298 | for (i = 0; i < 2; i++) |
| 299 | { |
| 300 | float dir_x = (float)(((char*)gfx.DMEM)[(a+8)^3]) / 127.0f; |
| 301 | float dir_y = (float)(((char*)gfx.DMEM)[(a+9)^3]) / 127.0f; |
| 302 | float dir_z = (float)(((char*)gfx.DMEM)[(a+10)^3]) / 127.0f; |
| 303 | if (sqrt(dir_x*dir_x + dir_y*dir_y + dir_z*dir_z) < 0.98) |
| 304 | { |
| 305 | rdp.use_lookat = FALSE; |
| 306 | return; |
| 307 | } |
| 308 | rdp.lookat[i][0] = dir_x; |
| 309 | rdp.lookat[i][1] = dir_y; |
| 310 | rdp.lookat[i][2] = dir_z; |
| 311 | a += 24; |
| 312 | } |
| 313 | rdp.use_lookat = TRUE; |
| 314 | } |
| 315 | |
| 316 | static void uc9_light () |
| 317 | { |
| 318 | wxUint32 csrs = -1024 + ((rdp.cmd0>>12)&0xFFF); |
| 319 | wxUint32 nsrs = -1024 + (rdp.cmd0&0xFFF); |
| 320 | wxUint32 num = 1 + ((rdp.cmd1>>24)&0xFF); |
| 321 | wxUint32 cdest = -1024 + ((rdp.cmd1>>12)&0xFFF); |
| 322 | wxUint32 tdest = -1024 + (rdp.cmd1&0xFFF); |
| 323 | int use_material = (csrs != 0x0ff0); |
| 324 | tdest >>= 1; |
| 325 | FRDP ("uc9:light n: %d, colsrs: %04lx, normales: %04lx, coldst: %04lx, texdst: %04lx\n", num, csrs, nsrs, cdest, tdest); |
| 326 | VERTEX v; |
| 327 | for (wxUint32 i = 0; i < num; i++) |
| 328 | { |
| 329 | v.vec[0] = ((char*)gfx.DMEM)[(nsrs++)^3]; |
| 330 | v.vec[1] = ((char*)gfx.DMEM)[(nsrs++)^3]; |
| 331 | v.vec[2] = ((char*)gfx.DMEM)[(nsrs++)^3]; |
| 332 | calc_sphere (&v); |
| 333 | // calc_linear (&v); |
| 334 | NormalizeVector (v.vec); |
| 335 | calc_light (&v); |
| 336 | v.a = 0xFF; |
| 337 | if (use_material) |
| 338 | { |
| 339 | v.r = (wxUint8)(((wxUint32)v.r * gfx.DMEM[(csrs++)^3])>>8); |
| 340 | v.g = (wxUint8)(((wxUint32)v.g * gfx.DMEM[(csrs++)^3])>>8); |
| 341 | v.b = (wxUint8)(((wxUint32)v.b * gfx.DMEM[(csrs++)^3])>>8); |
| 342 | v.a = gfx.DMEM[(csrs++)^3]; |
| 343 | } |
| 344 | gfx.DMEM[(cdest++)^3] = v.r; |
| 345 | gfx.DMEM[(cdest++)^3] = v.g; |
| 346 | gfx.DMEM[(cdest++)^3] = v.b; |
| 347 | gfx.DMEM[(cdest++)^3] = v.a; |
| 348 | ((short*)gfx.DMEM)[(tdest++)^1] = (short)v.ou; |
| 349 | ((short*)gfx.DMEM)[(tdest++)^1] = (short)v.ov; |
| 350 | } |
| 351 | } |
| 352 | |
| 353 | static void uc9_mtxtrnsp () |
| 354 | { |
| 355 | LRDP("uc9:mtxtrnsp - ignored\n"); |
| 356 | /* |
| 357 | LRDP("uc9:mtxtrnsp "); |
| 358 | M44 *s; |
| 359 | switch (rdp.cmd1&0xF) { |
| 360 | case 4: |
| 361 | s = (M44*)rdp.model; |
| 362 | LRDP("Model\n"); |
| 363 | break; |
| 364 | case 6: |
| 365 | s = (M44*)rdp.proj; |
| 366 | LRDP("Proj\n"); |
| 367 | break; |
| 368 | case 8: |
| 369 | s = (M44*)rdp.combined; |
| 370 | LRDP("Comb\n"); |
| 371 | break; |
| 372 | } |
| 373 | float m = *s[1][0]; |
| 374 | *s[1][0] = *s[0][1]; |
| 375 | *s[0][1] = m; |
| 376 | m = *s[2][0]; |
| 377 | *s[2][0] = *s[0][2]; |
| 378 | *s[0][2] = m; |
| 379 | m = *s[2][1]; |
| 380 | *s[2][1] = *s[1][2]; |
| 381 | *s[1][2] = m; |
| 382 | */ |
| 383 | } |
| 384 | |
| 385 | static void uc9_mtxcat () |
| 386 | { |
| 387 | LRDP("uc9:mtxcat "); |
| 388 | M44 *s = NULL; |
| 389 | M44 *t = NULL; |
| 390 | wxUint32 S = rdp.cmd0&0xF; |
| 391 | wxUint32 T = (rdp.cmd1>>16)&0xF; |
| 392 | wxUint32 D = rdp.cmd1&0xF; |
| 393 | switch (S) { |
| 394 | case 4: |
| 395 | s = (M44*)rdp.model; |
| 396 | LRDP("Model * "); |
| 397 | break; |
| 398 | case 6: |
| 399 | s = (M44*)rdp.proj; |
| 400 | LRDP("Proj * "); |
| 401 | break; |
| 402 | case 8: |
| 403 | s = (M44*)rdp.combined; |
| 404 | LRDP("Comb * "); |
| 405 | break; |
| 406 | } |
| 407 | switch (T) { |
| 408 | case 4: |
| 409 | t = (M44*)rdp.model; |
| 410 | LRDP("Model -> "); |
| 411 | break; |
| 412 | case 6: |
| 413 | t = (M44*)rdp.proj; |
| 414 | LRDP("Proj -> "); |
| 415 | break; |
| 416 | case 8: |
| 417 | LRDP("Comb -> "); |
| 418 | t = (M44*)rdp.combined; |
| 419 | break; |
| 420 | } |
| 421 | DECLAREALIGN16VAR(m[4][4]); |
| 422 | MulMatrices(*s, *t, m); |
| 423 | |
| 424 | switch (D) { |
| 425 | case 4: |
| 426 | memcpy (rdp.model, m, 64);; |
| 427 | LRDP("Model\n"); |
| 428 | break; |
| 429 | case 6: |
| 430 | memcpy (rdp.proj, m, 64);; |
| 431 | LRDP("Proj\n"); |
| 432 | break; |
| 433 | case 8: |
| 434 | memcpy (rdp.combined, m, 64);; |
| 435 | LRDP("Comb\n"); |
| 436 | break; |
| 437 | } |
| 438 | #ifdef EXTREME_LOGGING |
| 439 | FRDP ("\nmodel\n{%f,%f,%f,%f}\n", rdp.model[0][0], rdp.model[0][1], rdp.model[0][2], rdp.model[0][3]); |
| 440 | FRDP ("{%f,%f,%f,%f}\n", rdp.model[1][0], rdp.model[1][1], rdp.model[1][2], rdp.model[1][3]); |
| 441 | FRDP ("{%f,%f,%f,%f}\n", rdp.model[2][0], rdp.model[2][1], rdp.model[2][2], rdp.model[2][3]); |
| 442 | FRDP ("{%f,%f,%f,%f}\n", rdp.model[3][0], rdp.model[3][1], rdp.model[3][2], rdp.model[3][3]); |
| 443 | FRDP ("\nproj\n{%f,%f,%f,%f}\n", rdp.proj[0][0], rdp.proj[0][1], rdp.proj[0][2], rdp.proj[0][3]); |
| 444 | FRDP ("{%f,%f,%f,%f}\n", rdp.proj[1][0], rdp.proj[1][1], rdp.proj[1][2], rdp.proj[1][3]); |
| 445 | FRDP ("{%f,%f,%f,%f}\n", rdp.proj[2][0], rdp.proj[2][1], rdp.proj[2][2], rdp.proj[2][3]); |
| 446 | FRDP ("{%f,%f,%f,%f}\n", rdp.proj[3][0], rdp.proj[3][1], rdp.proj[3][2], rdp.proj[3][3]); |
| 447 | FRDP ("\ncombined\n{%f,%f,%f,%f}\n", rdp.combined[0][0], rdp.combined[0][1], rdp.combined[0][2], rdp.combined[0][3]); |
| 448 | FRDP ("{%f,%f,%f,%f}\n", rdp.combined[1][0], rdp.combined[1][1], rdp.combined[1][2], rdp.combined[1][3]); |
| 449 | FRDP ("{%f,%f,%f,%f}\n", rdp.combined[2][0], rdp.combined[2][1], rdp.combined[2][2], rdp.combined[2][3]); |
| 450 | FRDP ("{%f,%f,%f,%f}\n", rdp.combined[3][0], rdp.combined[3][1], rdp.combined[3][2], rdp.combined[3][3]); |
| 451 | #endif |
| 452 | } |
| 453 | |
| 454 | typedef struct { |
| 455 | short sy; |
| 456 | short sx; |
| 457 | int invw; |
| 458 | short yi; |
| 459 | short xi; |
| 460 | short wi; |
| 461 | wxUint8 fog; |
| 462 | wxUint8 cc; |
| 463 | } zSortVDest; |
| 464 | |
| 465 | static void uc9_mult_mpmtx () |
| 466 | { |
| 467 | //int id = rdp.cmd0&0xFF; |
| 468 | int num = 1+ ((rdp.cmd1>>24)&0xFF); |
| 469 | int src = -1024 + ((rdp.cmd1>>12)&0xFFF); |
| 470 | int dst = -1024 + (rdp.cmd1&0xFFF); |
| 471 | FRDP ("uc9:mult_mpmtx from: %04lx to: %04lx n: %d\n", src, dst, num); |
| 472 | short * saddr = (short*)(gfx.DMEM+src); |
| 473 | zSortVDest * daddr = (zSortVDest*)(gfx.DMEM+dst); |
| 474 | int idx = 0; |
| 475 | zSortVDest v; |
| 476 | memset(&v, 0, sizeof(zSortVDest)); |
| 477 | //float scale_x = 4.0f/rdp.scale_x; |
| 478 | //float scale_y = 4.0f/rdp.scale_y; |
| 479 | for (int i = 0; i < num; i++) |
| 480 | { |
| 481 | short sx = saddr[(idx++)^1]; |
| 482 | short sy = saddr[(idx++)^1]; |
| 483 | short sz = saddr[(idx++)^1]; |
| 484 | float x = sx*rdp.combined[0][0] + sy*rdp.combined[1][0] + sz*rdp.combined[2][0] + rdp.combined[3][0]; |
| 485 | float y = sx*rdp.combined[0][1] + sy*rdp.combined[1][1] + sz*rdp.combined[2][1] + rdp.combined[3][1]; |
| 486 | float z = sx*rdp.combined[0][2] + sy*rdp.combined[1][2] + sz*rdp.combined[2][2] + rdp.combined[3][2]; |
| 487 | float w = sx*rdp.combined[0][3] + sy*rdp.combined[1][3] + sz*rdp.combined[2][3] + rdp.combined[3][3]; |
| 488 | v.sx = (short)(zSortRdp.view_trans[0] + x / w * zSortRdp.view_scale[0]); |
| 489 | v.sy = (short)(zSortRdp.view_trans[1] + y / w * zSortRdp.view_scale[1]); |
| 490 | |
| 491 | v.xi = (short)x; |
| 492 | v.yi = (short)y; |
| 493 | v.wi = (short)w; |
| 494 | v.invw = Calc_invw((int)(w * 31.0)); |
| 495 | |
| 496 | if (w < 0.0f) |
| 497 | v.fog = 0; |
| 498 | else |
| 499 | { |
| 500 | int fog = (int)(z / w * rdp.fog_multiplier + rdp.fog_offset); |
| 501 | if (fog > 255) |
| 502 | fog = 255; |
| 503 | v.fog = (fog >= 0) ? (wxUint8)fog : 0; |
| 504 | } |
| 505 | |
| 506 | v.cc = 0; |
| 507 | if (x < -w) v.cc |= 0x10; |
| 508 | if (x > w) v.cc |= 0x01; |
| 509 | if (y < -w) v.cc |= 0x20; |
| 510 | if (y > w) v.cc |= 0x02; |
| 511 | if (w < 0.1f) v.cc |= 0x04; |
| 512 | |
| 513 | daddr[i] = v; |
| 514 | //memcpy(gfx.DMEM+dst+sizeof(zSortVDest)*i, &v, sizeof(zSortVDest)); |
| 515 | // FRDP("v%d x: %d, y: %d, z: %d -> sx: %d, sy: %d, w: %d, xi: %d, yi: %d, wi: %d, fog: %d\n", i, sx, sy, sz, v.sx, v.sy, v.invw, v.xi, v.yi, v.wi, v.fog); |
| 516 | FRDP("v%d x: %d, y: %d, z: %d -> sx: %04lx, sy: %04lx, invw: %08lx - %f, xi: %04lx, yi: %04lx, wi: %04lx, fog: %04lx\n", i, sx, sy, sz, v.sx, v.sy, v.invw, w, v.xi, v.yi, v.wi, v.fog); |
| 517 | } |
| 518 | } |
| 519 | |
| 520 | static void uc9_link_subdl () |
| 521 | { |
| 522 | LRDP("uc9:link_subdl IGNORED\n"); |
| 523 | } |
| 524 | |
| 525 | static void uc9_set_subdl () |
| 526 | { |
| 527 | LRDP("uc9:set_subdl IGNORED\n"); |
| 528 | } |
| 529 | |
| 530 | static void uc9_wait_signal () |
| 531 | { |
| 532 | LRDP("uc9:wait_signal IGNORED\n"); |
| 533 | } |
| 534 | |
| 535 | static void uc9_send_signal () |
| 536 | { |
| 537 | LRDP("uc9:send_signal IGNORED\n"); |
| 538 | } |
| 539 | |
| 540 | void uc9_movemem () |
| 541 | { |
| 542 | LRDP("uc9:movemem\n"); |
| 543 | int idx = rdp.cmd0 & 0x0E; |
| 544 | int ofs = ((rdp.cmd0>>6)&0x1ff)<<3; |
| 545 | int len = (1 + ((rdp.cmd0>>15)&0x1ff))<<3; |
| 546 | FRDP ("uc9:movemem ofs: %d, len: %d. ", ofs, len); |
| 547 | int flag = rdp.cmd0 & 0x01; |
| 548 | wxUint32 addr = segoffset(rdp.cmd1); |
| 549 | switch (idx) |
| 550 | { |
| 551 | |
| 552 | case 0: //save/load |
| 553 | if (flag == 0) |
| 554 | { |
| 555 | int dmem_addr = (idx<<3) + ofs; |
| 556 | FRDP ("Load to DMEM. %08lx -> %08lx\n", addr, dmem_addr); |
| 557 | memcpy(gfx.DMEM + dmem_addr, gfx.RDRAM + addr, len); |
| 558 | } |
| 559 | else |
| 560 | { |
| 561 | int dmem_addr = (idx<<3) + ofs; |
| 562 | FRDP ("Load from DMEM. %08lx -> %08lx\n", dmem_addr, addr); |
| 563 | memcpy(gfx.RDRAM + addr, gfx.DMEM + dmem_addr, len); |
| 564 | } |
| 565 | break; |
| 566 | |
| 567 | case 4: // model matrix |
| 568 | case 6: // projection matrix |
| 569 | case 8: // combined matrix |
| 570 | { |
| 571 | DECLAREALIGN16VAR(m[4][4]); |
| 572 | load_matrix(m, addr); |
| 573 | switch (idx) |
| 574 | { |
| 575 | case 4: // model matrix |
| 576 | LRDP("Modelview load\n"); |
| 577 | modelview_load (m); |
| 578 | break; |
| 579 | case 6: // projection matrix |
| 580 | LRDP("Projection load\n"); |
| 581 | projection_load (m); |
| 582 | break; |
| 583 | case 8: // projection matrix |
| 584 | LRDP("Combined load\n"); |
| 585 | rdp.update &= ~UPDATE_MULT_MAT; |
| 586 | memcpy (rdp.combined, m, 64);; |
| 587 | break; |
| 588 | } |
| 589 | #ifdef EXTREME_LOGGING |
| 590 | FRDP ("{%f,%f,%f,%f}\n", m[0][0], m[0][1], m[0][2], m[0][3]); |
| 591 | FRDP ("{%f,%f,%f,%f}\n", m[1][0], m[1][1], m[1][2], m[1][3]); |
| 592 | FRDP ("{%f,%f,%f,%f}\n", m[2][0], m[2][1], m[2][2], m[2][3]); |
| 593 | FRDP ("{%f,%f,%f,%f}\n", m[3][0], m[3][1], m[3][2], m[3][3]); |
| 594 | FRDP ("\nmodel\n{%f,%f,%f,%f}\n", rdp.model[0][0], rdp.model[0][1], rdp.model[0][2], rdp.model[0][3]); |
| 595 | FRDP ("{%f,%f,%f,%f}\n", rdp.model[1][0], rdp.model[1][1], rdp.model[1][2], rdp.model[1][3]); |
| 596 | FRDP ("{%f,%f,%f,%f}\n", rdp.model[2][0], rdp.model[2][1], rdp.model[2][2], rdp.model[2][3]); |
| 597 | FRDP ("{%f,%f,%f,%f}\n", rdp.model[3][0], rdp.model[3][1], rdp.model[3][2], rdp.model[3][3]); |
| 598 | FRDP ("\nproj\n{%f,%f,%f,%f}\n", rdp.proj[0][0], rdp.proj[0][1], rdp.proj[0][2], rdp.proj[0][3]); |
| 599 | FRDP ("{%f,%f,%f,%f}\n", rdp.proj[1][0], rdp.proj[1][1], rdp.proj[1][2], rdp.proj[1][3]); |
| 600 | FRDP ("{%f,%f,%f,%f}\n", rdp.proj[2][0], rdp.proj[2][1], rdp.proj[2][2], rdp.proj[2][3]); |
| 601 | FRDP ("{%f,%f,%f,%f}\n", rdp.proj[3][0], rdp.proj[3][1], rdp.proj[3][2], rdp.proj[3][3]); |
| 602 | #endif |
| 603 | } |
| 604 | break; |
| 605 | |
| 606 | case 10: |
| 607 | LRDP("Othermode - IGNORED\n"); |
| 608 | break; |
| 609 | |
| 610 | case 12: // VIEWPORT |
| 611 | { |
| 612 | wxUint32 a = addr >> 1; |
| 613 | short scale_x = ((short*)gfx.RDRAM)[(a+0)^1] >> 2; |
| 614 | short scale_y = ((short*)gfx.RDRAM)[(a+1)^1] >> 2; |
| 615 | short scale_z = ((short*)gfx.RDRAM)[(a+2)^1]; |
| 616 | rdp.fog_multiplier = ((short*)gfx.RDRAM)[(a+3)^1]; |
| 617 | short trans_x = ((short*)gfx.RDRAM)[(a+4)^1] >> 2; |
| 618 | short trans_y = ((short*)gfx.RDRAM)[(a+5)^1] >> 2; |
| 619 | short trans_z = ((short*)gfx.RDRAM)[(a+6)^1]; |
| 620 | rdp.fog_offset = ((short*)gfx.RDRAM)[(a+7)^1]; |
| 621 | rdp.view_scale[0] = scale_x * rdp.scale_x; |
| 622 | rdp.view_scale[1] = scale_y * rdp.scale_y; |
| 623 | rdp.view_scale[2] = 32.0f * scale_z; |
| 624 | rdp.view_trans[0] = trans_x * rdp.scale_x; |
| 625 | rdp.view_trans[1] = trans_y * rdp.scale_y; |
| 626 | rdp.view_trans[2] = 32.0f * trans_z; |
| 627 | zSortRdp.view_scale[0] = (float)(scale_x*4); |
| 628 | zSortRdp.view_scale[1] = (float)(scale_y*4); |
| 629 | zSortRdp.view_trans[0] = (float)(trans_x*4); |
| 630 | zSortRdp.view_trans[1] = (float)(trans_y*4); |
| 631 | zSortRdp.scale_x = rdp.scale_x / 4.0f; |
| 632 | zSortRdp.scale_y = rdp.scale_y / 4.0f; |
| 633 | |
| 634 | rdp.update |= UPDATE_VIEWPORT; |
| 635 | |
| 636 | rdp.mipmap_level = 0; |
| 637 | rdp.cur_tile = 0; |
| 638 | TILE *tmp_tile = &rdp.tiles[0]; |
| 639 | tmp_tile->on = 1; |
| 640 | tmp_tile->org_s_scale = 0xFFFF; |
| 641 | tmp_tile->org_t_scale = 0xFFFF; |
| 642 | tmp_tile->s_scale = 0.031250f; |
| 643 | tmp_tile->t_scale = 0.031250f; |
| 644 | |
| 645 | rdp.geom_mode |= 0x0200; |
| 646 | |
| 647 | FRDP ("viewport scale(%d, %d, %d), trans(%d, %d, %d), from:%08lx\n", scale_x, scale_y, scale_z, |
| 648 | trans_x, trans_y, trans_z, a); |
| 649 | FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset); |
| 650 | } |
| 651 | break; |
| 652 | |
| 653 | default: |
| 654 | FRDP ("** UNKNOWN %d\n", idx); |
| 655 | } |
| 656 | |
| 657 | } |
| 658 | |
| 659 | static void uc9_setscissor() |
| 660 | { |
| 661 | rdp_setscissor(); |
| 662 | |
| 663 | if ((rdp.scissor_o.lr_x - rdp.scissor_o.ul_x) > (zSortRdp.view_scale[0] - zSortRdp.view_trans[0])) |
| 664 | { |
| 665 | float w = (rdp.scissor_o.lr_x - rdp.scissor_o.ul_x) / 2.0f; |
| 666 | float h = (rdp.scissor_o.lr_y - rdp.scissor_o.ul_y) / 2.0f; |
| 667 | rdp.view_scale[0] = w * rdp.scale_x; |
| 668 | rdp.view_scale[1] = h * rdp.scale_y; |
| 669 | rdp.view_trans[0] = w * rdp.scale_x; |
| 670 | rdp.view_trans[1] = h * rdp.scale_y; |
| 671 | zSortRdp.view_scale[0] = w * 4.0f; |
| 672 | zSortRdp.view_scale[1] = h * 4.0f; |
| 673 | zSortRdp.view_trans[0] = w * 4.0f; |
| 674 | zSortRdp.view_trans[1] = h * 4.0f; |
| 675 | zSortRdp.scale_x = rdp.scale_x / 4.0f; |
| 676 | zSortRdp.scale_y = rdp.scale_y / 4.0f; |
| 677 | rdp.update |= UPDATE_VIEWPORT; |
| 678 | |
| 679 | rdp.mipmap_level = 0; |
| 680 | rdp.cur_tile = 0; |
| 681 | TILE *tmp_tile = &rdp.tiles[0]; |
| 682 | tmp_tile->on = 1; |
| 683 | tmp_tile->org_s_scale = 0xFFFF; |
| 684 | tmp_tile->org_t_scale = 0xFFFF; |
| 685 | tmp_tile->s_scale = 0.031250f; |
| 686 | tmp_tile->t_scale = 0.031250f; |
| 687 | |
| 688 | rdp.geom_mode |= 0x0200; |
| 689 | } |
| 690 | } |