| Previous | 199869 Revisions | Next |
| r29517 Thursday 10th April, 2014 at 20:30:44 UTC by Tafoid |
|---|
| Chihiro improvements: [Samuele Zannoli] * i386 cpu x87 opcodes FPREM and FPREM1 must clear status bit C2 not C0 * Add basic management of some Nvidia APU sound registers. * Store modelview/projection matrices and translate/scale vectors sent to NV2A. * Store vertex program (vertex shader) sent to NV2A 3d accelerator. * Added debug command "chihiro grab_texture,<type>,<filename>", it saves to <filename> the next used texture of type <type>. * Fixed DXT3 and adds DXt5 texture decompression. * Add 3d accelerator method 0x1800 for indexed mode vertex sending. |
| [src/emu/cpu/i386] | x87ops.inc |
| [src/mame/drivers] | chihiro.c |
| r29516 | r29517 | |
|---|---|---|
| 416 | 416 | void dword_write_le(UINT8 *addr,UINT32 d); |
| 417 | 417 | void word_write_le(UINT8 *addr,UINT16 d); |
| 418 | 418 | void debug_generate_irq(int irq,bool active); |
| 419 | void debug_grab_texture(int type, char *filename); | |
| 419 | 420 | |
| 420 | 421 | void vblank_callback(screen_device &screen, bool state); |
| 421 | 422 | UINT32 screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| r29516 | r29517 | |
| 445 | 446 | UINT32 words[256/4]; |
| 446 | 447 | } smbusst; |
| 447 | 448 | struct apu_state { |
| 448 | UINT32 memory0_sgaddress; | |
| 449 | UINT32 memory0_sgblocks; | |
| 450 | UINT32 memory0_address; | |
| 451 | UINT32 memory1_sgaddress; | |
| 452 | UINT32 memory1_sgblocks; | |
| 449 | UINT32 memory[0x60000/4]; | |
| 450 | UINT32 gpdsp_sgaddress; // global processor scatter-gather | |
| 451 | UINT32 gpdsp_sgblocks; | |
| 452 | UINT32 gpdsp_address; | |
| 453 | UINT32 epdsp_sgaddress; // encoder processor scatter-gather | |
| 454 | UINT32 epdsp_sgblocks; | |
| 455 | UINT32 unknown_sgaddress; | |
| 456 | UINT32 unknown_sgblocks; | |
| 457 | int voice_number; | |
| 458 | UINT32 voices_heap_blockaddr[1024]; | |
| 459 | UINT64 voices_active[4]; //one bit for each voice: 1 playing 0 not | |
| 460 | UINT32 voicedata_address; | |
| 461 | int voices_frequency[256]; // sample rate | |
| 462 | int voices_position[256]; // position in samples * 1000 | |
| 463 | int voices_position_start[256]; // position in samples * 1000 | |
| 464 | int voices_position_end[256]; // position in samples * 1000 | |
| 465 | int voices_position_increment[256]; // position increment every 1ms * 1000 | |
| 453 | 466 | emu_timer *timer; |
| 454 | 467 | address_space *space; |
| 455 | 468 | } apust; |
| r29516 | r29517 | |
| 503 | 516 | combiner.used=0; |
| 504 | 517 | combiner.lock=osd_lock_alloc(); |
| 505 | 518 | enabled_vertex_attributes=0; |
| 506 | memset(words_vertex_attributes,0,sizeof(words_vertex_attributes)); | |
| 519 | indexesleft_count = 0; | |
| 520 | debug_grab_texttype = -1; | |
| 521 | debug_grab_textfile = NULL; | |
| 522 | memset(words_vertex_attributes, 0, sizeof(words_vertex_attributes)); | |
| 507 | 523 | } |
| 508 | 524 | DECLARE_READ32_MEMBER( geforce_r ); |
| 509 | 525 | DECLARE_WRITE32_MEMBER( geforce_w ); |
| r29516 | r29517 | |
| 546 | 562 | void computedilated(void); |
| 547 | 563 | void putpixtex(int xp,int yp,int up,int vp); |
| 548 | 564 | int toggle_register_combiners_usage(); |
| 565 | void debug_grab_texture(int type, const char *filename); | |
| 549 | 566 | void savestate_items(); |
| 550 | 567 | |
| 551 | 568 | struct { |
| r29516 | r29517 | |
| 570 | 587 | int rectangle_pitch; |
| 571 | 588 | void *buffer; |
| 572 | 589 | } texture[4]; |
| 590 | int primitives_count; | |
| 591 | int indexesleft_count; | |
| 592 | UINT32 indexesleft[8]; | |
| 573 | 593 | struct { |
| 574 | 594 | float variable_A[4]; // 0=R 1=G 2=B 3=A |
| 575 | 595 | float variable_B[4]; |
| r29516 | r29517 | |
| 673 | 693 | int used; |
| 674 | 694 | osd_lock *lock; |
| 675 | 695 | } combiner; |
| 696 | struct { | |
| 697 | float modelview[16]; | |
| 698 | float modelview_inverse[16]; | |
| 699 | float projection[16]; | |
| 700 | float translate[4]; | |
| 701 | float scale[4]; | |
| 702 | } matrix; | |
| 703 | struct { | |
| 704 | UINT32 instruction[1024]; | |
| 705 | int instructions; | |
| 706 | int upload_instruction; | |
| 707 | UINT32 parameter[1024]; | |
| 708 | int upload_parameter; | |
| 709 | } vertexprogram; | |
| 676 | 710 | int enabled_vertex_attributes; |
| 677 | 711 | int words_vertex_attributes[16]; |
| 678 | 712 | bitmap_rgb32 fb; |
| r29516 | r29517 | |
| 680 | 714 | UINT32 dilated1[16][2048]; |
| 681 | 715 | int dilatechose[256]; |
| 682 | 716 | nvidia_object_data *objectdata; |
| 717 | int debug_grab_texttype; | |
| 718 | char *debug_grab_textfile; | |
| 683 | 719 | |
| 684 | 720 | enum NV2A_BEGIN_END { |
| 685 | 721 | STOP=0, |
| r29516 | r29517 | |
| 1052 | 1088 | debug_console_printf(machine,"Register combiners disabled\n"); |
| 1053 | 1089 | } |
| 1054 | 1090 | |
| 1091 | static void grab_texture_command(running_machine &machine, int ref, int params, const char **param) | |
| 1092 | { | |
| 1093 | UINT64 type; | |
| 1094 | chihiro_state *chst = machine.driver_data<chihiro_state>(); | |
| 1095 | ||
| 1096 | if (params < 2) | |
| 1097 | return; | |
| 1098 | if (!debug_command_parameter_number(machine, param[0], &type)) | |
| 1099 | return; | |
| 1100 | if ((param[1][0] == 0) || (strlen(param[1]) > 127)) | |
| 1101 | return; | |
| 1102 | chst->nvidia_nv2a->debug_grab_texture((int)type,param[1]); | |
| 1103 | } | |
| 1104 | ||
| 1055 | 1105 | static void help_command(running_machine &machine, int ref, int params, const char **param) |
| 1056 | 1106 | { |
| 1057 | 1107 | debug_console_printf(machine,"Available Chihiro commands:\n"); |
| r29516 | r29517 | |
| 1062 | 1112 | debug_console_printf(machine," chihiro curthread -- Print information about current thread\n"); |
| 1063 | 1113 | debug_console_printf(machine," chihiro irq,<number> -- Generate interrupt with irq number 0-15\n"); |
| 1064 | 1114 | debug_console_printf(machine," chihiro nv2a_combiners -- Toggle use of register combiners\n"); |
| 1115 | debug_console_printf(machine," chihiro grab_texture,<type>,<filename> -- Save to <filename> the next used texture of type <type>\n"); | |
| 1065 | 1116 | debug_console_printf(machine," chihiro help -- this list\n"); |
| 1066 | 1117 | } |
| 1067 | 1118 | |
| r29516 | r29517 | |
| 1083 | 1134 | generate_irq_command(machine,ref,params-1,param+1); |
| 1084 | 1135 | else if (strcmp("nv2a_combiners",param[0]) == 0) |
| 1085 | 1136 | nv2a_combiners_command(machine,ref,params-1,param+1); |
| 1137 | else if (strcmp("grab_texture", param[0]) == 0) | |
| 1138 | grab_texture_command(machine, ref, params - 1, param + 1); | |
| 1086 | 1139 | else |
| 1087 | 1140 | help_command(machine,ref,params-1,param+1); |
| 1088 | 1141 | } |
| r29516 | r29517 | |
| 1256 | 1309 | |
| 1257 | 1310 | UINT32 nv2a_renderer::texture_get_texel(int number,int x,int y) |
| 1258 | 1311 | { |
| 1259 | UINT32 to,s,c,sa,ca; | |
| 1260 | UINT32 a4r4g4b4,a1r5g5b5,r5g6b5; | |
| 1261 | int bx,by; | |
| 1262 | int color0,color1,color0m2,color1m2; | |
| 1312 | UINT32 to, s, c, sa, ca; | |
| 1313 | UINT32 a4r4g4b4, a1r5g5b5, r5g6b5; | |
| 1314 | int bx, by; | |
| 1315 | int color0, color1, color0m2, color1m2, alpha0, alpha1; | |
| 1263 | 1316 | UINT32 codes; |
| 1264 | 1317 | UINT64 alphas; |
| 1265 | int cr,cg,cb; | |
| 1318 | int cr, cg, cb; | |
| 1266 | 1319 | |
| 1320 | // force to [0,size-1] | |
| 1321 | x = (unsigned int)x & (texture[number].sizeu - 1); | |
| 1322 | y = (unsigned int)y & (texture[number].sizev - 1); | |
| 1267 | 1323 | switch (texture[number].format) { |
| 1268 | case A8R8G8B8: | |
| 1269 | to=dilated0[texture[number].dilate][x]+dilated1[texture[number].dilate][y]; // offset of texel in texture memory | |
| 1270 | return *(((UINT32 *)texture[number].buffer)+to); // get texel color | |
| 1271 | case DXT1: | |
| 1272 | bx=x >> 2; | |
| 1273 | by=y >> 2; | |
| 1274 | x=x & 3; | |
| 1275 | y=y & 3; | |
| 1276 | //to=dilated0[texture[number].dilate][bx]+dilated1[texture[number].dilate][by]; // swizzle 4x4 blocks ? | |
| 1277 | to=bx+by*(texture[number].sizeu >> 2); | |
| 1278 | color0=*((UINT16 *)(((UINT64 *)texture[number].buffer)+to)+0); | |
| 1279 | color1=*((UINT16 *)(((UINT64 *)texture[number].buffer)+to)+1); | |
| 1280 | codes=*((UINT32 *)(((UINT64 *)texture[number].buffer)+to)+1); | |
| 1281 | s=(y << 3)+(x << 1); | |
| 1282 | c=(codes >> s) & 3; | |
| 1283 | c=c+(color0 > color1 ? 0 : 4); | |
| 1284 | color0m2=color0 << 1; | |
| 1285 | color1m2=color1 << 1; | |
| 1286 | switch (c) { | |
| 1287 | case 0: | |
| 1288 | return 0xff000000+convert_r5g6b5_r8g8b8(color0); | |
| 1289 | break; | |
| 1290 | case 1: | |
| 1291 | return 0xff000000+convert_r5g6b5_r8g8b8(color1); | |
| 1292 | break; | |
| 1293 | case 2: | |
| 1294 | cb=pal5bit(((color0m2 & 0x003e)+(color1 & 0x001f))/3); | |
| 1295 | cg=pal6bit(((color0m2 & 0x0fc0)+(color1 & 0x07e0))/3 >> 5); | |
| 1296 | cr=pal5bit(((color0m2 & 0x1f000)+color1)/3 >> 11); | |
| 1297 | return 0xff000000|(cr<<16)|(cg<<8)|(cb); | |
| 1298 | break; | |
| 1299 | case 3: | |
| 1300 | cb=pal5bit(((color1m2 & 0x003e)+(color0 & 0x001f))/3); | |
| 1301 | cg=pal6bit(((color1m2 & 0x0fc0)+(color0 & 0x07e0))/3 >> 5); | |
| 1302 | cr=pal5bit(((color1m2 & 0x1f000)+color0)/3 >> 11); | |
| 1303 | return 0xff000000|(cr<<16)|(cg<<8)|(cb); | |
| 1304 | break; | |
| 1305 | case 4: | |
| 1306 | return 0xff000000+convert_r5g6b5_r8g8b8(color0); | |
| 1307 | break; | |
| 1308 | case 5: | |
| 1309 | return 0xff000000+convert_r5g6b5_r8g8b8(color1); | |
| 1310 | break; | |
| 1311 | case 6: | |
| 1312 | cb=pal5bit(((color0 & 0x001f)+(color1 & 0x001f))/2); | |
| 1313 | cg=pal6bit(((color0 & 0x07e0)+(color1 & 0x07e0))/2 >> 5); | |
| 1314 | cr=pal5bit((color0+color1)/2 >> 11); | |
| 1315 | return 0xff000000|(cr<<16)|(cg<<8)|(cb); | |
| 1316 | break; | |
| 1317 | default: | |
| 1318 | return 0xff000000; | |
| 1319 | break; | |
| 1320 | } | |
| 1321 | case DXT3: | |
| 1322 | bx=x >> 2; | |
| 1323 | by=y >> 2; | |
| 1324 | x=x & 3; | |
| 1325 | y=y & 3; | |
| 1326 | //to=(dilated0[texture[number].dilate][bx]+dilated1[texture[number].dilate][by]) << 1; // swizzle 4x4 blocks ? | |
| 1327 | to=(bx+by*(texture[number].sizeu >> 2)) << 1; | |
| 1328 | color0=*((UINT16 *)(((UINT64 *)texture[number].buffer)+to)+4); | |
| 1329 | color1=*((UINT16 *)(((UINT64 *)texture[number].buffer)+to)+5); | |
| 1330 | codes=*((UINT32 *)(((UINT64 *)texture[number].buffer)+to)+3); | |
| 1331 | alphas=*(((UINT64 *)texture[number].buffer)+to); | |
| 1332 | s=(y << 3)+(x << 1); | |
| 1333 | sa=((y << 2)+x) << 2; | |
| 1334 | c=(codes >> s) & 3; | |
| 1335 | ca=(alphas >> sa) & 15; | |
| 1336 | switch (c) { | |
| 1337 | case 0: | |
| 1338 | return ((ca+(ca << 4)) << 24)+convert_r5g6b5_r8g8b8(color0); | |
| 1339 | break; | |
| 1340 | case 1: | |
| 1341 | return ((ca+(ca << 4)) << 24)+convert_r5g6b5_r8g8b8(color1); | |
| 1342 | break; | |
| 1343 | case 2: | |
| 1344 | cb=pal5bit(((color0 & 0x001f)+(color1 & 0x001f))/2); | |
| 1345 | cg=pal6bit(((color0 & 0x07e0)+(color1 & 0x07e0))/2 >> 5); | |
| 1346 | cr=pal5bit((color0+color1)/2 >> 11); | |
| 1347 | return ((ca+(ca << 4)) << 24)|(cr<<16)|(cg<<8)|(cb); | |
| 1348 | break; | |
| 1349 | default: | |
| 1350 | return (ca+(ca << 4)) << 24; | |
| 1351 | break; | |
| 1352 | } | |
| 1324 | case A8R8G8B8: | |
| 1325 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory | |
| 1326 | return *(((UINT32 *)texture[number].buffer) + to); // get texel color | |
| 1327 | case DXT1: | |
| 1328 | bx = x >> 2; | |
| 1329 | by = y >> 2; | |
| 1330 | x = x & 3; | |
| 1331 | y = y & 3; | |
| 1332 | to = bx + by*(texture[number].sizeu >> 2); | |
| 1333 | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 0); | |
| 1334 | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 1); | |
| 1335 | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 1); | |
| 1336 | s = (y << 3) + (x << 1); | |
| 1337 | c = (codes >> s) & 3; | |
| 1338 | c = c + (color0 > color1 ? 0 : 4); | |
| 1339 | color0m2 = color0 << 1; | |
| 1340 | color1m2 = color1 << 1; | |
| 1341 | switch (c) { | |
| 1342 | case 0: | |
| 1343 | return 0xff000000 + convert_r5g6b5_r8g8b8(color0); | |
| 1353 | 1344 | break; |
| 1354 | case A4R4G4B4: | |
| 1355 | to=dilated0[texture[number].dilate][x]+dilated1[texture[number].dilate][y]; // offset of texel in texture memory | |
| 1356 | a4r4g4b4=*(((UINT16 *)texture[number].buffer)+to); // get texel color | |
| 1357 | return convert_a4r4g4b4_a8r8g8b8(a4r4g4b4); | |
| 1358 | case A1R5G5B5: | |
| 1359 | to=dilated0[texture[number].dilate][x]+dilated1[texture[number].dilate][y]; // offset of texel in texture memory | |
| 1360 | a1r5g5b5=*(((UINT16 *)texture[number].buffer)+to); // get texel color | |
| 1361 | return convert_a1r5g5b5_a8r8g8b8(a1r5g5b5); | |
| 1362 | case R5G6B5: | |
| 1363 | to=dilated0[texture[number].dilate][x]+dilated1[texture[number].dilate][y]; // offset of texel in texture memory | |
| 1364 | r5g6b5=*(((UINT16 *)texture[number].buffer)+to); // get texel color | |
| 1365 | return 0xff000000+convert_r5g6b5_r8g8b8(r5g6b5); | |
| 1366 | case R8G8B8_RECT: | |
| 1367 | to=texture[number].rectangle_pitch*y+(x << 2); | |
| 1368 | return *((UINT32 *)(((UINT8 *)texture[number].buffer)+to)); | |
| 1345 | case 1: | |
| 1346 | return 0xff000000 + convert_r5g6b5_r8g8b8(color1); | |
| 1347 | break; | |
| 1348 | case 2: | |
| 1349 | cb = pal5bit(((color0m2 & 0x003e) + (color1 & 0x001f)) / 3); | |
| 1350 | cg = pal6bit(((color0m2 & 0x0fc0) + (color1 & 0x07e0)) / 3 >> 5); | |
| 1351 | cr = pal5bit(((color0m2 & 0x1f000) + color1) / 3 >> 11); | |
| 1352 | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); | |
| 1353 | break; | |
| 1354 | case 3: | |
| 1355 | cb = pal5bit(((color1m2 & 0x003e) + (color0 & 0x001f)) / 3); | |
| 1356 | cg = pal6bit(((color1m2 & 0x0fc0) + (color0 & 0x07e0)) / 3 >> 5); | |
| 1357 | cr = pal5bit(((color1m2 & 0x1f000) + color0) / 3 >> 11); | |
| 1358 | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); | |
| 1359 | break; | |
| 1360 | case 4: | |
| 1361 | return 0xff000000 + convert_r5g6b5_r8g8b8(color0); | |
| 1362 | break; | |
| 1363 | case 5: | |
| 1364 | return 0xff000000 + convert_r5g6b5_r8g8b8(color1); | |
| 1365 | break; | |
| 1366 | case 6: | |
| 1367 | cb = pal5bit(((color0 & 0x001f) + (color1 & 0x001f)) / 2); | |
| 1368 | cg = pal6bit(((color0 & 0x07e0) + (color1 & 0x07e0)) / 2 >> 5); | |
| 1369 | cr = pal5bit(((color0 & 0xf800) + (color1 & 0xf800)) / 2 >> 11); | |
| 1370 | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); | |
| 1371 | break; | |
| 1369 | 1372 | default: |
| 1370 | return 0xff00ff00; | |
| 1373 | return 0xff000000; | |
| 1374 | break; | |
| 1375 | } | |
| 1376 | case DXT3: | |
| 1377 | bx = x >> 2; | |
| 1378 | by = y >> 2; | |
| 1379 | x = x & 3; | |
| 1380 | y = y & 3; | |
| 1381 | to = (bx + by*(texture[number].sizeu >> 2)) << 1; | |
| 1382 | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 4); | |
| 1383 | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 5); | |
| 1384 | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 3); | |
| 1385 | alphas = *(((UINT64 *)texture[number].buffer) + to); | |
| 1386 | s = (y << 3) + (x << 1); | |
| 1387 | sa = ((y << 2) + x) << 2; | |
| 1388 | c = (codes >> s) & 3; | |
| 1389 | ca = (alphas >> sa) & 15; | |
| 1390 | switch (c) { | |
| 1391 | case 0: | |
| 1392 | return ((ca + (ca << 4)) << 24) + convert_r5g6b5_r8g8b8(color0); | |
| 1393 | break; | |
| 1394 | case 1: | |
| 1395 | return ((ca + (ca << 4)) << 24) + convert_r5g6b5_r8g8b8(color1); | |
| 1396 | break; | |
| 1397 | case 2: | |
| 1398 | cb = pal5bit((2 * (color0 & 0x001f) + (color1 & 0x001f)) / 3); | |
| 1399 | cg = pal6bit((2 * (color0 & 0x07e0) + (color1 & 0x07e0)) / 3 >> 5); | |
| 1400 | cr = pal5bit((2 * (color0 & 0xf800) + (color1 & 0xf800)) / 3 >> 11); | |
| 1401 | return ((ca + (ca << 4)) << 24) | (cr << 16) | (cg << 8) | (cb); | |
| 1402 | break; | |
| 1403 | default: | |
| 1404 | cb = pal5bit(((color0 & 0x001f) + 2 * (color1 & 0x001f)) / 3); | |
| 1405 | cg = pal6bit(((color0 & 0x07e0) + 2 * (color1 & 0x07e0)) / 3 >> 5); | |
| 1406 | cr = pal5bit(((color0 & 0xf800) + 2 * (color1 & 0xf800)) / 3 >> 11); | |
| 1407 | return ((ca + (ca << 4)) << 24) | (cr << 16) | (cg << 8) | (cb); | |
| 1408 | break; | |
| 1409 | } | |
| 1410 | break; | |
| 1411 | case A4R4G4B4: | |
| 1412 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory | |
| 1413 | a4r4g4b4 = *(((UINT16 *)texture[number].buffer) + to); // get texel color | |
| 1414 | return convert_a4r4g4b4_a8r8g8b8(a4r4g4b4); | |
| 1415 | case A1R5G5B5: | |
| 1416 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory | |
| 1417 | a1r5g5b5 = *(((UINT16 *)texture[number].buffer) + to); // get texel color | |
| 1418 | return convert_a1r5g5b5_a8r8g8b8(a1r5g5b5); | |
| 1419 | case R5G6B5: | |
| 1420 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory | |
| 1421 | r5g6b5 = *(((UINT16 *)texture[number].buffer) + to); // get texel color | |
| 1422 | return 0xff000000 + convert_r5g6b5_r8g8b8(r5g6b5); | |
| 1423 | case R8G8B8_RECT: | |
| 1424 | to = texture[number].rectangle_pitch*y + (x << 2); | |
| 1425 | return *((UINT32 *)(((UINT8 *)texture[number].buffer) + to)); | |
| 1426 | case A8R8G8B8_RECT: | |
| 1427 | to = texture[number].rectangle_pitch*y + (x << 2); | |
| 1428 | return *((UINT32 *)(((UINT8 *)texture[number].buffer) + to)); | |
| 1429 | case DXT5: | |
| 1430 | bx = x >> 2; | |
| 1431 | by = y >> 2; | |
| 1432 | x = x & 3; | |
| 1433 | y = y & 3; | |
| 1434 | to = (bx + by*(texture[number].sizeu >> 2)) << 1; | |
| 1435 | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 4); | |
| 1436 | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 5); | |
| 1437 | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 3); | |
| 1438 | alpha0 = *((UINT8 *)(((UINT64 *)texture[number].buffer) + to) + 0); | |
| 1439 | alpha1 = *((UINT8 *)(((UINT64 *)texture[number].buffer) + to) + 1); | |
| 1440 | alphas = *(((UINT64 *)texture[number].buffer) + to); | |
| 1441 | s = (y << 3) + (x << 1); | |
| 1442 | sa = ((y << 2) + x) * 3; | |
| 1443 | c = (codes >> s) & 3; | |
| 1444 | ca = (alphas >> sa) & 7; | |
| 1445 | ca = ca + (alpha0 > alpha1 ? 0 : 8); | |
| 1446 | switch (ca) { | |
| 1447 | case 0: | |
| 1448 | ca = alpha0; | |
| 1449 | break; | |
| 1450 | case 1: | |
| 1451 | ca = alpha1; | |
| 1452 | break; | |
| 1453 | case 2: | |
| 1454 | ca = (6 * alpha0 + 1 * alpha1) / 7; | |
| 1455 | break; | |
| 1456 | case 3: | |
| 1457 | ca = (5 * alpha0 + 2 * alpha1) / 7; | |
| 1458 | break; | |
| 1459 | case 4: | |
| 1460 | ca = (4 * alpha0 + 3 * alpha1) / 7; | |
| 1461 | break; | |
| 1462 | case 5: | |
| 1463 | ca = (3 * alpha0 + 4 * alpha1) / 7; | |
| 1464 | break; | |
| 1465 | case 6: | |
| 1466 | ca = (2 * alpha0 + 5 * alpha1) / 7; | |
| 1467 | break; | |
| 1468 | case 7: | |
| 1469 | ca = (1 * alpha0 + 6 * alpha1) / 7; | |
| 1470 | break; | |
| 1471 | case 8: | |
| 1472 | ca = alpha0; | |
| 1473 | break; | |
| 1474 | case 9: | |
| 1475 | ca = alpha1; | |
| 1476 | break; | |
| 1477 | case 10: | |
| 1478 | ca = (4 * alpha0 + 1 * alpha1) / 5; | |
| 1479 | break; | |
| 1480 | case 11: | |
| 1481 | ca = (3 * alpha0 + 2 * alpha1) / 5; | |
| 1482 | break; | |
| 1483 | case 12: | |
| 1484 | ca = (2 * alpha0 + 3 * alpha1) / 5; | |
| 1485 | break; | |
| 1486 | case 13: | |
| 1487 | ca = (1 * alpha0 + 4 * alpha1) / 5; | |
| 1488 | break; | |
| 1489 | case 14: | |
| 1490 | ca = 0; | |
| 1491 | break; | |
| 1492 | case 15: | |
| 1493 | ca = 255; | |
| 1494 | break; | |
| 1495 | } | |
| 1496 | switch (c) { | |
| 1497 | case 0: | |
| 1498 | return (ca << 24) + convert_r5g6b5_r8g8b8(color0); | |
| 1499 | break; | |
| 1500 | case 1: | |
| 1501 | return (ca << 24) + convert_r5g6b5_r8g8b8(color1); | |
| 1502 | break; | |
| 1503 | case 2: | |
| 1504 | cb = pal5bit((2 * (color0 & 0x001f) + (color1 & 0x001f)) / 3); | |
| 1505 | cg = pal6bit((2 * (color0 & 0x07e0) + (color1 & 0x07e0)) / 3 >> 5); | |
| 1506 | cr = pal5bit((2 * (color0 & 0xf800) + (color1 & 0xf800)) / 3 >> 11); | |
| 1507 | return (ca << 24) | (cr << 16) | (cg << 8) | (cb); | |
| 1508 | break; | |
| 1509 | default: | |
| 1510 | cb = pal5bit(((color0 & 0x001f) + 2 * (color1 & 0x001f)) / 3); | |
| 1511 | cg = pal6bit(((color0 & 0x07e0) + 2 * (color1 & 0x07e0)) / 3 >> 5); | |
| 1512 | cr = pal5bit(((color0 & 0xf800) + 2 * (color1 & 0xf800)) / 3 >> 11); | |
| 1513 | return (ca << 24) | (cr << 16) | (cg << 8) | (cb); | |
| 1514 | break; | |
| 1515 | } | |
| 1516 | default: | |
| 1517 | return 0xff00ff00; | |
| 1371 | 1518 | } |
| 1372 | 1519 | } |
| 1373 | 1520 | |
| r29516 | r29517 | |
| 1616 | 1763 | maddress=method*4; |
| 1617 | 1764 | data=space.read_dword(address); |
| 1618 | 1765 | channel[chanel][subchannel].object.method[method]=data; |
| 1766 | if (maddress == 0x17fc) { | |
| 1767 | indexesleft_count = 0; | |
| 1768 | primitives_count = 0; | |
| 1769 | countlen--; | |
| 1770 | } | |
| 1619 | 1771 | if (maddress == 0x1810) { |
| 1620 | 1772 | // draw vertices |
| 1621 | 1773 | int offset,count,type; |
| r29516 | r29517 | |
| 1629 | 1781 | offset=data & 0xffffff; |
| 1630 | 1782 | count=(data >> 24) & 0xff; |
| 1631 | 1783 | type=channel[chanel][subchannel].object.method[0x17fc/4]; |
| 1632 | tmp=channel[chanel][subchannel].object.method[0x1720/4]; | |
| 1633 | 1784 | dmahand[0]=channel[chanel][subchannel].object.method[0x019c/4]; |
| 1634 | 1785 | dmahand[1]=channel[chanel][subchannel].object.method[0x01a0/4]; |
| 1635 | 1786 | geforce_read_dma_object(dmahand[0],dmaoff[0],smasiz[0]); |
| r29516 | r29517 | |
| 1674 | 1825 | *((UINT32 *)(&xy[m].y))=space.read_dword(vtxbuf_address[0]+(n+m+offset)*vtxbuf_stride[0]+4); |
| 1675 | 1826 | *((UINT32 *)(&z[m]))=space.read_dword(vtxbuf_address[0]+(n+m+offset)*vtxbuf_stride[0]+8); |
| 1676 | 1827 | *((UINT32 *)(&w[m]))=space.read_dword(vtxbuf_address[0]+(n+m+offset)*vtxbuf_stride[0]+12); |
| 1677 | c[m]=space.read_dword(vtxbuf_address[3]+(n+m+offset)*vtxbuf_stride[ | |
| 1828 | c[m]=space.read_dword(vtxbuf_address[3]+(n+m+offset)*vtxbuf_stride[3]+0); // color | |
| 1678 | 1829 | xy[m].p[0]=c[m] & 0xff; // b |
| 1679 | 1830 | xy[m].p[1]=(c[m] & 0xff00) >> 8; // g |
| 1680 | 1831 | xy[m].p[2]=(c[m] & 0xff0000) >> 16; // r |
| r29516 | r29517 | |
| 1711 | 1862 | *((UINT32 *)(&xy[m].y))=space.read_dword(vtxbuf_address[0]+(m+offset)*vtxbuf_stride[0]+4); |
| 1712 | 1863 | *((UINT32 *)(&z[m]))=space.read_dword(vtxbuf_address[0]+(m+offset)*vtxbuf_stride[0]+8); |
| 1713 | 1864 | *((UINT32 *)(&w[m]))=space.read_dword(vtxbuf_address[0]+(m+offset)*vtxbuf_stride[0]+12); |
| 1714 | c[m]=space.read_dword(vtxbuf_address[3]+(m+offset)*vtxbuf_stride[ | |
| 1865 | c[m]=space.read_dword(vtxbuf_address[3]+(m+offset)*vtxbuf_stride[3]+0); // color | |
| 1715 | 1866 | xy[m].p[0]=c[m] & 0xff; // b |
| 1716 | 1867 | xy[m].p[1]=(c[m] & 0xff00) >> 8; // g |
| 1717 | 1868 | xy[m].p[2]=(c[m] & 0xff0000) >> 16; // r |
| r29516 | r29517 | |
| 1731 | 1882 | *((UINT32 *)(&xy[2].y))=space.read_dword(vtxbuf_address[0]+(n+offset)*vtxbuf_stride[0]+4); |
| 1732 | 1883 | *((UINT32 *)(&z[2]))=space.read_dword(vtxbuf_address[0]+(n+offset)*vtxbuf_stride[0]+8); |
| 1733 | 1884 | *((UINT32 *)(&w[2]))=space.read_dword(vtxbuf_address[0]+(n+offset)*vtxbuf_stride[0]+12); |
| 1734 | c[2]=space.read_dword(vtxbuf_address[3]+(n+offset)*vtxbuf_stride[ | |
| 1885 | c[2]=space.read_dword(vtxbuf_address[3]+(n+offset)*vtxbuf_stride[3]+0); // color | |
| 1735 | 1886 | xy[2].p[0]=c[2] & 0xff; // b |
| 1736 | 1887 | xy[2].p[1]=(c[2] & 0xff00) >> 8; // g |
| 1737 | 1888 | xy[2].p[2]=(c[2] & 0xff0000) >> 16; // r |
| r29516 | r29517 | |
| 1760 | 1911 | } |
| 1761 | 1912 | countlen--; |
| 1762 | 1913 | } |
| 1914 | if (maddress == 0x1800) { | |
| 1915 | int vtxbuf_stride[16]; | |
| 1916 | UINT32 vtxbuf_address[16]; | |
| 1917 | UINT32 dmahand[2], dmaoff[2], smasiz[2]; | |
| 1918 | UINT32 type, tmp, n, m, u; | |
| 1919 | render_delegate renderspans; | |
| 1920 | ||
| 1921 | // vertices are selected from the vertex buffer using an array of indexes | |
| 1922 | // each dword after 1800 contains two 16 bit index values to select the vartices | |
| 1923 | type = channel[chanel][subchannel].object.method[0x17fc / 4]; | |
| 1924 | dmahand[0] = channel[chanel][subchannel].object.method[0x019c / 4]; | |
| 1925 | dmahand[1] = channel[chanel][subchannel].object.method[0x01a0 / 4]; | |
| 1926 | geforce_read_dma_object(dmahand[0], dmaoff[0], smasiz[0]); | |
| 1927 | geforce_read_dma_object(dmahand[1], dmaoff[1], smasiz[1]); | |
| 1928 | if (((channel[chanel][subchannel].object.method[0x1e60 / 4] & 7) > 0) && (combiner.used != 0)) { | |
| 1929 | renderspans = render_delegate(FUNC(nv2a_renderer::render_register_combiners), this); | |
| 1930 | } | |
| 1931 | else if (texture[0].enabled) { | |
| 1932 | renderspans = render_delegate(FUNC(nv2a_renderer::render_texture_simple), this); | |
| 1933 | } | |
| 1934 | else | |
| 1935 | renderspans = render_delegate(FUNC(nv2a_renderer::render_color), this); | |
| 1936 | #ifdef LOG_NV2A | |
| 1937 | printf("vertex %d %d %d\n\r", type, offset, count); | |
| 1938 | #endif | |
| 1939 | for (n = 0; n < 16; n++) { | |
| 1940 | #ifdef LOG_NV2A | |
| 1941 | printf(" %08X %08X\n\r", channel[chanel][subchannel].object.method[0x1720 / 4 + n], channel[chanel][subchannel].object.method[0x1760 / 4 + n]); | |
| 1942 | #endif | |
| 1943 | tmp = channel[chanel][subchannel].object.method[0x1760 / 4 + n]; // VTXBUF_FMT | |
| 1944 | //vtxbuf_kind[n]=tmp & 15; | |
| 1945 | //vtxbuf_size[n]=(tmp >> 4) & 15; | |
| 1946 | vtxbuf_stride[n] = (tmp >> 8) & 255; | |
| 1947 | tmp = channel[chanel][subchannel].object.method[0x1720 / 4 + n]; // VTXBUF_OFFSET | |
| 1948 | if (tmp & 0x80000000) | |
| 1949 | vtxbuf_address[n] = (tmp & 0x0fffffff) + dmaoff[1]; | |
| 1950 | else | |
| 1951 | vtxbuf_address[n] = (tmp & 0x0fffffff) + dmaoff[0]; | |
| 1952 | } | |
| 1953 | if (type == nv2a_renderer::QUADS) { | |
| 1954 | while (1) { | |
| 1955 | vertex_t xy[4]; | |
| 1956 | float z[4], w[4]; | |
| 1957 | UINT32 c[4]; | |
| 1958 | ||
| 1959 | // need 4 per object | |
| 1960 | // get remaining | |
| 1961 | while ((indexesleft_count < 4) && (countlen > 0)) { | |
| 1962 | indexesleft[indexesleft_count] = data & 0xffff; | |
| 1963 | indexesleft[indexesleft_count+ 1] = (data >> 16) & 0xffff; | |
| 1964 | indexesleft_count+=2; | |
| 1965 | countlen--; | |
| 1966 | address = address + 4; | |
| 1967 | data = space.read_dword(address); | |
| 1968 | } | |
| 1969 | if ((indexesleft_count < 4) && (countlen == 0)) | |
| 1970 | break; | |
| 1971 | //printf("draw quad\n\r"); | |
| 1972 | for (m = 0; m < 4; m++) { | |
| 1973 | *((UINT32 *)(&xy[m].x)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 0); | |
| 1974 | *((UINT32 *)(&xy[m].y)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 4); | |
| 1975 | *((UINT32 *)(&z[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 8); | |
| 1976 | *((UINT32 *)(&w[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 12); | |
| 1977 | c[m] = space.read_dword(vtxbuf_address[3] + indexesleft[m] * vtxbuf_stride[3] + 0); // color | |
| 1978 | xy[m].p[0] = c[m] & 0xff; // b | |
| 1979 | xy[m].p[1] = (c[m] & 0xff00) >> 8; // g | |
| 1980 | xy[m].p[2] = (c[m] & 0xff0000) >> 16; // r | |
| 1981 | xy[m].p[3] = (c[m] & 0xff000000) >> 24; // a | |
| 1982 | for (u = 0; u < 4; u++) { | |
| 1983 | xy[m].p[4 + u * 2] = 0; | |
| 1984 | xy[m].p[5 + u * 2] = 0; | |
| 1985 | if (texture[u].enabled) { | |
| 1986 | *((UINT32 *)(&xy[m].p[4 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 0); | |
| 1987 | *((UINT32 *)(&xy[m].p[5 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 4); | |
| 1988 | } | |
| 1989 | } | |
| 1990 | } | |
| 1991 | ||
| 1992 | render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv | |
| 1993 | /*myline(fb,xy[0].x,xy[0].y,xy[1].x,xy[1].y); | |
| 1994 | myline(fb,xy[1].x,xy[1].y,xy[2].x,xy[2].y); | |
| 1995 | myline(fb,xy[2].x,xy[2].y,xy[3].x,xy[3].y); | |
| 1996 | myline(fb,xy[3].x,xy[3].y,xy[0].x,xy[0].y);*/ | |
| 1997 | #ifdef LOG_NV2A | |
| 1998 | printf(" (%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)\n\r", xy[0].x, xy[0].y, z[0], xy[1].x, xy[1].y, z[1], xy[2].x, xy[2].y, z[2], xy[3].x, xy[3].y, z[3]); | |
| 1999 | #endif | |
| 2000 | for (m = 4; m < indexesleft_count; m++) | |
| 2001 | indexesleft[m - 4] = indexesleft[m]; | |
| 2002 | indexesleft_count = indexesleft_count - 4; | |
| 2003 | } | |
| 2004 | wait(); | |
| 2005 | } | |
| 2006 | else if (type == nv2a_renderer::TRIANGLES) { | |
| 2007 | while (1) { | |
| 2008 | vertex_t xy[4]; | |
| 2009 | float z[4], w[4]; | |
| 2010 | UINT32 c[4]; | |
| 2011 | ||
| 2012 | // need 3 dwords per object | |
| 2013 | // get remaining | |
| 2014 | while ((indexesleft_count < 3) && (countlen > 0)) { | |
| 2015 | indexesleft[indexesleft_count] = data & 0xffff; | |
| 2016 | indexesleft[indexesleft_count + 1] = (data >> 16) & 0xffff; | |
| 2017 | indexesleft_count += 2; | |
| 2018 | countlen--; | |
| 2019 | address = address + 4; | |
| 2020 | data = space.read_dword(address); | |
| 2021 | } | |
| 2022 | if ((indexesleft_count < 3) && (countlen == 0)) | |
| 2023 | break; | |
| 2024 | //printf("draw triangle\n\r"); | |
| 2025 | for (m = 0; m < 3; m++) { | |
| 2026 | *((UINT32 *)(&xy[m].x)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 0); | |
| 2027 | *((UINT32 *)(&xy[m].y)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 4); | |
| 2028 | *((UINT32 *)(&z[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 8); | |
| 2029 | *((UINT32 *)(&w[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 12); | |
| 2030 | c[m] = space.read_dword(vtxbuf_address[3] + indexesleft[m] * vtxbuf_stride[3] + 0); // color | |
| 2031 | xy[m].p[0] = c[m] & 0xff; // b | |
| 2032 | xy[m].p[1] = (c[m] & 0xff00) >> 8; // g | |
| 2033 | xy[m].p[2] = (c[m] & 0xff0000) >> 16; // r | |
| 2034 | xy[m].p[3] = (c[m] & 0xff000000) >> 24; // a | |
| 2035 | for (u = 0; u < 4; u++) { | |
| 2036 | xy[m].p[4 + u * 2] = 0; | |
| 2037 | xy[m].p[5 + u * 2] = 0; | |
| 2038 | if (texture[u].enabled) { | |
| 2039 | *((UINT32 *)(&xy[m].p[4 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 0); | |
| 2040 | *((UINT32 *)(&xy[m].p[5 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 4); | |
| 2041 | } | |
| 2042 | } | |
| 2043 | } | |
| 2044 | ||
| 2045 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[0], xy[1], xy[2]); // 4 rgba, 4 texture units 2 uv | |
| 2046 | /*myline(fb,xy[0].x,xy[0].y,xy[1].x,xy[1].y); | |
| 2047 | myline(fb,xy[1].x,xy[1].y,xy[2].x,xy[2].y); | |
| 2048 | myline(fb,xy[2].x,xy[2].y,xy[3].x,xy[3].y);*/ | |
| 2049 | #ifdef LOG_NV2A | |
| 2050 | printf(" (%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)\n\r", xy[0].x, xy[0].y, z[0], xy[1].x, xy[1].y, z[1], xy[2].x, xy[2].y, z[2]); | |
| 2051 | #endif | |
| 2052 | for (m = 3; m < indexesleft_count; m++) | |
| 2053 | indexesleft[m - 3] = indexesleft[m]; | |
| 2054 | indexesleft_count = indexesleft_count - 3; | |
| 2055 | } | |
| 2056 | wait(); | |
| 2057 | } | |
| 2058 | else if (type == nv2a_renderer::TRIANGLE_STRIP) { | |
| 2059 | while (1) { | |
| 2060 | vertex_t xy[4]; | |
| 2061 | float z[4], w[4]; | |
| 2062 | UINT32 c[4]; | |
| 2063 | ||
| 2064 | // need 3 dwords per object | |
| 2065 | // get remaining | |
| 2066 | while ((indexesleft_count < 3) && (countlen > 0)) { | |
| 2067 | indexesleft[indexesleft_count] = data & 0xffff; | |
| 2068 | indexesleft[indexesleft_count + 1] = (data >> 16) & 0xffff; | |
| 2069 | indexesleft_count += 2; | |
| 2070 | countlen--; | |
| 2071 | address = address + 4; | |
| 2072 | data = space.read_dword(address); | |
| 2073 | } | |
| 2074 | if ((indexesleft_count < 3) && (countlen == 0)) | |
| 2075 | break; | |
| 2076 | //printf("draw triangle\n\r"); | |
| 2077 | for (m = 0; m < 3; m++) { | |
| 2078 | *((UINT32 *)(&xy[m].x)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 0); | |
| 2079 | *((UINT32 *)(&xy[m].y)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 4); | |
| 2080 | *((UINT32 *)(&z[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 8); | |
| 2081 | *((UINT32 *)(&w[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 12); | |
| 2082 | c[m] = space.read_dword(vtxbuf_address[3] + indexesleft[m] * vtxbuf_stride[3] + 0); // color | |
| 2083 | xy[m].p[0] = c[m] & 0xff; // b | |
| 2084 | xy[m].p[1] = (c[m] & 0xff00) >> 8; // g | |
| 2085 | xy[m].p[2] = (c[m] & 0xff0000) >> 16; // r | |
| 2086 | xy[m].p[3] = (c[m] & 0xff000000) >> 24; // a | |
| 2087 | for (u = 0; u < 4; u++) { | |
| 2088 | xy[m].p[4 + u * 2] = 0; | |
| 2089 | xy[m].p[5 + u * 2] = 0; | |
| 2090 | if (texture[u].enabled) { | |
| 2091 | *((UINT32 *)(&xy[m].p[4 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 0); | |
| 2092 | *((UINT32 *)(&xy[m].p[5 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 4); | |
| 2093 | } | |
| 2094 | } | |
| 2095 | } | |
| 2096 | ||
| 2097 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[primitives_count & 1], xy[~primitives_count & 1], xy[2]); // 012,102,012,102... | |
| 2098 | /*myline(fb,xy[0].x,xy[0].y,xy[1].x,xy[1].y); | |
| 2099 | myline(fb,xy[1].x,xy[1].y,xy[2].x,xy[2].y); | |
| 2100 | myline(fb,xy[2].x,xy[2].y,xy[3].x,xy[3].y);*/ | |
| 2101 | #ifdef LOG_NV2A | |
| 2102 | printf(" (%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)\n\r", xy[0].x, xy[0].y, z[0], xy[1].x, xy[1].y, z[1], xy[2].x, xy[2].y, z[2]); | |
| 2103 | #endif | |
| 2104 | primitives_count++; | |
| 2105 | for (m = 1; m < indexesleft_count; m++) | |
| 2106 | indexesleft[m - 1] = indexesleft[m]; | |
| 2107 | indexesleft_count = indexesleft_count - 1; | |
| 2108 | } | |
| 2109 | wait(); | |
| 2110 | } | |
| 2111 | else { | |
| 2112 | logerror("Unsupported primitive %d for method 0x1800\n", type); | |
| 2113 | countlen = 0; | |
| 2114 | } | |
| 2115 | } | |
| 1763 | 2116 | if (maddress == 0x1818) { |
| 1764 | 2117 | int n,m,u,vwords; |
| 1765 | 2118 | int vattrpos[16]; |
| r29516 | r29517 | |
| 1900 | 2253 | } |
| 1901 | 2254 | for (n=2;countlen > 0;n++) { |
| 1902 | 2255 | // put vertex n data in element 2 of arrays |
| 1903 | // put vertex n data in element 2 of arrays | |
| 1904 | 2256 | // position |
| 1905 | 2257 | *((UINT32 *)(&xy[2].x))=space.read_dword(address+vattrpos[0]*4+0); |
| 1906 | 2258 | *((UINT32 *)(&xy[2].y))=space.read_dword(address+vattrpos[0]*4+4); |
| r29516 | r29517 | |
| 2055 | 2407 | wait(); |
| 2056 | 2408 | } else { |
| 2057 | 2409 | logerror("Unsupported primitive %d for method 0x1818\n",type); |
| 2410 | countlen = 0; | |
| 2058 | 2411 | } |
| 2059 | 2412 | } |
| 2413 | if ((maddress >= 0x1760) && (maddress < 0x17A0)) { | |
| 2414 | int bit=method-0x1760/4; | |
| 2415 | ||
| 2416 | data=data & 255; | |
| 2417 | if (data > 15) | |
| 2418 | enabled_vertex_attributes |= (1 << bit); | |
| 2419 | else | |
| 2420 | enabled_vertex_attributes &= ~(1 << bit); | |
| 2421 | switch (data & 15) { | |
| 2422 | case 0: | |
| 2423 | words_vertex_attributes[bit]=(((data >> 4) + 3) & 15) >> 2; | |
| 2424 | break; | |
| 2425 | case nv2a_renderer::FLOAT: | |
| 2426 | words_vertex_attributes[bit]=(data >> 4); | |
| 2427 | break; | |
| 2428 | case nv2a_renderer::UBYTE: | |
| 2429 | words_vertex_attributes[bit]=(((data >> 4) + 3) & 15) >> 2; | |
| 2430 | break; | |
| 2431 | case nv2a_renderer::USHORT: | |
| 2432 | words_vertex_attributes[bit]=(((data >> 4) + 1) & 15) >> 1; | |
| 2433 | break; | |
| 2434 | default: | |
| 2435 | words_vertex_attributes[bit]=0; | |
| 2436 | } | |
| 2437 | countlen--; | |
| 2438 | } | |
| 2060 | 2439 | if ((maddress == 0x1d6c) || (maddress == 0x1d70) || (maddress == 0x1a4)) |
| 2061 | 2440 | countlen--; |
| 2062 | 2441 | if (maddress == 0x1d70) { |
| r29516 | r29517 | |
| 2124 | 2503 | texture[unit].sizew=1 << basesizew; |
| 2125 | 2504 | texture[unit].dilate=dilatechose[(basesizeu << 4)+basesizev]; |
| 2126 | 2505 | texture[unit].format=format; |
| 2506 | if (debug_grab_texttype == format) { | |
| 2507 | FILE *f; | |
| 2508 | int written; | |
| 2509 | ||
| 2510 | debug_grab_texttype = -1; | |
| 2511 | f = fopen(debug_grab_textfile, "wb"); | |
| 2512 | if (f) { | |
| 2513 | written=(int)fwrite(texture[unit].buffer, texture[unit].sizeu*texture[unit].sizev*4, 1, f); | |
| 2514 | fclose(f); | |
| 2515 | logerror("Written %d bytes of texture to specified file\n", written); | |
| 2516 | } else | |
| 2517 | logerror("Unable to save texture to specified file\n"); | |
| 2518 | } | |
| 2127 | 2519 | } |
| 2128 | 2520 | if (maddress == 0x1b0c) { |
| 2129 | 2521 | // enable texture |
| r29516 | r29517 | |
| 2137 | 2529 | } |
| 2138 | 2530 | countlen--; |
| 2139 | 2531 | } |
| 2140 | if ((maddress >= 0x1760) && (maddress < 0x17A0)) { | |
| 2141 | int bit=method-0x1760/4; | |
| 2142 | ||
| 2143 | data=data & 255; | |
| 2144 | if (data > 15) | |
| 2145 | enabled_vertex_attributes |= (1 << bit); | |
| 2532 | // modelview matrix | |
| 2533 | if ((maddress >= 0x0480) && (maddress < 0x04c0)) { | |
| 2534 | maddress = (maddress - 0x0480) / 4; | |
| 2535 | *(UINT32 *)(&matrix.modelview[maddress]) = data; | |
| 2536 | countlen--; | |
| 2537 | } | |
| 2538 | // inverse modelview matrix | |
| 2539 | if ((maddress >= 0x0580) && (maddress < 0x05c0)) { | |
| 2540 | maddress = (maddress - 0x0580) / 4; | |
| 2541 | *(UINT32 *)(&matrix.modelview_inverse[maddress]) = data; | |
| 2542 | countlen--; | |
| 2543 | } | |
| 2544 | // projection matrix | |
| 2545 | if ((maddress >= 0x0680) && (maddress < 0x06c0)) { | |
| 2546 | maddress = (maddress - 0x0680) / 4; | |
| 2547 | *(UINT32 *)(&matrix.projection[maddress]) = data; | |
| 2548 | countlen--; | |
| 2549 | } | |
| 2550 | // viewport translate | |
| 2551 | if ((maddress >= 0x0a20) && (maddress < 0x0a30)) { | |
| 2552 | maddress = (maddress - 0x0a20) / 4; | |
| 2553 | *(UINT32 *)(&matrix.translate[maddress]) = data; | |
| 2554 | countlen--; | |
| 2555 | } | |
| 2556 | // viewport scale | |
| 2557 | if ((maddress >= 0x0af0) && (maddress < 0x0b00)) { | |
| 2558 | maddress = (maddress - 0x0af0) / 4; | |
| 2559 | *(UINT32 *)(&matrix.scale[maddress]) = data; | |
| 2560 | countlen--; | |
| 2561 | } | |
| 2562 | // Vertex program (shader) | |
| 2563 | if (maddress == 0x1e94) { | |
| 2564 | /*if (data == 2) | |
| 2565 | logerror("Enabled vertex program\n"); | |
| 2566 | else if (data == 4) | |
| 2567 | logerror("Enabled fixed function pipeline\n"); | |
| 2568 | else if (data == 6) | |
| 2569 | logerror("Enabled both fixed function pipeline and vertex program ?\n"); | |
| 2146 | 2570 | else |
| 2147 | enabled_vertex_attributes &= ~(1 << bit); | |
| 2148 | switch (data & 15) { | |
| 2149 | case 0: | |
| 2150 | words_vertex_attributes[bit]=(((data >> 4) + 3) & 15) >> 2; | |
| 2151 | break; | |
| 2152 | case nv2a_renderer::FLOAT: | |
| 2153 | words_vertex_attributes[bit]=(data >> 4); | |
| 2154 | break; | |
| 2155 | case nv2a_renderer::UBYTE: | |
| 2156 | words_vertex_attributes[bit]=(((data >> 4) + 3) & 15) >> 2; | |
| 2157 | break; | |
| 2158 | case nv2a_renderer::USHORT: | |
| 2159 | words_vertex_attributes[bit]=(((data >> 4) + 1) & 15) >> 1; | |
| 2160 | break; | |
| 2161 | default: | |
| 2162 | words_vertex_attributes[bit]=0; | |
| 2163 | } | |
| 2571 | logerror("Unknown value %d to method 0x1e94\n",data);*/ | |
| 2572 | countlen--; | |
| 2164 | 2573 | } |
| 2574 | if (maddress == 0x1e9c) { | |
| 2575 | //logerror("VP_UPLOAD_FROM_ID %d\n",data); | |
| 2576 | vertexprogram.upload_instruction=data*4; | |
| 2577 | countlen--; | |
| 2578 | } | |
| 2579 | if (maddress == 0x1ea0) { | |
| 2580 | //logerror("VP_START_FROM_ID %d\n",data); | |
| 2581 | vertexprogram.instructions=vertexprogram.upload_instruction/4; | |
| 2582 | countlen--; | |
| 2583 | } | |
| 2584 | if (maddress == 0x1ea4) { | |
| 2585 | //logerror("VP_UPLOAD_CONST_ID %d\n",data); | |
| 2586 | vertexprogram.upload_parameter=data; | |
| 2587 | countlen--; | |
| 2588 | } | |
| 2589 | if ((maddress >= 0x0b00) && (maddress < 0x0b80)) { | |
| 2590 | //logerror("VP_UPLOAD_INST\n"); | |
| 2591 | if (vertexprogram.upload_instruction < 1024) | |
| 2592 | vertexprogram.instruction[vertexprogram.upload_instruction]=data; | |
| 2593 | else | |
| 2594 | logerror("Need to increase size of vertexprogram.instruction to %d\n\r", vertexprogram.upload_parameter); | |
| 2595 | vertexprogram.upload_instruction++; | |
| 2596 | } | |
| 2597 | if ((maddress >= 0x0b80) && (maddress < 0x0c00)) { | |
| 2598 | //logerror("VP_UPLOAD_CONST\n"); | |
| 2599 | if (vertexprogram.upload_parameter < 1024) | |
| 2600 | vertexprogram.parameter[vertexprogram.upload_parameter] = data; | |
| 2601 | else | |
| 2602 | logerror("Need to increase size of vertexprogram.parameter to %d\n\r", vertexprogram.upload_parameter); | |
| 2603 | vertexprogram.upload_parameter++; | |
| 2604 | } | |
| 2605 | // Register combiners | |
| 2165 | 2606 | if (maddress == 0x1e60) { |
| 2166 | 2607 | combiner.stages=data & 15; |
| 2167 | 2608 | countlen--; |
| r29516 | r29517 | |
| 2290 | 2731 | return combiner.used; |
| 2291 | 2732 | } |
| 2292 | 2733 | |
| 2734 | void nv2a_renderer::debug_grab_texture(int type, const char *filename) | |
| 2735 | { | |
| 2736 | debug_grab_texttype = type; | |
| 2737 | if (debug_grab_textfile == NULL) | |
| 2738 | debug_grab_textfile = (char *)malloc(128); | |
| 2739 | strncpy(debug_grab_textfile, filename, 127); | |
| 2740 | } | |
| 2741 | ||
| 2293 | 2742 | void nv2a_renderer::savestate_items() |
| 2294 | 2743 | { |
| 2295 | 2744 | } |
| r29516 | r29517 | |
| 3008 | 3457 | } |
| 3009 | 3458 | } |
| 3010 | 3459 | |
| 3460 | void chihiro_state::debug_grab_texture(int type, char *filename) | |
| 3461 | { | |
| 3462 | nvidia_nv2a->debug_grab_texture(type, filename); | |
| 3463 | } | |
| 3464 | ||
| 3011 | 3465 | void chihiro_state::vblank_callback(screen_device &screen, bool state) |
| 3012 | 3466 | { |
| 3013 | 3467 | nvidia_nv2a->vblank_callback(screen,state); |
| r29516 | r29517 | |
| 3338 | 3792 | READ32_MEMBER( chihiro_state::audio_apu_r ) |
| 3339 | 3793 | { |
| 3340 | 3794 | logerror("Audio_APU: read from %08X mask %08X\n",0xfe800000+offset*4,mem_mask); |
| 3341 | if (offset == 0x20010/4) | |
| 3795 | if (offset == 0x20010/4) // some kind of internal counter or state value | |
| 3342 | 3796 | return 0x20+4+8+0x48+0x80; |
| 3343 | return | |
| 3797 | return apust.memory[offset]; | |
| 3344 | 3798 | } |
| 3345 | 3799 | |
| 3346 | 3800 | WRITE32_MEMBER( chihiro_state::audio_apu_w ) |
| 3347 | 3801 | { |
| 3802 | //UINT32 old; | |
| 3803 | UINT32 v; | |
| 3804 | ||
| 3348 | 3805 | logerror("Audio_APU: write at %08X mask %08X value %08X\n",0xfe800000+offset*4,mem_mask,data); |
| 3349 | if (offset == 0x2040/4) | |
| 3350 | apust.memory0_sgaddress=data; | |
| 3351 | if (offset == 0x20d4/4) { | |
| 3352 | apust.memory0_sgblocks=data; | |
| 3353 | apust.memory0_address=apust.space->read_dword(apust.memory0_sgaddress); | |
| 3806 | //old = apust.memory[offset]; | |
| 3807 | apust.memory[offset] = data; | |
| 3808 | if (offset == 0x02040/4) // address of memory area with scatter-gather info (gpdsp scratch dma) | |
| 3809 | apust.gpdsp_sgaddress=data; | |
| 3810 | if (offset == 0x020d4/4) { // block count (gpdsp) | |
| 3811 | apust.gpdsp_sgblocks=data; | |
| 3812 | apust.gpdsp_address=apust.space->read_dword(apust.gpdsp_sgaddress); // memory address of first block | |
| 3354 | 3813 | apust.timer->enable(); |
| 3355 | 3814 | apust.timer->adjust(attotime::from_msec(1),0,attotime::from_msec(1)); |
| 3356 | 3815 | } |
| 3357 | if (offset == 0x2048/4) | |
| 3358 | apust.memory1_sgaddress=data; | |
| 3359 | if (offset == 0x20dc/4) | |
| 3360 | apust.memory1_sgblocks=data; | |
| 3816 | if (offset == 0x02048 / 4) // (epdsp scratch dma) | |
| 3817 | apust.epdsp_sgaddress=data; | |
| 3818 | if (offset == 0x020dc / 4) // (epdsp) | |
| 3819 | apust.epdsp_sgblocks=data; | |
| 3820 | if (offset == 0x0204c / 4) // address of memory area with information about blocks | |
| 3821 | apust.unknown_sgaddress = data; | |
| 3822 | if (offset == 0x020e0 / 4) // block count - 1 | |
| 3823 | apust.unknown_sgblocks = data; | |
| 3824 | if (offset == 0x0202c / 4) { // address of memory area with 0x80 bytes for each voice | |
| 3825 | apust.voicedata_address = data; | |
| 3826 | return; | |
| 3827 | } | |
| 3828 | if (offset == 0x04024 / 4) // offset in memory area indicated by 0x204c (analog output ?) | |
| 3829 | return; | |
| 3830 | if (offset == 0x04034 / 4) // size | |
| 3831 | return; | |
| 3832 | if (offset == 0x04028 / 4) // offset in memory area indicated by 0x204c (digital output ?) | |
| 3833 | return; | |
| 3834 | if (offset == 0x04038 / 4) // size | |
| 3835 | return; | |
| 3836 | if (offset == 0x20804 / 4) { // block number for scatter-gather heap that stores sampled audio to be played | |
| 3837 | if (data >= 1024) { | |
| 3838 | logerror("Audio_APU: sg block number too high, increase size of voices_heap_blockaddr\n"); | |
| 3839 | apust.memory[offset] = 1023; | |
| 3840 | } | |
| 3841 | return; | |
| 3842 | } | |
| 3843 | if (offset == 0x20808 / 4) { // block address for scatter-gather heap that stores sampled audio to be played | |
| 3844 | apust.voices_heap_blockaddr[apust.memory[0x20804 / 4]] = data; | |
| 3845 | return; | |
| 3846 | } | |
| 3847 | if (offset == 0x202f8 / 4) { // voice number for parameters ? | |
| 3848 | apust.voice_number = data; | |
| 3849 | return; | |
| 3850 | } | |
| 3851 | if (offset == 0x202fc / 4) // 1 when accessing voice parameters 0 otherwise | |
| 3852 | return; | |
| 3853 | if (offset == 0x20304 / 4) { // format | |
| 3854 | /* | |
| 3855 | bits 28-31 sample format: | |
| 3856 | 0 8-bit pcm | |
| 3857 | 5 16-bit pcm | |
| 3858 | 10 adpcm ? | |
| 3859 | 14 24-bit pcm | |
| 3860 | 15 32-bit pcm | |
| 3861 | bits 16-20 number of channels - 1: | |
| 3862 | 0 mono | |
| 3863 | 1 stereo | |
| 3864 | */ | |
| 3865 | return; | |
| 3866 | } | |
| 3867 | if (offset == 0x2037c / 4) { // value related to sample rate | |
| 3868 | INT16 v = (INT16)(data >> 16); // upper 16 bits as a signed 16 bit value | |
| 3869 | float vv = ((float)v) / 4096.0; // divide by 4096 | |
| 3870 | float vvv = powf(2, vv); // two to the vv | |
| 3871 | int f = vvv*48000.0; // sample rate | |
| 3872 | apust.voices_frequency[apust.voice_number] = f; | |
| 3873 | return; | |
| 3874 | } | |
| 3875 | if (offset == 0x203a0 / 4) // start offset of data in scatter-gather heap | |
| 3876 | return; | |
| 3877 | if (offset == 0x203a4 / 4) { // first sample to play | |
| 3878 | apust.voices_position_start[apust.voice_number] = data*1000; | |
| 3879 | return; | |
| 3880 | } | |
| 3881 | if (offset == 0x203dc / 4) { // last sample to play | |
| 3882 | apust.voices_position_end[apust.voice_number] = data*1000; | |
| 3883 | return; | |
| 3884 | } | |
| 3885 | if (offset == 0x2010c / 4) // voice processor 0 idle 1 not idle ? | |
| 3886 | return; | |
| 3887 | if (offset == 0x20124 / 4) { // voice number to activate ? | |
| 3888 | v = apust.voice_number; | |
| 3889 | apust.voices_active[v >> 6] |= ((UINT64)1 << (v & 63)); | |
| 3890 | apust.voices_position[v] = apust.voices_position_start[apust.voice_number]; | |
| 3891 | apust.voices_position_increment[apust.voice_number] = apust.voices_frequency[apust.voice_number]; | |
| 3892 | return; | |
| 3893 | } | |
| 3894 | if (offset == 0x20128 / 4) { // voice number to deactivate ? | |
| 3895 | v = apust.voice_number; | |
| 3896 | apust.voices_active[v >> 6] &= ~(1 << (v & 63)); | |
| 3897 | return; | |
| 3898 | } | |
| 3899 | if (offset == 0x20140 / 4) // voice number to ? | |
| 3900 | return; | |
| 3901 | if ((offset >= 0x20200 / 4) && (offset < 0x20280 / 4)) // headroom for each of the 32 mixbins | |
| 3902 | return; | |
| 3903 | if (offset == 0x20280 / 4) // hrtf headroom ? | |
| 3904 | return; | |
| 3361 | 3905 | } |
| 3362 | 3906 | |
| 3363 | 3907 | READ32_MEMBER( chihiro_state::audio_ac93_r ) |
| r29516 | r29517 | |
| 3405 | 3949 | |
| 3406 | 3950 | TIMER_CALLBACK_MEMBER(chihiro_state::audio_apu_timer) |
| 3407 | 3951 | { |
| 3408 | int cmd=apust.space->read_dword(apust.memory0_address+0x800+0x10); | |
| 3952 | int cmd; | |
| 3953 | int bb, b, v; | |
| 3954 | UINT64 bv; | |
| 3955 | UINT32 phys; | |
| 3956 | ||
| 3957 | cmd=apust.space->read_dword(apust.gpdsp_address+0x800+0x10); | |
| 3409 | 3958 | if (cmd == 3) |
| 3410 | apust.space->write_dword(apust. | |
| 3959 | apust.space->write_dword(apust.gpdsp_address+0x800+0x10,0); | |
| 3411 | 3960 | /*else |
| 3412 | logerror("Audio_APU: unexpected value at address %d\n",apust.memory0_address+0x800+0x10);*/ | |
| 3961 | logerror("Audio_APU: unexpected value at address %d\n",apust.gpdsp_address+0x800+0x10);*/ | |
| 3962 | for (b = 0; b < 4; b++) { | |
| 3963 | bv = 1; | |
| 3964 | for (bb = 0; bb < 64; bb++) { | |
| 3965 | if (apust.voices_active[b] & bv) { | |
| 3966 | v = bb + (b << 6); | |
| 3967 | apust.voices_position[v] += apust.voices_position_increment[v]; | |
| 3968 | while (apust.voices_position[v] >= apust.voices_position_end[v]) | |
| 3969 | apust.voices_position[v] = apust.voices_position_start[v] + apust.voices_position[v] - apust.voices_position_end[v] - 1000; | |
| 3970 | phys = apust.voicedata_address + 0x80 * v; | |
| 3971 | apust.space->write_dword(phys + 0x58, apust.voices_position[v] / 1000); | |
| 3972 | } | |
| 3973 | bv = bv << 1; | |
| 3974 | } | |
| 3975 | } | |
| 3413 | 3976 | } |
| 3414 | 3977 | |
| 3415 | 3978 | /* |
| r29516 | r29517 | |
| 3902 | 4465 | if (chihiro_devs.dimmboard != NULL) { |
| 3903 | 4466 | dimm_board_memory=chihiro_devs.dimmboard->memory(dimm_board_memory_size); |
| 3904 | 4467 | } |
| 3905 | apust.space=&m_maincpu->space(); | |
| 4468 | memset(apust.memory, 0, sizeof(apust.memory)); | |
| 4469 | memset(apust.voices_heap_blockaddr, 0, sizeof(apust.voices_heap_blockaddr)); | |
| 4470 | memset(apust.voices_active, 0, sizeof(apust.voices_active)); | |
| 4471 | memset(apust.voices_position, 0, sizeof(apust.voices_position)); | |
| 4472 | memset(apust.voices_position_start, 0, sizeof(apust.voices_position_start)); | |
| 4473 | memset(apust.voices_position_end, 0, sizeof(apust.voices_position_end)); | |
| 4474 | memset(apust.voices_position_increment, 0, sizeof(apust.voices_position_increment)); | |
| 4475 | apust.space = &m_maincpu->space(); | |
| 3906 | 4476 | apust.timer=machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(chihiro_state::audio_apu_timer),this),(void *)"APU Timer"); |
| 3907 | 4477 | apust.timer->enable(false); |
| 3908 | 4478 | if (machine().debug_flags & DEBUG_FLAG_ENABLED) |
| r29516 | r29517 | |
|---|---|---|
| 1976 | 1976 | floatx80 a = ST(0); |
| 1977 | 1977 | floatx80 b = ST(1); |
| 1978 | 1978 | |
| 1979 | m_x87_sw &= ~X87_SW_C | |
| 1979 | m_x87_sw &= ~X87_SW_C2; | |
| 1980 | 1980 | |
| 1981 | 1981 | // TODO: Implement Cx bits |
| 1982 | 1982 | result = floatx80_rem(a, b); |
| r29516 | r29517 | |
| 2002 | 2002 | floatx80 a = ST(0); |
| 2003 | 2003 | floatx80 b = ST(1); |
| 2004 | 2004 | |
| 2005 | m_x87_sw &= ~X87_SW_C | |
| 2005 | m_x87_sw &= ~X87_SW_C2; | |
| 2006 | 2006 | |
| 2007 | 2007 | // TODO: Implement Cx bits |
| 2008 | 2008 | result = floatx80_rem(a, b); |
| Previous | 199869 Revisions | Next |