trunk/src/mame/drivers/chihiro.c
| r242208 | r242209 | |
| 370 | 370 | #include "debug/debugcmd.h" |
| 371 | 371 | #include "debug/debugcpu.h" |
| 372 | 372 | #include "osdcore.h" |
| 373 | #include "includes/chihiro.h" |
| 373 | 374 | |
| 374 | 375 | #define LOG_PCI |
| 375 | 376 | //#define LOG_OHCI |
| 376 | | //#define LOG_NV2A |
| 377 | 377 | //#define LOG_BASEBOARD |
| 378 | 378 | |
| 379 | | class nv2a_renderer; // forw. dec. |
| 380 | | struct nvidia_object_data |
| 381 | | { |
| 382 | | nv2a_renderer *data; |
| 383 | | }; |
| 384 | | |
| 385 | 379 | class chihiro_state : public driver_device |
| 386 | 380 | { |
| 387 | 381 | public: |
| r242208 | r242209 | |
| 391 | 385 | debug_irq_active(false), |
| 392 | 386 | m_maincpu(*this, "maincpu") { } |
| 393 | 387 | |
| 394 | | DECLARE_READ32_MEMBER( geforce_r ); |
| 395 | | DECLARE_WRITE32_MEMBER( geforce_w ); |
| 396 | | DECLARE_READ32_MEMBER( usbctrl_r ); |
| 397 | | DECLARE_WRITE32_MEMBER( usbctrl_w ); |
| 398 | | DECLARE_READ32_MEMBER( smbus_r ); |
| 399 | | DECLARE_WRITE32_MEMBER( smbus_w ); |
| 400 | | DECLARE_READ32_MEMBER( mediaboard_r ); |
| 401 | | DECLARE_WRITE32_MEMBER( mediaboard_w ); |
| 402 | | DECLARE_READ32_MEMBER( audio_apu_r ); |
| 403 | | DECLARE_WRITE32_MEMBER( audio_apu_w ); |
| 404 | | DECLARE_READ32_MEMBER( audio_ac93_r ); |
| 405 | | DECLARE_WRITE32_MEMBER( audio_ac93_w ); |
| 406 | | DECLARE_READ32_MEMBER( dummy_r ); |
| 407 | | DECLARE_WRITE32_MEMBER( dummy_w ); |
| 388 | DECLARE_READ32_MEMBER(geforce_r); |
| 389 | DECLARE_WRITE32_MEMBER(geforce_w); |
| 390 | DECLARE_READ32_MEMBER(usbctrl_r); |
| 391 | DECLARE_WRITE32_MEMBER(usbctrl_w); |
| 392 | DECLARE_READ32_MEMBER(smbus_r); |
| 393 | DECLARE_WRITE32_MEMBER(smbus_w); |
| 394 | DECLARE_READ32_MEMBER(mediaboard_r); |
| 395 | DECLARE_WRITE32_MEMBER(mediaboard_w); |
| 396 | DECLARE_READ32_MEMBER(audio_apu_r); |
| 397 | DECLARE_WRITE32_MEMBER(audio_apu_w); |
| 398 | DECLARE_READ32_MEMBER(audio_ac93_r); |
| 399 | DECLARE_WRITE32_MEMBER(audio_ac93_w); |
| 400 | DECLARE_READ32_MEMBER(dummy_r); |
| 401 | DECLARE_WRITE32_MEMBER(dummy_w); |
| 408 | 402 | |
| 409 | | void smbus_register_device(int address,int (*handler)(chihiro_state &chs,int command,int rw,int data)); |
| 410 | | int smbus_pic16lc(int command,int rw,int data); |
| 411 | | int smbus_cx25871(int command,int rw,int data); |
| 412 | | int smbus_eeprom(int command,int rw,int data); |
| 413 | | void baseboard_ide_event(int type,UINT8 *read,UINT8 *write); |
| 403 | void smbus_register_device(int address, int(*handler)(chihiro_state &chs, int command, int rw, int data)); |
| 404 | int smbus_pic16lc(int command, int rw, int data); |
| 405 | int smbus_cx25871(int command, int rw, int data); |
| 406 | int smbus_eeprom(int command, int rw, int data); |
| 407 | void baseboard_ide_event(int type, UINT8 *read, UINT8 *write); |
| 414 | 408 | UINT8 *baseboard_ide_dimmboard(UINT32 lba); |
| 415 | | void dword_write_le(UINT8 *addr,UINT32 d); |
| 416 | | void word_write_le(UINT8 *addr,UINT16 d); |
| 417 | | void debug_generate_irq(int irq,bool active); |
| 409 | void dword_write_le(UINT8 *addr, UINT32 d); |
| 410 | void word_write_le(UINT8 *addr, UINT16 d); |
| 411 | void debug_generate_irq(int irq, bool active); |
| 418 | 412 | |
| 419 | 413 | void vblank_callback(screen_device &screen, bool state); |
| 420 | 414 | UINT32 screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| r242208 | r242209 | |
| 440 | 434 | int data; |
| 441 | 435 | int command; |
| 442 | 436 | int rw; |
| 443 | | int (*devices[128])(chihiro_state &chs,int command,int rw,int data); |
| 444 | | UINT32 words[256/4]; |
| 437 | int(*devices[128])(chihiro_state &chs, int command, int rw, int data); |
| 438 | UINT32 words[256 / 4]; |
| 445 | 439 | } smbusst; |
| 446 | 440 | struct apu_state { |
| 447 | | UINT32 memory[0x60000/4]; |
| 441 | UINT32 memory[0x60000 / 4]; |
| 448 | 442 | UINT32 gpdsp_sgaddress; // global processor scatter-gather |
| 449 | 443 | UINT32 gpdsp_sgblocks; |
| 450 | 444 | UINT32 gpdsp_address; |
| r242208 | r242209 | |
| 465 | 459 | address_space *space; |
| 466 | 460 | } apust; |
| 467 | 461 | struct ac97_state { |
| 468 | | UINT32 mixer_regs[0x80/4]; |
| 469 | | UINT32 controller_regs[0x38/4]; |
| 462 | UINT32 mixer_regs[0x80 / 4]; |
| 463 | UINT32 controller_regs[0x38 / 4]; |
| 470 | 464 | } ac97st; |
| 471 | 465 | UINT8 pic16lc_buffer[0xff]; |
| 472 | 466 | nv2a_renderer *nvidia_nv2a; |
| r242208 | r242209 | |
| 478 | 472 | required_device<cpu_device> m_maincpu; |
| 479 | 473 | }; |
| 480 | 474 | |
| 481 | | /* |
| 482 | | * geforce 3d (NV2A) vertex program disassembler |
| 483 | | */ |
| 484 | | class vertex_program_disassembler { |
| 485 | | static const char *srctypes[]; |
| 486 | | static const char *scaops[]; |
| 487 | | static const int scapar2[]; |
| 488 | | static const char *vecops[]; |
| 489 | | static const int vecpar2[]; |
| 490 | | static const char *vecouts[]; |
| 491 | | static const char compchar[]; |
| 492 | | int o[6]; |
| 493 | | int state; |
| 494 | | |
| 495 | | struct sourcefields |
| 496 | | { |
| 497 | | int Sign; |
| 498 | | int SwizzleX; |
| 499 | | int SwizzleY; |
| 500 | | int SwizzleZ; |
| 501 | | int SwizzleW; |
| 502 | | int TempIndex; |
| 503 | | int ParameterType; |
| 504 | | }; |
| 505 | | |
| 506 | | struct fields |
| 507 | | { |
| 508 | | int ScaOperation; |
| 509 | | int VecOperation; |
| 510 | | int SourceConstantIndex; |
| 511 | | int InputIndex; |
| 512 | | sourcefields src[3]; |
| 513 | | int VecTempWriteMask; |
| 514 | | int VecTempIndex; |
| 515 | | int ScaTempWriteMask; |
| 516 | | int OutputWriteMask; |
| 517 | | int OutputSelect; |
| 518 | | int OutputIndex; |
| 519 | | int MultiplexerControl; |
| 520 | | int Usea0x; |
| 521 | | int EndOfProgram; |
| 522 | | }; |
| 523 | | fields f; |
| 524 | | |
| 525 | | void decodefields(unsigned int *dwords, int offset, fields &decoded); |
| 526 | | int disassemble_mask(int mask, char *s); |
| 527 | | int disassemble_swizzle(sourcefields f, char *s); |
| 528 | | int disassemble_source(sourcefields f, fields fi, char *s); |
| 529 | | int disassemble_output(fields f, char *s); |
| 530 | | int output_types(fields f, int *o); |
| 531 | | public: |
| 532 | | vertex_program_disassembler() { state = 0; } |
| 533 | | int disassemble(unsigned int *instruction, char *line); |
| 534 | | }; |
| 535 | | |
| 536 | | const char *vertex_program_disassembler::srctypes[] = { "??", "Rn", "Vn", "Cn" }; |
| 537 | | const char *vertex_program_disassembler::scaops[] = { "NOP", "IMV", "RCP", "RCC", "RSQ", "EXP", "LOG", "LIT", "???", "???", "???", "???", "???", "???", "???", "???", "???" }; |
| 538 | | const int vertex_program_disassembler::scapar2[] = { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 539 | | const char *vertex_program_disassembler::vecops[] = { "NOP", "MOV", "MUL", "ADD", "MAD", "DP3", "DPH", "DP4", "DST", "MIN", "MAX", "SLT", "SGE", "ARL", "???", "???", "???" }; |
| 540 | | const int vertex_program_disassembler::vecpar2[] = { 0, 4, 6, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 4, 0, 0, 0 }; |
| 541 | | const char *vertex_program_disassembler::vecouts[] = { "oPos", "???", "???", "oD0", "oD1", "oFog", "oPts", "oB0", "oB1", "oT0", "oT1", "oT2", "oT3" }; |
| 542 | | const char vertex_program_disassembler::compchar[] = { 'x', 'y', 'z', 'w' }; |
| 543 | | |
| 544 | | /* |
| 545 | | Each vertex program instruction is a 128 bit word made of the fields: |
| 546 | | d f |
| 547 | | w b i |
| 548 | | o i e |
| 549 | | r t l |
| 550 | | d s d |
| 551 | | +-+-----+------- |
| 552 | | |0|31-0 |not used |
| 553 | | +-+-----+------- |
| 554 | | | |31-29|not used |
| 555 | | | +-----+------- |
| 556 | | | |28-25|scalar operation |
| 557 | | | +-----+------- |
| 558 | | | |24-21|vectorial operation |
| 559 | | | +-----+------- |
| 560 | | | |20-13|index for source constant C[] |
| 561 | | | +-----+------- |
| 562 | | | |12-9 |input vector index |
| 563 | | | +-----+------- |
| 564 | | |1| 8 |parameter A:sign |
| 565 | | | +-----+------- |
| 566 | | | | 7-6 |parameter A:swizzle x |
| 567 | | | +-----+------- |
| 568 | | | | 5-4 |parameter A:swizzle y |
| 569 | | | +-----+------- |
| 570 | | | | 3-2 |parameter A:swizzle z |
| 571 | | | +-----+------- |
| 572 | | | | 1-0 |parameter A:swizzle w |
| 573 | | |-+-----+------- |
| 574 | | | |31-28|parameter A:parameter Rn index |
| 575 | | | +-----+------- |
| 576 | | | |27-26|parameter A:input type 1:Rn 2:Vn 3:C[n] |
| 577 | | | +-----+------- |
| 578 | | | | 25 |parameter B:sign |
| 579 | | | +-----+------- |
| 580 | | | |24-23|parameter B:swizzle x |
| 581 | | | +-----+------- |
| 582 | | | |22-21|parameter B:swizzle y |
| 583 | | | +-----+------- |
| 584 | | | |20-19|parameter B:swizzle z |
| 585 | | | +-----+------- |
| 586 | | |2|18-17|parameter B:swizzle w |
| 587 | | | +-----+------- |
| 588 | | | |16-13|parameter B:parameter Rn index |
| 589 | | | +-----+------- |
| 590 | | | |12-11|parameter B:input type 1:Rn 2:Vn 3:C[n] |
| 591 | | | +-----+------- |
| 592 | | | | 10 |parameter C:sign |
| 593 | | | +-----+------- |
| 594 | | | | 9-8 |parameter C:swizzle x |
| 595 | | | +-----+------- |
| 596 | | | | 7-6 |parameter C:swizzle y |
| 597 | | | +-----+------- |
| 598 | | | | 5-4 |parameter C:swizzle z |
| 599 | | | +-----+------- |
| 600 | | | | 3-2 |parameter C:swizzle w |
| 601 | | | +-----+------- |
| 602 | | | | 1-0 | |
| 603 | | |-+ |parameter C:parameter Rn index |
| 604 | | | |31-30| |
| 605 | | | +-----+------- |
| 606 | | | |29-28|parameter C:input type 1:Rn 2:Vn 3:C[n] |
| 607 | | | +-----+------- |
| 608 | | | |27-24|output Rn mask from vectorial operation |
| 609 | | | +-----+------- |
| 610 | | | |23-20|output Rn index from vectorial operation |
| 611 | | | +-----+------- |
| 612 | | | |19-16|output Rn mask from scalar operation |
| 613 | | | +-----+------- |
| 614 | | |3|15-12|output vector write mask |
| 615 | | | +-----+------- |
| 616 | | | | 11 |1:output is output vector 0:output is constant C[] |
| 617 | | | +-----+------- |
| 618 | | | |10-3 |output vector/constant index |
| 619 | | | +-----+------- |
| 620 | | | | 2 |0:output Rn from vectorial operation 1:output Rn from scalar operation |
| 621 | | | +-----+------- |
| 622 | | | | 1 |1:add a0x to index for source constant C[] |
| 623 | | | +-----+------- |
| 624 | | | | 0 |1:end of program |
| 625 | | +-+-----+------- |
| 626 | | Each vertex program instruction can generate up to three destination values using up to three source values. |
| 627 | | The first possible destination is to Rn from a vectorial operation. |
| 628 | | The second possible destination is to a vertex shader output or C[n] from a vectorial or scalar operation. |
| 629 | | The third possible destination is to Rn from a scalar operation. |
| 630 | | */ |
| 631 | | void vertex_program_disassembler::decodefields(unsigned int *dwords, int offset, fields &decoded) |
| 632 | | { |
| 633 | | unsigned int srcbits[3]; |
| 634 | | int a; |
| 635 | | |
| 636 | | srcbits[0] = ((dwords[1 + offset] & 0x1ff) << 6) | (dwords[2 + offset] >> 26); |
| 637 | | srcbits[1] = (dwords[2 + offset] >> 11) & 0x7fff; |
| 638 | | srcbits[2] = ((dwords[2 + offset] & 0x7ff) << 4) | (dwords[3 + offset] >> 28); |
| 639 | | decoded.ScaOperation = (int)(dwords[1 + offset] >> 25) & 0xf; |
| 640 | | decoded.VecOperation = (int)(dwords[1 + offset] >> 21) & 0xf; |
| 641 | | decoded.SourceConstantIndex = (int)(dwords[1 + offset] >> 13) & 0xff; |
| 642 | | decoded.InputIndex = (int)(dwords[1 + offset] >> 9) & 0xf; |
| 643 | | for (a = 0; a < 3; a++) |
| 644 | | { |
| 645 | | decoded.src[a].Sign = (int)(srcbits[a] >> 14) & 1; |
| 646 | | decoded.src[a].SwizzleX = (int)(srcbits[a] >> 12) & 3; |
| 647 | | decoded.src[a].SwizzleY = (int)(srcbits[a] >> 10) & 3; |
| 648 | | decoded.src[a].SwizzleZ = (int)(srcbits[a] >> 8) & 3; |
| 649 | | decoded.src[a].SwizzleW = (int)(srcbits[a] >> 6) & 3; |
| 650 | | decoded.src[a].TempIndex = (int)(srcbits[a] >> 2) & 0xf; |
| 651 | | decoded.src[a].ParameterType = (int)(srcbits[a] >> 0) & 3; |
| 652 | | } |
| 653 | | |
| 654 | | decoded.VecTempWriteMask = (int)(dwords[3 + offset] >> 24) & 0xf; |
| 655 | | decoded.VecTempIndex = (int)(dwords[3 + offset] >> 20) & 0xf; |
| 656 | | decoded.ScaTempWriteMask = (int)(dwords[3 + offset] >> 16) & 0xf; |
| 657 | | decoded.OutputWriteMask = (int)(dwords[3 + offset] >> 12) & 0xf; |
| 658 | | decoded.OutputSelect = (int)(dwords[3 + offset] >> 11) & 0x1; |
| 659 | | decoded.OutputIndex = (int)(dwords[3 + offset] >> 3) & 0xff; |
| 660 | | decoded.MultiplexerControl = (int)(dwords[3 + offset] >> 2) & 0x1; |
| 661 | | decoded.Usea0x = (int)(dwords[3 + offset] >> 1) & 0x1; |
| 662 | | decoded.EndOfProgram = (int)(dwords[3 + offset] >> 0) & 0x1; |
| 663 | | } |
| 664 | | |
| 665 | | int vertex_program_disassembler::disassemble_mask(int mask, char *s) |
| 666 | | { |
| 667 | | int l; |
| 668 | | |
| 669 | | *s = 0; |
| 670 | | if (mask == 15) |
| 671 | | return 0; |
| 672 | | s[0] = '.'; |
| 673 | | l = 1; |
| 674 | | if ((mask & 8) != 0) { |
| 675 | | s[l] = 'x'; |
| 676 | | l++; |
| 677 | | } |
| 678 | | if ((mask & 4) != 0){ |
| 679 | | s[l] = 'y'; |
| 680 | | l++; |
| 681 | | } |
| 682 | | if ((mask & 2) != 0){ |
| 683 | | s[l] = 'z'; |
| 684 | | l++; |
| 685 | | } |
| 686 | | if ((mask & 1) != 0){ |
| 687 | | s[l] = 'w'; |
| 688 | | l++; |
| 689 | | } |
| 690 | | s[l] = 0; |
| 691 | | return l; |
| 692 | | } |
| 693 | | |
| 694 | | int vertex_program_disassembler::disassemble_swizzle(sourcefields f, char *s) |
| 695 | | { |
| 696 | | int t, l; |
| 697 | | |
| 698 | | t = 4; |
| 699 | | if (f.SwizzleW == 3) |
| 700 | | { |
| 701 | | t = t - 1; |
| 702 | | if (f.SwizzleZ == 2) |
| 703 | | { |
| 704 | | t = t - 1; |
| 705 | | if (f.SwizzleY == 1) |
| 706 | | { |
| 707 | | t = t - 1; |
| 708 | | if (f.SwizzleX == 0) |
| 709 | | { |
| 710 | | t = t - 1; |
| 711 | | } |
| 712 | | } |
| 713 | | } |
| 714 | | } |
| 715 | | *s = 0; |
| 716 | | if (t == 0) |
| 717 | | return 0; |
| 718 | | s[0] = '.'; |
| 719 | | l = 1; |
| 720 | | if (t > 0) |
| 721 | | { |
| 722 | | s[l] = compchar[f.SwizzleX]; |
| 723 | | l++; |
| 724 | | } |
| 725 | | if (t > 1) |
| 726 | | { |
| 727 | | s[l] = compchar[f.SwizzleY]; |
| 728 | | l++; |
| 729 | | } |
| 730 | | if (t > 2) |
| 731 | | { |
| 732 | | s[l] = compchar[f.SwizzleZ]; |
| 733 | | l++; |
| 734 | | } |
| 735 | | if (t > 3) |
| 736 | | { |
| 737 | | s[l] = compchar[f.SwizzleW]; |
| 738 | | l++; |
| 739 | | } |
| 740 | | s[l] = 0; |
| 741 | | return l; |
| 742 | | } |
| 743 | | |
| 744 | | int vertex_program_disassembler::disassemble_source(sourcefields f, fields fi, char *s) |
| 745 | | { |
| 746 | | int l; |
| 747 | | |
| 748 | | if (f.ParameterType == 0) { |
| 749 | | strcpy(s, ",???"); |
| 750 | | return 4; |
| 751 | | } |
| 752 | | l = 0; |
| 753 | | if (f.Sign != 0) { |
| 754 | | s[l] = '-'; |
| 755 | | l++; |
| 756 | | } |
| 757 | | if (f.ParameterType == 1) { |
| 758 | | s[l] = 'r'; |
| 759 | | l = l + 1 + sprintf(s + l + 1, "%d", f.TempIndex); |
| 760 | | } |
| 761 | | else if (f.ParameterType == 2){ |
| 762 | | s[l] = 'v'; |
| 763 | | l = l + 1 + sprintf(s + l + 1, "%d", fi.InputIndex); |
| 764 | | } |
| 765 | | else |
| 766 | | { |
| 767 | | if (fi.Usea0x != 0) |
| 768 | | { |
| 769 | | if (fi.SourceConstantIndex >= 96) { |
| 770 | | strcpy(s + l, "c["); |
| 771 | | l = l + 2; |
| 772 | | l = l + sprintf(s + l, "%d", fi.SourceConstantIndex - 96); |
| 773 | | strcpy(s + l, "+a0.x]"); |
| 774 | | l = l + 6; |
| 775 | | } |
| 776 | | else { |
| 777 | | strcpy(s + l, "c[a0.x"); |
| 778 | | l = l + 6; |
| 779 | | l = l + sprintf(s + l, "%d", fi.SourceConstantIndex - 96); |
| 780 | | s[l] = ']'; |
| 781 | | l++; |
| 782 | | } |
| 783 | | } |
| 784 | | else { |
| 785 | | strcpy(s + l, "c["); |
| 786 | | l = l + 2; |
| 787 | | l = l + sprintf(s + l, "%d", fi.SourceConstantIndex - 96); |
| 788 | | s[l] = ']'; |
| 789 | | l++; |
| 790 | | } |
| 791 | | } |
| 792 | | l = l + disassemble_swizzle(f, s + l); |
| 793 | | s[l] = 0; |
| 794 | | return l; |
| 795 | | } |
| 796 | | |
| 797 | | int vertex_program_disassembler::disassemble_output(fields f, char *s) |
| 798 | | { |
| 799 | | int l; |
| 800 | | |
| 801 | | if (f.OutputSelect == 1) { |
| 802 | | strcpy(s, vecouts[f.OutputIndex]); |
| 803 | | return strlen(s); |
| 804 | | } |
| 805 | | else { |
| 806 | | strcpy(s, "c["); |
| 807 | | l = 2; |
| 808 | | l = l + sprintf(s + l, "%d", f.OutputIndex - 96); |
| 809 | | s[l] = ']'; |
| 810 | | l++; |
| 811 | | } |
| 812 | | s[l] = 0; |
| 813 | | return l; |
| 814 | | } |
| 815 | | |
| 816 | | int vertex_program_disassembler::output_types(fields f, int *o) |
| 817 | | { |
| 818 | | o[0] = o[1] = o[2] = o[3] = o[4] = o[5] = 0; |
| 819 | | if ((f.VecOperation > 0) && (f.VecTempWriteMask != 0)) |
| 820 | | o[0] = 1; |
| 821 | | if ((f.VecOperation > 0) && (f.OutputWriteMask != 0) && (f.MultiplexerControl == 0)) |
| 822 | | o[1] = 1; |
| 823 | | if ((f.ScaOperation > 0) && (f.OutputWriteMask != 0) && (f.MultiplexerControl == 1)) |
| 824 | | o[2] = 1; |
| 825 | | if ((f.ScaOperation > 0) && (f.ScaTempWriteMask != 0)) |
| 826 | | o[3] = 1; |
| 827 | | if (f.VecOperation == 13) |
| 828 | | o[4] = 1; |
| 829 | | if (f.EndOfProgram == 1) |
| 830 | | o[5] = 1; |
| 831 | | return o[0] + o[1] + o[2] + o[3] + o[4] + o[5]; |
| 832 | | } |
| 833 | | |
| 834 | | int vertex_program_disassembler::disassemble(unsigned int *instruction, char *line) |
| 835 | | { |
| 836 | | int b, p; |
| 837 | | char *c; |
| 838 | | |
| 839 | | if (state == 0) { |
| 840 | | decodefields(instruction, 0, f); |
| 841 | | output_types(f, o); |
| 842 | | state = 1; |
| 843 | | } |
| 844 | | if (o[0] != 0) |
| 845 | | { |
| 846 | | o[0] = 0; |
| 847 | | c = line; |
| 848 | | strcpy(c, vecops[f.VecOperation]); |
| 849 | | c = c + strlen(c); |
| 850 | | strcpy(c, " r"); |
| 851 | | c = c + 2; |
| 852 | | c = c + sprintf(c, "%d", f.VecTempIndex); |
| 853 | | c = c + disassemble_mask(f.VecTempWriteMask, c); |
| 854 | | b = 0; |
| 855 | | for (p = 4; p != 0; p = p >> 1) |
| 856 | | { |
| 857 | | if ((vecpar2[f.VecOperation] & p) != 0) { |
| 858 | | c[0] = ','; |
| 859 | | c++; |
| 860 | | c = c + disassemble_source(f.src[b], f, c); |
| 861 | | } |
| 862 | | b++; |
| 863 | | } |
| 864 | | *c = 0; |
| 865 | | return 1; |
| 866 | | } |
| 867 | | if (o[1] != 0) |
| 868 | | { |
| 869 | | o[1] = 0; |
| 870 | | c = line; |
| 871 | | strcpy(c, vecops[f.VecOperation]); |
| 872 | | c = c + strlen(c); |
| 873 | | *c = ' '; |
| 874 | | c++; |
| 875 | | c = c + disassemble_output(f, c); |
| 876 | | c = c + disassemble_mask(f.OutputWriteMask, c); |
| 877 | | b = 0; |
| 878 | | for (p = 4; p != 0; p = p >> 1) |
| 879 | | { |
| 880 | | if ((vecpar2[f.VecOperation] & p) != 0) { |
| 881 | | *c = ','; |
| 882 | | c++; |
| 883 | | c = c + disassemble_source(f.src[b], f, c); |
| 884 | | } |
| 885 | | b++; |
| 886 | | } |
| 887 | | *c = 0; |
| 888 | | return 1; |
| 889 | | } |
| 890 | | if (o[2] != 0) |
| 891 | | { |
| 892 | | o[2] = 0; |
| 893 | | c = line; |
| 894 | | strcpy(c, scaops[f.ScaOperation]); |
| 895 | | c = c + strlen(c); |
| 896 | | *c = ' '; |
| 897 | | c++; |
| 898 | | c = c + disassemble_output(f, c); |
| 899 | | c = c + disassemble_mask(f.OutputWriteMask, c); |
| 900 | | b = 0; |
| 901 | | for (p = 4; p != 0; p = p >> 1) |
| 902 | | { |
| 903 | | if ((scapar2[f.ScaOperation] & p) != 0) { |
| 904 | | *c = ','; |
| 905 | | c++; |
| 906 | | c = c + disassemble_source(f.src[b], f, c); |
| 907 | | } |
| 908 | | b++; |
| 909 | | } |
| 910 | | *c = 0; |
| 911 | | return 1; |
| 912 | | } |
| 913 | | if (o[3] != 0) |
| 914 | | { |
| 915 | | if (f.VecOperation > 0) |
| 916 | | b = 1; |
| 917 | | else |
| 918 | | b = f.VecTempIndex; |
| 919 | | o[3] = 0; |
| 920 | | c = line; |
| 921 | | strcpy(c, scaops[f.ScaOperation]); |
| 922 | | c = c + strlen(c); |
| 923 | | strcpy(c, " r"); |
| 924 | | c = c + 2; |
| 925 | | c = c + sprintf(c, "%d", b); |
| 926 | | c = c + disassemble_mask(f.ScaTempWriteMask, c); |
| 927 | | b = 0; |
| 928 | | for (p = 4; p != 0; p = p >> 1) |
| 929 | | { |
| 930 | | if ((scapar2[f.ScaOperation] & p) != 0) { |
| 931 | | *c = ','; |
| 932 | | c++; |
| 933 | | c = c + disassemble_source(f.src[b], f, c); |
| 934 | | } |
| 935 | | b++; |
| 936 | | } |
| 937 | | *c = 0; |
| 938 | | return 1; |
| 939 | | } |
| 940 | | if (o[4] != 0) |
| 941 | | { |
| 942 | | o[4] = 0; |
| 943 | | c = line; |
| 944 | | c = c + sprintf(c, "MOV a0.x,"); |
| 945 | | c = c + disassemble_source(f.src[0], f, c); |
| 946 | | *c = 0; |
| 947 | | return 1; |
| 948 | | } |
| 949 | | if (o[5] != 0) |
| 950 | | { |
| 951 | | o[5] = 0; |
| 952 | | strcpy(line, "END"); |
| 953 | | return 1; |
| 954 | | } |
| 955 | | state = 0; |
| 956 | | return 0; |
| 957 | | } |
| 958 | | |
| 959 | | /* |
| 960 | | * geforce 3d (NV2A) accellerator |
| 961 | | */ |
| 962 | | /* very simplified view |
| 963 | | there is a set of context objects |
| 964 | | |
| 965 | | context objects are stored in RAMIN |
| 966 | | each context object is identified by an handle stored in RAMHT |
| 967 | | |
| 968 | | each context object can be assigned to a channel |
| 969 | | to assign you give to the channel an handle for the object |
| 970 | | |
| 971 | | offset in ramht=(((((handle >> 11) xor handle) >> 11) xor handle) & 0x7ff)*8 |
| 972 | | offset in ramht contains the handle itself |
| 973 | | offset in ramht+4 contains in the lower 16 bits the offset in RAMIN divided by 16 |
| 974 | | |
| 975 | | objects have methods used to do drawing |
| 976 | | most methods set parameters, others actually draw |
| 977 | | */ |
| 978 | | class nv2a_renderer : public poly_manager<float, nvidia_object_data, 12, 8192> |
| 979 | | { |
| 980 | | public: |
| 981 | | nv2a_renderer(running_machine &machine) : poly_manager<float, nvidia_object_data, 12, 8192>(machine) |
| 982 | | { |
| 983 | | memset(channel,0,sizeof(channel)); |
| 984 | | memset(pfifo,0,sizeof(pfifo)); |
| 985 | | memset(pcrtc,0,sizeof(pcrtc)); |
| 986 | | memset(pmc,0,sizeof(pmc)); |
| 987 | | memset(ramin,0,sizeof(ramin)); |
| 988 | | computedilated(); |
| 989 | | fb.allocate(640,480); |
| 990 | | objectdata=&(object_data_alloc()); |
| 991 | | objectdata->data=this; |
| 992 | | combiner.used=0; |
| 993 | | combiner.lock=osd_lock_alloc(); |
| 994 | | enabled_vertex_attributes=0; |
| 995 | | indexesleft_count = 0; |
| 996 | | vertex_pipeline = 4; |
| 997 | | alpha_test_enabled = false; |
| 998 | | alpha_reference = 0; |
| 999 | | alpha_func = nv2a_renderer::ALWAYS; |
| 1000 | | blending_enabled = false; |
| 1001 | | blend_equation = nv2a_renderer::FUNC_ADD; |
| 1002 | | blend_color = 0; |
| 1003 | | blend_function_destination = nv2a_renderer::ZERO; |
| 1004 | | blend_function_source = nv2a_renderer::ONE; |
| 1005 | | logical_operation_enabled = false; |
| 1006 | | logical_operation = nv2a_renderer::COPY; |
| 1007 | | debug_grab_texttype = -1; |
| 1008 | | debug_grab_textfile = NULL; |
| 1009 | | memset(vertex_attribute_words, 0, sizeof(vertex_attribute_words)); |
| 1010 | | memset(vertex_attribute_offset, 0, sizeof(vertex_attribute_offset)); |
| 1011 | | } |
| 1012 | | DECLARE_READ32_MEMBER( geforce_r ); |
| 1013 | | DECLARE_WRITE32_MEMBER( geforce_w ); |
| 1014 | | void vblank_callback(screen_device &screen, bool state); |
| 1015 | | UINT32 screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| 1016 | | |
| 1017 | | void render_texture_simple(INT32 scanline, const extent_t &extent, const nvidia_object_data &extradata, int threadid); |
| 1018 | | void render_color(INT32 scanline, const extent_t &extent, const nvidia_object_data &extradata, int threadid); |
| 1019 | | void render_register_combiners(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid); |
| 1020 | | |
| 1021 | | int geforce_commandkind(UINT32 word); |
| 1022 | | UINT32 geforce_object_offset(UINT32 handle); |
| 1023 | | void geforce_read_dma_object(UINT32 handle,UINT32 &offset,UINT32 &size); |
| 1024 | | void geforce_exec_method(address_space &space,UINT32 channel,UINT32 subchannel,UINT32 method,UINT32 address,int &countlen); |
| 1025 | | UINT32 texture_get_texel(int number,int x,int y); |
| 1026 | | void write_pixel(int x, int y, UINT32 color); |
| 1027 | | void combiner_initialize_registers(UINT32 argb8[6]); |
| 1028 | | void combiner_initialize_stage(int stage_number); |
| 1029 | | void combiner_initialize_final(); |
| 1030 | | void combiner_map_input(int stage_number); // map combiner registers to variables A..D |
| 1031 | | void combiner_map_output(int stage_number); // map combiner calculation results to combiner registers |
| 1032 | | void combiner_map_final_input(); // map final combiner registers to variables A..F |
| 1033 | | void combiner_final_output(); // generate final combiner output |
| 1034 | | float combiner_map_input_select(int code,int index); // get component index in register code |
| 1035 | | float *combiner_map_input_select3(int code); // get pointer to register code |
| 1036 | | float *combiner_map_output_select3(int code); // get pointer to register code for output |
| 1037 | | float combiner_map_input_function(int code,float value); // apply input mapping function code to value |
| 1038 | | void combiner_map_input_function3(int code,float *data); // apply input mapping function code to data |
| 1039 | | void combiner_function_AB(float result[4]); |
| 1040 | | void combiner_function_AdotB(float result[4]); |
| 1041 | | void combiner_function_CD(float result[4]); |
| 1042 | | void combiner_function_CdotD(float result[4]); |
| 1043 | | void combiner_function_ABmuxCD(float result[4]); |
| 1044 | | void combiner_function_ABsumCD(float result[4]); |
| 1045 | | void combiner_compute_rgb_outputs(int index); |
| 1046 | | void combiner_compute_a_outputs(int index); |
| 1047 | | void combiner_argb8_float(UINT32 color,float reg[4]); |
| 1048 | | UINT32 combiner_float_argb8(float reg[4]); |
| 1049 | | UINT32 dilate0(UINT32 value,int bits); |
| 1050 | | UINT32 dilate1(UINT32 value,int bits); |
| 1051 | | void computedilated(void); |
| 1052 | | void putpixtex(int xp,int yp,int up,int vp); |
| 1053 | | int toggle_register_combiners_usage(); |
| 1054 | | void debug_grab_texture(int type, const char *filename); |
| 1055 | | void debug_grab_vertex_program_slot(int slot, UINT32 *instruction); |
| 1056 | | void savestate_items(); |
| 1057 | | |
| 1058 | | struct vertex { |
| 1059 | | union { |
| 1060 | | float fv[4]; |
| 1061 | | UINT32 iv[4]; |
| 1062 | | } attribute[16]; |
| 1063 | | }; |
| 1064 | | int read_vertices_0x1810(address_space & space, vertex *destination, int offset, int limit); |
| 1065 | | int read_vertices_0x1800(address_space & space, vertex *destination, UINT32 address, int limit); |
| 1066 | | int read_vertices_0x1818(address_space & space, vertex *destination, UINT32 address, int limit); |
| 1067 | | void convert_vertices_poly(vertex *source, vertex_t *destination, int count); |
| 1068 | | |
| 1069 | | struct { |
| 1070 | | UINT32 regs[0x80/4]; |
| 1071 | | struct { |
| 1072 | | UINT32 objhandle; |
| 1073 | | UINT32 objclass; |
| 1074 | | UINT32 method[0x2000/4]; |
| 1075 | | } object; |
| 1076 | | } channel[32][8]; |
| 1077 | | UINT32 pfifo[0x2000/4]; |
| 1078 | | UINT32 pcrtc[0x1000/4]; |
| 1079 | | UINT32 pmc[0x1000/4]; |
| 1080 | | UINT32 ramin[0x100000/4]; |
| 1081 | | UINT32 dma_offset[2]; |
| 1082 | | UINT32 dma_size[2]; |
| 1083 | | UINT32 vertexbuffer_address[16]; |
| 1084 | | int vertexbuffer_stride[16]; |
| 1085 | | struct { |
| 1086 | | int enabled; |
| 1087 | | int sizeu; |
| 1088 | | int sizev; |
| 1089 | | int sizew; |
| 1090 | | int dilate; |
| 1091 | | int format; |
| 1092 | | int rectangle_pitch; |
| 1093 | | void *buffer; |
| 1094 | | } texture[4]; |
| 1095 | | int primitives_count; |
| 1096 | | int indexesleft_count; |
| 1097 | | int indexesleft_first; |
| 1098 | | UINT32 indexesleft[8]; |
| 1099 | | struct { |
| 1100 | | float variable_A[4]; // 0=R 1=G 2=B 3=A |
| 1101 | | float variable_B[4]; |
| 1102 | | float variable_C[4]; |
| 1103 | | float variable_D[4]; |
| 1104 | | float variable_E[4]; |
| 1105 | | float variable_F[4]; |
| 1106 | | float variable_G; |
| 1107 | | float variable_EF[4]; |
| 1108 | | float variable_sumclamp[4]; |
| 1109 | | float function_RGBop1[4]; // 0=R 1=G 2=B |
| 1110 | | float function_RGBop2[4]; |
| 1111 | | float function_RGBop3[4]; |
| 1112 | | float function_Aop1; |
| 1113 | | float function_Aop2; |
| 1114 | | float function_Aop3; |
| 1115 | | float register_primarycolor[4]; // rw |
| 1116 | | float register_secondarycolor[4]; |
| 1117 | | float register_texture0color[4]; |
| 1118 | | float register_texture1color[4]; |
| 1119 | | float register_texture2color[4]; |
| 1120 | | float register_texture3color[4]; |
| 1121 | | float register_color0[4]; |
| 1122 | | float register_color1[4]; |
| 1123 | | float register_spare0[4]; |
| 1124 | | float register_spare1[4]; |
| 1125 | | float register_fogcolor[4]; // ro |
| 1126 | | float register_zero[4]; |
| 1127 | | float output[4]; |
| 1128 | | struct { |
| 1129 | | float register_constantcolor0[4]; |
| 1130 | | float register_constantcolor1[4]; |
| 1131 | | int mapin_aA_input; |
| 1132 | | int mapin_aA_component; |
| 1133 | | int mapin_aA_mapping; |
| 1134 | | int mapin_aB_input; |
| 1135 | | int mapin_aB_component; |
| 1136 | | int mapin_aB_mapping; |
| 1137 | | int mapin_aC_input; |
| 1138 | | int mapin_aC_component; |
| 1139 | | int mapin_aC_mapping; |
| 1140 | | int mapin_aD_input; |
| 1141 | | int mapin_aD_component; |
| 1142 | | int mapin_aD_mapping; |
| 1143 | | int mapin_rgbA_input; |
| 1144 | | int mapin_rgbA_component; |
| 1145 | | int mapin_rgbA_mapping; |
| 1146 | | int mapin_rgbB_input; |
| 1147 | | int mapin_rgbB_component; |
| 1148 | | int mapin_rgbB_mapping; |
| 1149 | | int mapin_rgbC_input; |
| 1150 | | int mapin_rgbC_component; |
| 1151 | | int mapin_rgbC_mapping; |
| 1152 | | int mapin_rgbD_input; |
| 1153 | | int mapin_rgbD_component; |
| 1154 | | int mapin_rgbD_mapping; |
| 1155 | | int mapout_aCD_output; |
| 1156 | | int mapout_aAB_output; |
| 1157 | | int mapout_aSUM_output; |
| 1158 | | int mapout_aCD_dotproduct; |
| 1159 | | int mapout_aAB_dotproduct; |
| 1160 | | int mapout_a_muxsum; |
| 1161 | | int mapout_a_bias; |
| 1162 | | int mapout_a_scale; |
| 1163 | | int mapout_rgbCD_output; |
| 1164 | | int mapout_rgbAB_output; |
| 1165 | | int mapout_rgbSUM_output; |
| 1166 | | int mapout_rgbCD_dotproduct; |
| 1167 | | int mapout_rgbAB_dotproduct; |
| 1168 | | int mapout_rgb_muxsum; |
| 1169 | | int mapout_rgb_bias; |
| 1170 | | int mapout_rgb_scale; |
| 1171 | | } stage[8]; |
| 1172 | | struct { |
| 1173 | | float register_constantcolor0[4]; |
| 1174 | | float register_constantcolor1[4]; |
| 1175 | | int color_sum_clamp; |
| 1176 | | int mapin_rgbA_input; |
| 1177 | | int mapin_rgbA_component; |
| 1178 | | int mapin_rgbA_mapping; |
| 1179 | | int mapin_rgbB_input; |
| 1180 | | int mapin_rgbB_component; |
| 1181 | | int mapin_rgbB_mapping; |
| 1182 | | int mapin_rgbC_input; |
| 1183 | | int mapin_rgbC_component; |
| 1184 | | int mapin_rgbC_mapping; |
| 1185 | | int mapin_rgbD_input; |
| 1186 | | int mapin_rgbD_component; |
| 1187 | | int mapin_rgbD_mapping; |
| 1188 | | int mapin_rgbE_input; |
| 1189 | | int mapin_rgbE_component; |
| 1190 | | int mapin_rgbE_mapping; |
| 1191 | | int mapin_rgbF_input; |
| 1192 | | int mapin_rgbF_component; |
| 1193 | | int mapin_rgbF_mapping; |
| 1194 | | int mapin_aG_input; |
| 1195 | | int mapin_aG_component; |
| 1196 | | int mapin_aG_mapping; |
| 1197 | | } final; |
| 1198 | | int stages; |
| 1199 | | int used; |
| 1200 | | osd_lock *lock; |
| 1201 | | } combiner; |
| 1202 | | bool alpha_test_enabled; |
| 1203 | | int alpha_func; |
| 1204 | | int alpha_reference; |
| 1205 | | bool blending_enabled; |
| 1206 | | int blend_equation; |
| 1207 | | int blend_function_source; |
| 1208 | | int blend_function_destination; |
| 1209 | | UINT32 blend_color; |
| 1210 | | bool logical_operation_enabled; |
| 1211 | | int logical_operation; |
| 1212 | | struct { |
| 1213 | | float modelview[16]; |
| 1214 | | float modelview_inverse[16]; |
| 1215 | | float projection[16]; |
| 1216 | | float translate[4]; |
| 1217 | | float scale[4]; |
| 1218 | | } matrix; |
| 1219 | | struct { |
| 1220 | | UINT32 instruction[1024]; |
| 1221 | | int instructions; |
| 1222 | | int upload_instruction; |
| 1223 | | int start_instruction; |
| 1224 | | float parameter[1024]; |
| 1225 | | int upload_parameter; |
| 1226 | | } vertexprogram; |
| 1227 | | int vertex_pipeline; |
| 1228 | | int enabled_vertex_attributes; |
| 1229 | | int vertex_attribute_words[16]; |
| 1230 | | int vertex_attribute_offset[16]; |
| 1231 | | bitmap_rgb32 fb; |
| 1232 | | UINT32 dilated0[16][2048]; |
| 1233 | | UINT32 dilated1[16][2048]; |
| 1234 | | int dilatechose[256]; |
| 1235 | | nvidia_object_data *objectdata; |
| 1236 | | int debug_grab_texttype; |
| 1237 | | char *debug_grab_textfile; |
| 1238 | | |
| 1239 | | enum NV2A_BEGIN_END { |
| 1240 | | STOP=0, |
| 1241 | | POINTS=1, |
| 1242 | | LINES=2, |
| 1243 | | LINE_LOOP=3, |
| 1244 | | LINE_STRIP=4, |
| 1245 | | TRIANGLES=5, |
| 1246 | | TRIANGLE_STRIP=6, |
| 1247 | | TRIANGLE_FAN=7, |
| 1248 | | QUADS=8, |
| 1249 | | QUAD_STRIP=9, |
| 1250 | | POLYGON=10 |
| 1251 | | }; |
| 1252 | | enum NV2A_VERTEX_ATTR { |
| 1253 | | POS=0, |
| 1254 | | WEIGHT=1, |
| 1255 | | NORMAL=2, |
| 1256 | | COLOR0=3, |
| 1257 | | COLOR1=4, |
| 1258 | | FOG=5, |
| 1259 | | TEX0=9, |
| 1260 | | TEX1=10, |
| 1261 | | TEX2=11, |
| 1262 | | TEX3=12 |
| 1263 | | }; |
| 1264 | | enum NV2A_VTXBUF_TYPE { |
| 1265 | | FLOAT=2, |
| 1266 | | UBYTE=4, |
| 1267 | | USHORT=5 |
| 1268 | | }; |
| 1269 | | enum NV2A_TEX_FORMAT { |
| 1270 | | L8=0x0, |
| 1271 | | I8=0x1, |
| 1272 | | A1R5G5B5=0x2, |
| 1273 | | A4R4G4B4=0x4, |
| 1274 | | R5G6B5=0x5, |
| 1275 | | A8R8G8B8=0x6, |
| 1276 | | X8R8G8B8=0x7, |
| 1277 | | INDEX8=0xb, |
| 1278 | | DXT1=0xc, |
| 1279 | | DXT3=0xe, |
| 1280 | | DXT5=0xf, |
| 1281 | | A1R5G5B5_RECT=0x10, |
| 1282 | | R5G6B5_RECT=0x11, |
| 1283 | | A8R8G8B8_RECT=0x12, |
| 1284 | | L8_RECT=0x13, |
| 1285 | | DSDT8_RECT=0x17, |
| 1286 | | A8L8=0x1a, |
| 1287 | | I8_RECT=0x1b, |
| 1288 | | A4R4G4B4_RECT=0x1d, |
| 1289 | | R8G8B8_RECT=0x1e, |
| 1290 | | A8L8_RECT=0x20, |
| 1291 | | Z24=0x2a, |
| 1292 | | Z24_RECT=0x2b, |
| 1293 | | Z16=0x2c, |
| 1294 | | Z16_RECT=0x2d, |
| 1295 | | DSDT8=0x28, |
| 1296 | | HILO16=0x33, |
| 1297 | | HILO16_RECT=0x36, |
| 1298 | | HILO8=0x44, |
| 1299 | | SIGNED_HILO8=0x45, |
| 1300 | | HILO8_RECT=0x46, |
| 1301 | | SIGNED_HILO8_RECT=0x47 |
| 1302 | | }; |
| 1303 | | enum NV2A_LOGIC_OP { |
| 1304 | | CLEAR=0x1500, |
| 1305 | | AND=0x1501, |
| 1306 | | AND_REVERSE=0x1502, |
| 1307 | | COPY=0x1503, |
| 1308 | | AND_INVERTED=0x1504, |
| 1309 | | NOOP=0x1505, |
| 1310 | | XOR=0x1506, |
| 1311 | | OR=0x1507, |
| 1312 | | NOR=0x1508, |
| 1313 | | EQUIV=0x1509, |
| 1314 | | INVERT=0x150a, |
| 1315 | | OR_REVERSE=0x150b, |
| 1316 | | COPY_INVERTED=0x150c, |
| 1317 | | OR_INVERTED=0x150d, |
| 1318 | | NAND=0x150e, |
| 1319 | | SET=0x150f |
| 1320 | | }; |
| 1321 | | enum NV2A_BLEND_EQUATION { |
| 1322 | | FUNC_ADD=0x8006, |
| 1323 | | MIN=0x8007, |
| 1324 | | MAX=0x8008, |
| 1325 | | FUNC_SUBTRACT=0x800a, |
| 1326 | | FUNC_REVERSE_SUBTRACT=0x80b |
| 1327 | | }; |
| 1328 | | enum NV2A_BLEND_FACTOR { |
| 1329 | | ZERO=0x0000, |
| 1330 | | ONE=0x0001, |
| 1331 | | SRC_COLOR=0x0300, |
| 1332 | | ONE_MINUS_SRC_COLOR=0x0301, |
| 1333 | | SRC_ALPHA=0x0302, |
| 1334 | | ONE_MINUS_SRC_ALPHA=0x0303, |
| 1335 | | DST_ALPHA=0x0304, |
| 1336 | | ONE_MINUS_DST_ALPHA=0x0305, |
| 1337 | | DST_COLOR=0x0306, |
| 1338 | | ONE_MINUS_DST_COLOR=0x0307, |
| 1339 | | SRC_ALPHA_SATURATE=0x0308, |
| 1340 | | CONSTANT_COLOR=0x8001, |
| 1341 | | ONE_MINUS_CONSTANT_COLOR=0x8002, |
| 1342 | | CONSTANT_ALPHA=0x8003, |
| 1343 | | ONE_MINUS_CONSTANT_ALPHA=0x8004 |
| 1344 | | }; |
| 1345 | | enum NV2A_COMPARISON_OP { |
| 1346 | | NEVER=0x0200, |
| 1347 | | LESS=0x0201, |
| 1348 | | EQUAL=0x0202, |
| 1349 | | LEQUAL=0x0203, |
| 1350 | | GREATER=0x0204, |
| 1351 | | NOTEQUAL=0x0205, |
| 1352 | | GEQUAL=0x0206, |
| 1353 | | ALWAYS=0x0207 |
| 1354 | | }; |
| 1355 | | enum NV2A_STENCIL_OP { |
| 1356 | | ZEROOP=0x0000, |
| 1357 | | INVERTOP=0x150a, |
| 1358 | | KEEP=0x1e00, |
| 1359 | | REPLACE=0x1e01, |
| 1360 | | INCR=0x1e02, |
| 1361 | | DECR=0x1e03, |
| 1362 | | INCR_WRAP=0x8507, |
| 1363 | | DECR_WRAP=0x8508 |
| 1364 | | }; |
| 1365 | | }; |
| 1366 | | |
| 1367 | 475 | /* jamtable instructions for Chihiro (different from console) |
| 1368 | 476 | St. Instr. Comment |
| 1369 | 477 | 0x01 POKEPCI PCICONF[OP2] := OP1 |
| r242208 | r242209 | |
| 1380 | 488 | */ |
| 1381 | 489 | |
| 1382 | 490 | /* jamtable disassembler */ |
| 1383 | | static void jamtable_disasm(running_machine &machine, address_space &space,UINT32 address,UINT32 size) // 0xff000080 == fff00080 |
| 491 | static void jamtable_disasm(running_machine &machine, address_space &space, UINT32 address, UINT32 size) // 0xff000080 == fff00080 |
| 1384 | 492 | { |
| 1385 | | offs_t base,addr; |
| 1386 | | UINT32 opcode,op1,op2; |
| 493 | offs_t base, addr; |
| 494 | UINT32 opcode, op1, op2; |
| 1387 | 495 | char sop1[16]; |
| 1388 | 496 | char sop2[16]; |
| 1389 | 497 | char pcrel[16]; |
| 1390 | 498 | |
| 1391 | | addr=(offs_t)address; |
| 1392 | | if (!debug_cpu_translate(space,TRANSLATE_READ_DEBUG,&addr)) |
| 499 | addr = (offs_t)address; |
| 500 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &addr)) |
| 1393 | 501 | { |
| 1394 | | debug_console_printf(machine,"Address is unmapped.\n"); |
| 502 | debug_console_printf(machine, "Address is unmapped.\n"); |
| 1395 | 503 | return; |
| 1396 | 504 | } |
| 1397 | 505 | while (1) |
| 1398 | 506 | { |
| 1399 | | base=addr; |
| 1400 | | opcode=space.read_byte(addr); |
| 507 | base = addr; |
| 508 | opcode = space.read_byte(addr); |
| 1401 | 509 | addr++; |
| 1402 | | op1=space.read_dword_unaligned(addr); |
| 1403 | | addr+=4; |
| 1404 | | op2=space.read_dword_unaligned(addr); |
| 1405 | | addr+=4; |
| 510 | op1 = space.read_dword_unaligned(addr); |
| 511 | addr += 4; |
| 512 | op2 = space.read_dword_unaligned(addr); |
| 513 | addr += 4; |
| 1406 | 514 | if (opcode == 0xe1) |
| 1407 | 515 | { |
| 1408 | | opcode=op2 & 255; |
| 1409 | | op2=op1; |
| 516 | opcode = op2 & 255; |
| 517 | op2 = op1; |
| 1410 | 518 | //op1=edi; |
| 1411 | | sprintf(sop2,"%08X",op2); |
| 1412 | | sprintf(sop1,"ACC"); |
| 1413 | | sprintf(pcrel,"PC+ACC"); |
| 519 | sprintf(sop2, "%08X", op2); |
| 520 | sprintf(sop1, "ACC"); |
| 521 | sprintf(pcrel, "PC+ACC"); |
| 1414 | 522 | } |
| 1415 | 523 | else |
| 1416 | 524 | { |
| 1417 | | sprintf(sop2,"%08X",op2); |
| 1418 | | sprintf(sop1,"%08X",op1); |
| 1419 | | sprintf(pcrel,"%08X",base+9+op1); |
| 525 | sprintf(sop2, "%08X", op2); |
| 526 | sprintf(sop1, "%08X", op1); |
| 527 | sprintf(pcrel, "%08X", base + 9 + op1); |
| 1420 | 528 | } |
| 1421 | | debug_console_printf(machine,"%08X ",base); |
| 529 | debug_console_printf(machine, "%08X ", base); |
| 1422 | 530 | // dl=instr ebx=par1 eax=par2 |
| 1423 | 531 | switch (opcode) |
| 1424 | 532 | { |
| 1425 | | case 0x01: |
| 1426 | | // if ((op2 & 0xff) == 0x880) op1=op1 & 0xfffffffd |
| 1427 | | // out cf8,op2 |
| 1428 | | // out cfc,op1 |
| 1429 | | // out cf8,0 |
| 1430 | | // cf8 (CONFIG_ADDRESS) format: |
| 1431 | | // 31 30 24 23 16 15 11 10 8 7 2 1 0 |
| 1432 | | // +-+----------+------------+---------------+-----------------+-----------------+-+-+ |
| 1433 | | // | | Reserved | Bus Number | Device Number | Function Number | Register Number |0|0| |
| 1434 | | // +-+----------+------------+---------------+-----------------+-----------------+-+-+ |
| 1435 | | // 31 - Enable bit |
| 1436 | | debug_console_printf(machine,"POKEPCI PCICONF[%s]=%s\n",sop2,sop1); |
| 1437 | | break; |
| 1438 | | case 0x02: |
| 1439 | | debug_console_printf(machine,"OUTB PORT[%s]=%s\n",sop2,sop1); |
| 1440 | | break; |
| 1441 | | case 0x03: |
| 1442 | | debug_console_printf(machine,"POKE MEM[%s]=%s\n",sop2,sop1); |
| 1443 | | break; |
| 1444 | | case 0x04: |
| 1445 | | debug_console_printf(machine,"BNE IF ACC != %s THEN PC=%s\n",sop2,pcrel); |
| 1446 | | break; |
| 1447 | | case 0x05: |
| 1448 | | // out cf8,op2 |
| 1449 | | // in acc,cfc |
| 1450 | | debug_console_printf(machine,"PEEKPCI ACC=PCICONF[%s]\n",sop2); |
| 1451 | | break; |
| 1452 | | case 0x06: |
| 1453 | | debug_console_printf(machine,"AND/OR ACC=(ACC & %s) | %s\n",sop2,sop1); |
| 1454 | | break; |
| 1455 | | case 0x07: |
| 1456 | | debug_console_printf(machine,"BRA PC=%s\n",pcrel); |
| 1457 | | break; |
| 1458 | | case 0x08: |
| 1459 | | debug_console_printf(machine,"INB ACC=PORT[%s]\n",sop2); |
| 1460 | | break; |
| 1461 | | case 0x09: |
| 1462 | | debug_console_printf(machine,"PEEK ACC=MEM[%s]\n",sop2); |
| 1463 | | break; |
| 1464 | | case 0xee: |
| 1465 | | debug_console_printf(machine,"END\n"); |
| 1466 | | break; |
| 1467 | | default: |
| 1468 | | debug_console_printf(machine,"NOP ????\n"); |
| 1469 | | break; |
| 533 | case 0x01: |
| 534 | // if ((op2 & 0xff) == 0x880) op1=op1 & 0xfffffffd |
| 535 | // out cf8,op2 |
| 536 | // out cfc,op1 |
| 537 | // out cf8,0 |
| 538 | // cf8 (CONFIG_ADDRESS) format: |
| 539 | // 31 30 24 23 16 15 11 10 8 7 2 1 0 |
| 540 | // +-+----------+------------+---------------+-----------------+-----------------+-+-+ |
| 541 | // | | Reserved | Bus Number | Device Number | Function Number | Register Number |0|0| |
| 542 | // +-+----------+------------+---------------+-----------------+-----------------+-+-+ |
| 543 | // 31 - Enable bit |
| 544 | debug_console_printf(machine, "POKEPCI PCICONF[%s]=%s\n", sop2, sop1); |
| 545 | break; |
| 546 | case 0x02: |
| 547 | debug_console_printf(machine, "OUTB PORT[%s]=%s\n", sop2, sop1); |
| 548 | break; |
| 549 | case 0x03: |
| 550 | debug_console_printf(machine, "POKE MEM[%s]=%s\n", sop2, sop1); |
| 551 | break; |
| 552 | case 0x04: |
| 553 | debug_console_printf(machine, "BNE IF ACC != %s THEN PC=%s\n", sop2, pcrel); |
| 554 | break; |
| 555 | case 0x05: |
| 556 | // out cf8,op2 |
| 557 | // in acc,cfc |
| 558 | debug_console_printf(machine, "PEEKPCI ACC=PCICONF[%s]\n", sop2); |
| 559 | break; |
| 560 | case 0x06: |
| 561 | debug_console_printf(machine, "AND/OR ACC=(ACC & %s) | %s\n", sop2, sop1); |
| 562 | break; |
| 563 | case 0x07: |
| 564 | debug_console_printf(machine, "BRA PC=%s\n", pcrel); |
| 565 | break; |
| 566 | case 0x08: |
| 567 | debug_console_printf(machine, "INB ACC=PORT[%s]\n", sop2); |
| 568 | break; |
| 569 | case 0x09: |
| 570 | debug_console_printf(machine, "PEEK ACC=MEM[%s]\n", sop2); |
| 571 | break; |
| 572 | case 0xee: |
| 573 | debug_console_printf(machine, "END\n"); |
| 574 | break; |
| 575 | default: |
| 576 | debug_console_printf(machine, "NOP ????\n"); |
| 577 | break; |
| 1470 | 578 | } |
| 1471 | 579 | if (opcode == 0xee) |
| 1472 | 580 | break; |
| 1473 | 581 | if (size <= 9) |
| 1474 | 582 | break; |
| 1475 | | size-=9; |
| 583 | size -= 9; |
| 1476 | 584 | } |
| 1477 | 585 | } |
| 1478 | 586 | |
| 1479 | 587 | static void jamtable_disasm_command(running_machine &machine, int ref, int params, const char **param) |
| 1480 | 588 | { |
| 1481 | 589 | chihiro_state *state = machine.driver_data<chihiro_state>(); |
| 1482 | | address_space &space=state->m_maincpu->space(); |
| 1483 | | UINT64 addr,size; |
| 590 | address_space &space = state->m_maincpu->space(); |
| 591 | UINT64 addr, size; |
| 1484 | 592 | |
| 1485 | 593 | if (params < 2) |
| 1486 | 594 | return; |
| r242208 | r242209 | |
| 1494 | 602 | static void dump_string_command(running_machine &machine, int ref, int params, const char **param) |
| 1495 | 603 | { |
| 1496 | 604 | chihiro_state *state = machine.driver_data<chihiro_state>(); |
| 1497 | | address_space &space=state->m_maincpu->space(); |
| 605 | address_space &space = state->m_maincpu->space(); |
| 1498 | 606 | UINT64 addr; |
| 1499 | 607 | offs_t address; |
| 1500 | | UINT32 length,maximumlength; |
| 608 | UINT32 length, maximumlength; |
| 1501 | 609 | offs_t buffer; |
| 1502 | 610 | |
| 1503 | 611 | if (params < 1) |
| 1504 | 612 | return; |
| 1505 | 613 | if (!debug_command_parameter_number(machine, param[0], &addr)) |
| 1506 | 614 | return; |
| 1507 | | address=(offs_t)addr; |
| 1508 | | if (!debug_cpu_translate(space,TRANSLATE_READ_DEBUG,&address)) |
| 615 | address = (offs_t)addr; |
| 616 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 1509 | 617 | { |
| 1510 | | debug_console_printf(machine,"Address is unmapped.\n"); |
| 618 | debug_console_printf(machine, "Address is unmapped.\n"); |
| 1511 | 619 | return; |
| 1512 | 620 | } |
| 1513 | | length=space.read_word_unaligned(address); |
| 1514 | | maximumlength=space.read_word_unaligned(address+2); |
| 1515 | | buffer=space.read_dword_unaligned(address+4); |
| 1516 | | debug_console_printf(machine,"Length %d word\n",length); |
| 1517 | | debug_console_printf(machine,"MaximumLength %d word\n",maximumlength); |
| 1518 | | debug_console_printf(machine,"Buffer %08X byte* ",buffer); |
| 1519 | | if (!debug_cpu_translate(space,TRANSLATE_READ_DEBUG,&buffer)) |
| 621 | length = space.read_word_unaligned(address); |
| 622 | maximumlength = space.read_word_unaligned(address + 2); |
| 623 | buffer = space.read_dword_unaligned(address + 4); |
| 624 | debug_console_printf(machine, "Length %d word\n", length); |
| 625 | debug_console_printf(machine, "MaximumLength %d word\n", maximumlength); |
| 626 | debug_console_printf(machine, "Buffer %08X byte* ", buffer); |
| 627 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &buffer)) |
| 1520 | 628 | { |
| 1521 | | debug_console_printf(machine,"\nBuffer is unmapped.\n"); |
| 629 | debug_console_printf(machine, "\nBuffer is unmapped.\n"); |
| 1522 | 630 | return; |
| 1523 | 631 | } |
| 1524 | 632 | if (length > 256) |
| 1525 | | length=256; |
| 1526 | | for (int a=0;a < length;a++) |
| 633 | length = 256; |
| 634 | for (int a = 0; a < length; a++) |
| 1527 | 635 | { |
| 1528 | | UINT8 c=space.read_byte(buffer+a); |
| 1529 | | debug_console_printf(machine,"%c",c); |
| 636 | UINT8 c = space.read_byte(buffer + a); |
| 637 | debug_console_printf(machine, "%c", c); |
| 1530 | 638 | } |
| 1531 | | debug_console_printf(machine,"\n"); |
| 639 | debug_console_printf(machine, "\n"); |
| 1532 | 640 | } |
| 1533 | 641 | |
| 1534 | 642 | static void dump_process_command(running_machine &machine, int ref, int params, const char **param) |
| 1535 | 643 | { |
| 1536 | 644 | chihiro_state *state = machine.driver_data<chihiro_state>(); |
| 1537 | | address_space &space=state->m_maincpu->space(); |
| 645 | address_space &space = state->m_maincpu->space(); |
| 1538 | 646 | UINT64 addr; |
| 1539 | 647 | offs_t address; |
| 1540 | 648 | |
| r242208 | r242209 | |
| 1542 | 650 | return; |
| 1543 | 651 | if (!debug_command_parameter_number(machine, param[0], &addr)) |
| 1544 | 652 | return; |
| 1545 | | address=(offs_t)addr; |
| 1546 | | if (!debug_cpu_translate(space,TRANSLATE_READ_DEBUG,&address)) |
| 653 | address = (offs_t)addr; |
| 654 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 1547 | 655 | { |
| 1548 | | debug_console_printf(machine,"Address is unmapped.\n"); |
| 656 | debug_console_printf(machine, "Address is unmapped.\n"); |
| 1549 | 657 | return; |
| 1550 | 658 | } |
| 1551 | | debug_console_printf(machine,"ReadyListHead {%08X,%08X} _LIST_ENTRY\n",space.read_dword_unaligned(address),space.read_dword_unaligned(address+4)); |
| 1552 | | debug_console_printf(machine,"ThreadListHead {%08X,%08X} _LIST_ENTRY\n",space.read_dword_unaligned(address+8),space.read_dword_unaligned(address+12)); |
| 1553 | | debug_console_printf(machine,"StackCount %d dword\n",space.read_dword_unaligned(address+16)); |
| 1554 | | debug_console_printf(machine,"ThreadQuantum %d dword\n",space.read_dword_unaligned(address+20)); |
| 1555 | | debug_console_printf(machine,"BasePriority %d byte\n",space.read_byte(address+24)); |
| 1556 | | debug_console_printf(machine,"DisableBoost %d byte\n",space.read_byte(address+25)); |
| 1557 | | debug_console_printf(machine,"DisableQuantum %d byte\n",space.read_byte(address+26)); |
| 1558 | | debug_console_printf(machine,"_padding %d byte\n",space.read_byte(address+27)); |
| 659 | debug_console_printf(machine, "ReadyListHead {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address), space.read_dword_unaligned(address + 4)); |
| 660 | debug_console_printf(machine, "ThreadListHead {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 8), space.read_dword_unaligned(address + 12)); |
| 661 | debug_console_printf(machine, "StackCount %d dword\n", space.read_dword_unaligned(address + 16)); |
| 662 | debug_console_printf(machine, "ThreadQuantum %d dword\n", space.read_dword_unaligned(address + 20)); |
| 663 | debug_console_printf(machine, "BasePriority %d byte\n", space.read_byte(address + 24)); |
| 664 | debug_console_printf(machine, "DisableBoost %d byte\n", space.read_byte(address + 25)); |
| 665 | debug_console_printf(machine, "DisableQuantum %d byte\n", space.read_byte(address + 26)); |
| 666 | debug_console_printf(machine, "_padding %d byte\n", space.read_byte(address + 27)); |
| 1559 | 667 | } |
| 1560 | 668 | |
| 1561 | 669 | static void dump_list_command(running_machine &machine, int ref, int params, const char **param) |
| 1562 | 670 | { |
| 1563 | 671 | chihiro_state *state = machine.driver_data<chihiro_state>(); |
| 1564 | | address_space &space=state->m_maincpu->space(); |
| 1565 | | UINT64 addr,offs,start,old; |
| 1566 | | offs_t address,offset; |
| 672 | address_space &space = state->m_maincpu->space(); |
| 673 | UINT64 addr, offs, start, old; |
| 674 | offs_t address, offset; |
| 1567 | 675 | |
| 1568 | 676 | if (params < 1) |
| 1569 | 677 | return; |
| 1570 | 678 | if (!debug_command_parameter_number(machine, param[0], &addr)) |
| 1571 | 679 | return; |
| 1572 | | offs=0; |
| 1573 | | offset=0; |
| 680 | offs = 0; |
| 681 | offset = 0; |
| 1574 | 682 | if (params >= 2) |
| 1575 | 683 | { |
| 1576 | 684 | if (!debug_command_parameter_number(machine, param[1], &offs)) |
| 1577 | 685 | return; |
| 1578 | | offset=(offs_t)offs; |
| 686 | offset = (offs_t)offs; |
| 1579 | 687 | } |
| 1580 | | start=addr; |
| 1581 | | address=(offs_t)addr; |
| 1582 | | if (!debug_cpu_translate(space,TRANSLATE_READ_DEBUG,&address)) |
| 688 | start = addr; |
| 689 | address = (offs_t)addr; |
| 690 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 1583 | 691 | { |
| 1584 | | debug_console_printf(machine,"Address is unmapped.\n"); |
| 692 | debug_console_printf(machine, "Address is unmapped.\n"); |
| 1585 | 693 | return; |
| 1586 | 694 | } |
| 1587 | 695 | if (params >= 2) |
| 1588 | | debug_console_printf(machine,"Entry Object\n"); |
| 696 | debug_console_printf(machine, "Entry Object\n"); |
| 1589 | 697 | else |
| 1590 | | debug_console_printf(machine,"Entry\n"); |
| 1591 | | for (int num=0;num < 32;num++) |
| 698 | debug_console_printf(machine, "Entry\n"); |
| 699 | for (int num = 0; num < 32; num++) |
| 1592 | 700 | { |
| 1593 | 701 | if (params >= 2) |
| 1594 | | debug_console_printf(machine,"%08X %08X\n",(UINT32)addr,(offs_t)addr-offset); |
| 702 | debug_console_printf(machine, "%08X %08X\n", (UINT32)addr, (offs_t)addr - offset); |
| 1595 | 703 | else |
| 1596 | | debug_console_printf(machine,"%08X\n",(UINT32)addr); |
| 1597 | | old=addr; |
| 1598 | | addr=space.read_dword_unaligned(address); |
| 704 | debug_console_printf(machine, "%08X\n", (UINT32)addr); |
| 705 | old = addr; |
| 706 | addr = space.read_dword_unaligned(address); |
| 1599 | 707 | if (addr == start) |
| 1600 | 708 | break; |
| 1601 | 709 | if (addr == old) |
| 1602 | 710 | break; |
| 1603 | | address=(offs_t)addr; |
| 1604 | | if (!debug_cpu_translate(space,TRANSLATE_READ_DEBUG,&address)) |
| 711 | address = (offs_t)addr; |
| 712 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 1605 | 713 | break; |
| 1606 | 714 | } |
| 1607 | 715 | } |
| r242208 | r242209 | |
| 1609 | 717 | static void curthread_command(running_machine &machine, int ref, int params, const char **param) |
| 1610 | 718 | { |
| 1611 | 719 | chihiro_state *state = machine.driver_data<chihiro_state>(); |
| 1612 | | address_space &space=state->m_maincpu->space(); |
| 720 | address_space &space = state->m_maincpu->space(); |
| 1613 | 721 | UINT64 fsbase; |
| 1614 | | UINT32 kthrd,topstack,tlsdata; |
| 722 | UINT32 kthrd, topstack, tlsdata; |
| 1615 | 723 | offs_t address; |
| 1616 | 724 | |
| 1617 | 725 | fsbase = state->m_maincpu->state_int(44); |
| 1618 | | address=(offs_t)fsbase+0x28; |
| 1619 | | if (!debug_cpu_translate(space,TRANSLATE_READ_DEBUG,&address)) |
| 726 | address = (offs_t)fsbase + 0x28; |
| 727 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 1620 | 728 | { |
| 1621 | | debug_console_printf(machine,"Address is unmapped.\n"); |
| 729 | debug_console_printf(machine, "Address is unmapped.\n"); |
| 1622 | 730 | return; |
| 1623 | 731 | } |
| 1624 | | kthrd=space.read_dword_unaligned(address); |
| 1625 | | debug_console_printf(machine,"Current thread is %08X\n",kthrd); |
| 1626 | | address=(offs_t)kthrd+0x1c; |
| 1627 | | if (!debug_cpu_translate(space,TRANSLATE_READ_DEBUG,&address)) |
| 732 | kthrd = space.read_dword_unaligned(address); |
| 733 | debug_console_printf(machine, "Current thread is %08X\n", kthrd); |
| 734 | address = (offs_t)kthrd + 0x1c; |
| 735 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 1628 | 736 | return; |
| 1629 | | topstack=space.read_dword_unaligned(address); |
| 1630 | | debug_console_printf(machine,"Current thread stack top is %08X\n",topstack); |
| 1631 | | address=(offs_t)kthrd+0x28; |
| 1632 | | if (!debug_cpu_translate(space,TRANSLATE_READ_DEBUG,&address)) |
| 737 | topstack = space.read_dword_unaligned(address); |
| 738 | debug_console_printf(machine, "Current thread stack top is %08X\n", topstack); |
| 739 | address = (offs_t)kthrd + 0x28; |
| 740 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 1633 | 741 | return; |
| 1634 | | tlsdata=space.read_dword_unaligned(address); |
| 742 | tlsdata = space.read_dword_unaligned(address); |
| 1635 | 743 | if (tlsdata == 0) |
| 1636 | | address=(offs_t)topstack-0x210-8; |
| 744 | address = (offs_t)topstack - 0x210 - 8; |
| 1637 | 745 | else |
| 1638 | | address=(offs_t)tlsdata-8; |
| 1639 | | if (!debug_cpu_translate(space,TRANSLATE_READ_DEBUG,&address)) |
| 746 | address = (offs_t)tlsdata - 8; |
| 747 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 1640 | 748 | return; |
| 1641 | | debug_console_printf(machine,"Current thread function is %08X\n",space.read_dword_unaligned(address)); |
| 749 | debug_console_printf(machine, "Current thread function is %08X\n", space.read_dword_unaligned(address)); |
| 1642 | 750 | } |
| 1643 | 751 | |
| 1644 | 752 | static void generate_irq_command(running_machine &machine, int ref, int params, const char **param) |
| 1645 | 753 | { |
| 1646 | 754 | UINT64 irq; |
| 1647 | | chihiro_state *chst=machine.driver_data<chihiro_state>(); |
| 755 | chihiro_state *chst = machine.driver_data<chihiro_state>(); |
| 1648 | 756 | |
| 1649 | 757 | if (params < 1) |
| 1650 | 758 | return; |
| r242208 | r242209 | |
| 1654 | 762 | return; |
| 1655 | 763 | if (irq == 2) |
| 1656 | 764 | return; |
| 1657 | | chst->debug_generate_irq((int)irq,true); |
| 765 | chst->debug_generate_irq((int)irq, true); |
| 1658 | 766 | } |
| 1659 | 767 | |
| 1660 | 768 | static void nv2a_combiners_command(running_machine &machine, int ref, int params, const char **param) |
| 1661 | 769 | { |
| 1662 | 770 | int en; |
| 1663 | 771 | |
| 1664 | | chihiro_state *chst=machine.driver_data<chihiro_state>(); |
| 1665 | | en=chst->nvidia_nv2a->toggle_register_combiners_usage(); |
| 772 | chihiro_state *chst = machine.driver_data<chihiro_state>(); |
| 773 | en = chst->nvidia_nv2a->toggle_register_combiners_usage(); |
| 1666 | 774 | if (en != 0) |
| 1667 | | debug_console_printf(machine,"Register combiners enabled\n"); |
| 775 | debug_console_printf(machine, "Register combiners enabled\n"); |
| 1668 | 776 | else |
| 1669 | | debug_console_printf(machine,"Register combiners disabled\n"); |
| 777 | debug_console_printf(machine, "Register combiners disabled\n"); |
| 1670 | 778 | } |
| 1671 | 779 | |
| 1672 | 780 | static void grab_texture_command(running_machine &machine, int ref, int params, const char **param) |
| r242208 | r242209 | |
| 1680 | 788 | return; |
| 1681 | 789 | if ((param[1][0] == 0) || (strlen(param[1]) > 127)) |
| 1682 | 790 | return; |
| 1683 | | chst->nvidia_nv2a->debug_grab_texture((int)type,param[1]); |
| 791 | chst->nvidia_nv2a->debug_grab_texture((int)type, param[1]); |
| 1684 | 792 | } |
| 1685 | 793 | |
| 1686 | 794 | static void grab_vprog_command(running_machine &machine, int ref, int params, const char **param) |
| r242208 | r242209 | |
| 1728 | 836 | if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &addr)) |
| 1729 | 837 | return; |
| 1730 | 838 | instruction[0] = space.read_dword_unaligned(address); |
| 1731 | | instruction[1] = space.read_dword_unaligned(address+4); |
| 1732 | | instruction[2] = space.read_dword_unaligned(address+8); |
| 1733 | | instruction[3] = space.read_dword_unaligned(address+12); |
| 1734 | | } else |
| 839 | instruction[1] = space.read_dword_unaligned(address + 4); |
| 840 | instruction[2] = space.read_dword_unaligned(address + 8); |
| 841 | instruction[3] = space.read_dword_unaligned(address + 12); |
| 842 | } |
| 843 | else |
| 1735 | 844 | chst->nvidia_nv2a->debug_grab_vertex_program_slot((int)address, instruction); |
| 1736 | 845 | while (vd.disassemble(instruction, line) != 0) |
| 1737 | 846 | debug_console_printf(machine, "%s\n", line); |
| r242208 | r242209 | |
| 1745 | 854 | |
| 1746 | 855 | static void help_command(running_machine &machine, int ref, int params, const char **param) |
| 1747 | 856 | { |
| 1748 | | debug_console_printf(machine,"Available Chihiro commands:\n"); |
| 1749 | | debug_console_printf(machine," chihiro jamdis,<start>,<size> -- Disassemble <size> bytes of JamTable instructions starting at <start>\n"); |
| 1750 | | debug_console_printf(machine," chihiro dump_string,<address> -- Dump _STRING object at <address>\n"); |
| 1751 | | debug_console_printf(machine," chihiro dump_process,<address> -- Dump _PROCESS object at <address>\n"); |
| 1752 | | debug_console_printf(machine," chihiro dump_list,<address>[,<offset>] -- Dump _LIST_ENTRY chain starting at <address>\n"); |
| 1753 | | debug_console_printf(machine," chihiro curthread -- Print information about current thread\n"); |
| 1754 | | debug_console_printf(machine," chihiro irq,<number> -- Generate interrupt with irq number 0-15\n"); |
| 1755 | | debug_console_printf(machine," chihiro nv2a_combiners -- Toggle use of register combiners\n"); |
| 1756 | | debug_console_printf(machine," chihiro grab_texture,<type>,<filename> -- Save to <filename> the next used texture of type <type>\n"); |
| 1757 | | debug_console_printf(machine," chihiro grab_vprog,<filename> -- save current vertex program instruction slots to <filename>\n"); |
| 1758 | | debug_console_printf(machine," chihiro vprogdis,<address>,<length>[,<type>] -- disassemble <lenght> vertex program instructions at <address> of <type>\n"); |
| 1759 | | debug_console_printf(machine," chihiro help -- this list\n"); |
| 857 | debug_console_printf(machine, "Available Chihiro commands:\n"); |
| 858 | debug_console_printf(machine, " chihiro jamdis,<start>,<size> -- Disassemble <size> bytes of JamTable instructions starting at <start>\n"); |
| 859 | debug_console_printf(machine, " chihiro dump_string,<address> -- Dump _STRING object at <address>\n"); |
| 860 | debug_console_printf(machine, " chihiro dump_process,<address> -- Dump _PROCESS object at <address>\n"); |
| 861 | debug_console_printf(machine, " chihiro dump_list,<address>[,<offset>] -- Dump _LIST_ENTRY chain starting at <address>\n"); |
| 862 | debug_console_printf(machine, " chihiro curthread -- Print information about current thread\n"); |
| 863 | debug_console_printf(machine, " chihiro irq,<number> -- Generate interrupt with irq number 0-15\n"); |
| 864 | debug_console_printf(machine, " chihiro nv2a_combiners -- Toggle use of register combiners\n"); |
| 865 | debug_console_printf(machine, " chihiro grab_texture,<type>,<filename> -- Save to <filename> the next used texture of type <type>\n"); |
| 866 | debug_console_printf(machine, " chihiro grab_vprog,<filename> -- save current vertex program instruction slots to <filename>\n"); |
| 867 | debug_console_printf(machine, " chihiro vprogdis,<address>,<length>[,<type>] -- disassemble <lenght> vertex program instructions at <address> of <type>\n"); |
| 868 | debug_console_printf(machine, " chihiro help -- this list\n"); |
| 1760 | 869 | } |
| 1761 | 870 | |
| 1762 | 871 | static void chihiro_debug_commands(running_machine &machine, int ref, int params, const char **param) |
| 1763 | 872 | { |
| 1764 | 873 | if (params < 1) |
| 1765 | 874 | return; |
| 1766 | | if (strcmp("jamdis",param[0]) == 0) |
| 1767 | | jamtable_disasm_command(machine,ref,params-1,param+1); |
| 1768 | | else if (strcmp("dump_string",param[0]) == 0) |
| 1769 | | dump_string_command(machine,ref,params-1,param+1); |
| 1770 | | else if (strcmp("dump_process",param[0]) == 0) |
| 1771 | | dump_process_command(machine,ref,params-1,param+1); |
| 1772 | | else if (strcmp("dump_list",param[0]) == 0) |
| 1773 | | dump_list_command(machine,ref,params-1,param+1); |
| 1774 | | else if (strcmp("curthread",param[0]) == 0) |
| 1775 | | curthread_command(machine,ref,params-1,param+1); |
| 1776 | | else if (strcmp("irq",param[0]) == 0) |
| 1777 | | generate_irq_command(machine,ref,params-1,param+1); |
| 1778 | | else if (strcmp("nv2a_combiners",param[0]) == 0) |
| 1779 | | nv2a_combiners_command(machine,ref,params-1,param+1); |
| 875 | if (strcmp("jamdis", param[0]) == 0) |
| 876 | jamtable_disasm_command(machine, ref, params - 1, param + 1); |
| 877 | else if (strcmp("dump_string", param[0]) == 0) |
| 878 | dump_string_command(machine, ref, params - 1, param + 1); |
| 879 | else if (strcmp("dump_process", param[0]) == 0) |
| 880 | dump_process_command(machine, ref, params - 1, param + 1); |
| 881 | else if (strcmp("dump_list", param[0]) == 0) |
| 882 | dump_list_command(machine, ref, params - 1, param + 1); |
| 883 | else if (strcmp("curthread", param[0]) == 0) |
| 884 | curthread_command(machine, ref, params - 1, param + 1); |
| 885 | else if (strcmp("irq", param[0]) == 0) |
| 886 | generate_irq_command(machine, ref, params - 1, param + 1); |
| 887 | else if (strcmp("nv2a_combiners", param[0]) == 0) |
| 888 | nv2a_combiners_command(machine, ref, params - 1, param + 1); |
| 1780 | 889 | else if (strcmp("grab_texture", param[0]) == 0) |
| 1781 | 890 | grab_texture_command(machine, ref, params - 1, param + 1); |
| 1782 | 891 | else if (strcmp("grab_vprog", param[0]) == 0) |
| r242208 | r242209 | |
| 1784 | 893 | else if (strcmp("vprogdis", param[0]) == 0) |
| 1785 | 894 | vprogdis_command(machine, ref, params - 1, param + 1); |
| 1786 | 895 | else |
| 1787 | | help_command(machine,ref,params-1,param+1); |
| 896 | help_command(machine, ref, params - 1, param + 1); |
| 1788 | 897 | } |
| 1789 | 898 | |
| 1790 | | /* |
| 1791 | | * Graphics |
| 1792 | | */ |
| 1793 | | |
| 1794 | | UINT32 nv2a_renderer::dilate0(UINT32 value,int bits) // dilate first "bits" bits in "value" |
| 899 | void chihiro_state::debug_generate_irq(int irq, bool active) |
| 1795 | 900 | { |
| 1796 | | UINT32 x,m1,m2,m3; |
| 1797 | | int a; |
| 1798 | | |
| 1799 | | x = value; |
| 1800 | | for (a=0;a < bits;a++) |
| 1801 | | { |
| 1802 | | m2 = 1 << (a << 1); |
| 1803 | | m1 = m2 - 1; |
| 1804 | | m3 = (~m1) << 1; |
| 1805 | | x = (x & m1) + (x & m2) + ((x & m3) << 1); |
| 1806 | | } |
| 1807 | | return x; |
| 1808 | | } |
| 1809 | | |
| 1810 | | UINT32 nv2a_renderer::dilate1(UINT32 value,int bits) // dilate first "bits" bits in "value" |
| 1811 | | { |
| 1812 | | UINT32 x,m1,m2,m3; |
| 1813 | | int a; |
| 1814 | | |
| 1815 | | x = value; |
| 1816 | | for (a=0;a < bits;a++) |
| 1817 | | { |
| 1818 | | m2 = 1 << (a << 1); |
| 1819 | | m1 = m2 - 1; |
| 1820 | | m3 = (~m1) << 1; |
| 1821 | | x = (x & m1) + ((x & m2) << 1) + ((x & m3) << 1); |
| 1822 | | } |
| 1823 | | return x; |
| 1824 | | } |
| 1825 | | |
| 1826 | | void nv2a_renderer::computedilated(void) |
| 1827 | | { |
| 1828 | | int a,b; |
| 1829 | | |
| 1830 | | for (b=0;b < 16;b++) |
| 1831 | | for (a=0;a < 2048;a++) { |
| 1832 | | dilated0[b][a]=dilate0(a,b); |
| 1833 | | dilated1[b][a]=dilate1(a,b); |
| 1834 | | } |
| 1835 | | for (b=0;b < 16;b++) |
| 1836 | | for (a=0;a < 16;a++) |
| 1837 | | dilatechose[(b << 4) + a]=(a < b ? a : b); |
| 1838 | | } |
| 1839 | | |
| 1840 | | int nv2a_renderer::geforce_commandkind(UINT32 word) |
| 1841 | | { |
| 1842 | | if ((word & 0x00000003) == 0x00000002) |
| 1843 | | return 7; // call |
| 1844 | | if ((word & 0x00000003) == 0x00000001) |
| 1845 | | return 6; // jump |
| 1846 | | if ((word & 0xE0030003) == 0x40000000) |
| 1847 | | return 5; // non increasing |
| 1848 | | if ((word & 0xE0000003) == 0x20000000) |
| 1849 | | return 4; // old jump |
| 1850 | | if ((word & 0xFFFF0003) == 0x00030000) |
| 1851 | | return 3; // long non icreasing |
| 1852 | | if ((word & 0xFFFFFFFF) == 0x00020000) |
| 1853 | | return 2; // return |
| 1854 | | if ((word & 0xFFFF0003) == 0x00010000) |
| 1855 | | return 1; // sli conditional |
| 1856 | | if ((word & 0xE0030003) == 0x00000000) |
| 1857 | | return 0; // increasing |
| 1858 | | return -1; |
| 1859 | | } |
| 1860 | | |
| 1861 | | UINT32 nv2a_renderer::geforce_object_offset(UINT32 handle) |
| 1862 | | { |
| 1863 | | UINT32 h=((((handle >> 11) ^ handle) >> 11) ^ handle) & 0x7ff; |
| 1864 | | UINT32 o=(pfifo[0x210/4] & 0x1f) << 8; // or 12 ? |
| 1865 | | UINT32 e=o+h*8; // at 0xfd000000+0x00700000 |
| 1866 | | UINT32 w; |
| 1867 | | |
| 1868 | | if (ramin[e/4] != handle) |
| 1869 | | e=0; |
| 1870 | | w=ramin[e/4+1]; |
| 1871 | | return (w & 0xffff)*0x10; |
| 1872 | | } |
| 1873 | | |
| 1874 | | void nv2a_renderer::geforce_read_dma_object(UINT32 handle,UINT32 &offset,UINT32 &size) |
| 1875 | | { |
| 1876 | | //UINT32 objclass,pt_present,pt_linear,access,target,rorw; |
| 1877 | | UINT32 dma_adjust,dma_frame; |
| 1878 | | UINT32 o=geforce_object_offset(handle); |
| 1879 | | |
| 1880 | | o=o/4; |
| 1881 | | //objclass=ramin[o] & 0xfff; |
| 1882 | | //pt_present=(ramin[o] >> 12) & 1; |
| 1883 | | //pt_linear=(ramin[o] >> 13) & 1; |
| 1884 | | //access=(ramin[o] >> 14) & 3; |
| 1885 | | //target=(ramin[o] >> 16) & 3; |
| 1886 | | dma_adjust=(ramin[o] >> 20) & 0xfff; |
| 1887 | | size=ramin[o+1]; |
| 1888 | | //rorw=ramin[o+2] & 1; |
| 1889 | | dma_frame=ramin[o+2] & 0xfffff000; |
| 1890 | | offset=dma_frame+dma_adjust; |
| 1891 | | } |
| 1892 | | |
| 1893 | | /*void myline(bitmap_rgb32 &bmp,float x1,float y1,float x2,float y2) |
| 1894 | | { |
| 1895 | | int xx1,yy1,xx2,yy2; |
| 1896 | | |
| 1897 | | xx1=x1; |
| 1898 | | xx2=x2; |
| 1899 | | yy1=y1; |
| 1900 | | yy2=y2; |
| 1901 | | if (xx1 == xx2) { |
| 1902 | | if (yy1 > yy2) { |
| 1903 | | int t=yy1; |
| 1904 | | yy1=yy2; |
| 1905 | | yy2=t; |
| 1906 | | } |
| 1907 | | for (int y=yy1;y <= yy2;y++) |
| 1908 | | *((UINT32 *)bmp.raw_pixptr(y,xx1))= -1; |
| 1909 | | } else if (yy1 == yy2) { |
| 1910 | | if (xx1 > xx2) { |
| 1911 | | int t=xx1; |
| 1912 | | xx1=xx2; |
| 1913 | | xx2=t; |
| 1914 | | } |
| 1915 | | for (int x=xx1;x <= xx2;x++) |
| 1916 | | *((UINT32 *)bmp.raw_pixptr(yy1,x))= -1; |
| 1917 | | } |
| 1918 | | }*/ |
| 1919 | | |
| 1920 | | inline UINT32 convert_a4r4g4b4_a8r8g8b8(UINT32 a4r4g4b4) |
| 1921 | | { |
| 1922 | | UINT32 a8r8g8b8; |
| 1923 | | int ca,cr,cg,cb; |
| 1924 | | |
| 1925 | | cb=pal4bit(a4r4g4b4 & 0x000f); |
| 1926 | | cg=pal4bit((a4r4g4b4 & 0x00f0) >> 4); |
| 1927 | | cr=pal4bit((a4r4g4b4 & 0x0f00) >> 8); |
| 1928 | | ca=pal4bit((a4r4g4b4 & 0xf000) >> 12); |
| 1929 | | a8r8g8b8=(ca<<24)|(cr<<16)|(cg<<8)|(cb); // color converted to 8 bits per component |
| 1930 | | return a8r8g8b8; |
| 1931 | | } |
| 1932 | | |
| 1933 | | inline UINT32 convert_a1r5g5b5_a8r8g8b8(UINT32 a1r5g5b5) |
| 1934 | | { |
| 1935 | | UINT32 a8r8g8b8; |
| 1936 | | int ca,cr,cg,cb; |
| 1937 | | |
| 1938 | | cb=pal5bit(a1r5g5b5 & 0x001f); |
| 1939 | | cg=pal5bit((a1r5g5b5 & 0x03e0) >> 5); |
| 1940 | | cr=pal5bit((a1r5g5b5 & 0x7c00) >> 10); |
| 1941 | | ca=a1r5g5b5 & 0x8000 ? 0xff : 0; |
| 1942 | | a8r8g8b8=(ca<<24)|(cr<<16)|(cg<<8)|(cb); // color converted to 8 bits per component |
| 1943 | | return a8r8g8b8; |
| 1944 | | } |
| 1945 | | |
| 1946 | | inline UINT32 convert_r5g6b5_r8g8b8(UINT32 r5g6b5) |
| 1947 | | { |
| 1948 | | UINT32 r8g8b8; |
| 1949 | | int cr,cg,cb; |
| 1950 | | |
| 1951 | | cb=pal5bit(r5g6b5 & 0x001f); |
| 1952 | | cg=pal6bit((r5g6b5 & 0x07e0) >> 5); |
| 1953 | | cr=pal5bit((r5g6b5 & 0xf800) >> 11); |
| 1954 | | r8g8b8=(cr<<16)|(cg<<8)|(cb); // color converted to 8 bits per component |
| 1955 | | return r8g8b8; |
| 1956 | | } |
| 1957 | | |
| 1958 | | UINT32 nv2a_renderer::texture_get_texel(int number,int x,int y) |
| 1959 | | { |
| 1960 | | UINT32 to, s, c, sa, ca; |
| 1961 | | UINT32 a4r4g4b4, a1r5g5b5, r5g6b5; |
| 1962 | | int bx, by; |
| 1963 | | int color0, color1, color0m2, color1m2, alpha0, alpha1; |
| 1964 | | UINT32 codes; |
| 1965 | | UINT64 alphas; |
| 1966 | | int cr, cg, cb; |
| 1967 | | |
| 1968 | | // force to [0,size-1] |
| 1969 | | x = (unsigned int)x & (texture[number].sizeu - 1); |
| 1970 | | y = (unsigned int)y & (texture[number].sizev - 1); |
| 1971 | | switch (texture[number].format) { |
| 1972 | | case A8R8G8B8: |
| 1973 | | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1974 | | return *(((UINT32 *)texture[number].buffer) + to); // get texel color |
| 1975 | | case DXT1: |
| 1976 | | bx = x >> 2; |
| 1977 | | by = y >> 2; |
| 1978 | | x = x & 3; |
| 1979 | | y = y & 3; |
| 1980 | | to = bx + by*(texture[number].sizeu >> 2); |
| 1981 | | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 0); |
| 1982 | | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 1); |
| 1983 | | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 1); |
| 1984 | | s = (y << 3) + (x << 1); |
| 1985 | | c = (codes >> s) & 3; |
| 1986 | | c = c + (color0 > color1 ? 0 : 4); |
| 1987 | | color0m2 = color0 << 1; |
| 1988 | | color1m2 = color1 << 1; |
| 1989 | | switch (c) { |
| 1990 | | case 0: |
| 1991 | | return 0xff000000 + convert_r5g6b5_r8g8b8(color0); |
| 1992 | | case 1: |
| 1993 | | return 0xff000000 + convert_r5g6b5_r8g8b8(color1); |
| 1994 | | case 2: |
| 1995 | | cb = pal5bit(((color0m2 & 0x003e) + (color1 & 0x001f)) / 3); |
| 1996 | | cg = pal6bit(((color0m2 & 0x0fc0) + (color1 & 0x07e0)) / 3 >> 5); |
| 1997 | | cr = pal5bit(((color0m2 & 0x1f000) + color1) / 3 >> 11); |
| 1998 | | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); |
| 1999 | | case 3: |
| 2000 | | cb = pal5bit(((color1m2 & 0x003e) + (color0 & 0x001f)) / 3); |
| 2001 | | cg = pal6bit(((color1m2 & 0x0fc0) + (color0 & 0x07e0)) / 3 >> 5); |
| 2002 | | cr = pal5bit(((color1m2 & 0x1f000) + color0) / 3 >> 11); |
| 2003 | | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); |
| 2004 | | case 4: |
| 2005 | | return 0xff000000 + convert_r5g6b5_r8g8b8(color0); |
| 2006 | | case 5: |
| 2007 | | return 0xff000000 + convert_r5g6b5_r8g8b8(color1); |
| 2008 | | case 6: |
| 2009 | | cb = pal5bit(((color0 & 0x001f) + (color1 & 0x001f)) / 2); |
| 2010 | | cg = pal6bit(((color0 & 0x07e0) + (color1 & 0x07e0)) / 2 >> 5); |
| 2011 | | cr = pal5bit(((color0 & 0xf800) + (color1 & 0xf800)) / 2 >> 11); |
| 2012 | | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); |
| 2013 | | default: |
| 2014 | | return 0xff000000; |
| 2015 | | } |
| 2016 | | case DXT3: |
| 2017 | | bx = x >> 2; |
| 2018 | | by = y >> 2; |
| 2019 | | x = x & 3; |
| 2020 | | y = y & 3; |
| 2021 | | to = (bx + by*(texture[number].sizeu >> 2)) << 1; |
| 2022 | | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 4); |
| 2023 | | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 5); |
| 2024 | | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 3); |
| 2025 | | alphas = *(((UINT64 *)texture[number].buffer) + to); |
| 2026 | | s = (y << 3) + (x << 1); |
| 2027 | | sa = ((y << 2) + x) << 2; |
| 2028 | | c = (codes >> s) & 3; |
| 2029 | | ca = (alphas >> sa) & 15; |
| 2030 | | switch (c) { |
| 2031 | | case 0: |
| 2032 | | return ((ca + (ca << 4)) << 24) + convert_r5g6b5_r8g8b8(color0); |
| 2033 | | case 1: |
| 2034 | | return ((ca + (ca << 4)) << 24) + convert_r5g6b5_r8g8b8(color1); |
| 2035 | | case 2: |
| 2036 | | cb = pal5bit((2 * (color0 & 0x001f) + (color1 & 0x001f)) / 3); |
| 2037 | | cg = pal6bit((2 * (color0 & 0x07e0) + (color1 & 0x07e0)) / 3 >> 5); |
| 2038 | | cr = pal5bit((2 * (color0 & 0xf800) + (color1 & 0xf800)) / 3 >> 11); |
| 2039 | | return ((ca + (ca << 4)) << 24) | (cr << 16) | (cg << 8) | (cb); |
| 2040 | | default: |
| 2041 | | cb = pal5bit(((color0 & 0x001f) + 2 * (color1 & 0x001f)) / 3); |
| 2042 | | cg = pal6bit(((color0 & 0x07e0) + 2 * (color1 & 0x07e0)) / 3 >> 5); |
| 2043 | | cr = pal5bit(((color0 & 0xf800) + 2 * (color1 & 0xf800)) / 3 >> 11); |
| 2044 | | return ((ca + (ca << 4)) << 24) | (cr << 16) | (cg << 8) | (cb); |
| 2045 | | } |
| 2046 | | case A4R4G4B4: |
| 2047 | | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 2048 | | a4r4g4b4 = *(((UINT16 *)texture[number].buffer) + to); // get texel color |
| 2049 | | return convert_a4r4g4b4_a8r8g8b8(a4r4g4b4); |
| 2050 | | case A1R5G5B5: |
| 2051 | | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 2052 | | a1r5g5b5 = *(((UINT16 *)texture[number].buffer) + to); // get texel color |
| 2053 | | return convert_a1r5g5b5_a8r8g8b8(a1r5g5b5); |
| 2054 | | case R5G6B5: |
| 2055 | | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 2056 | | r5g6b5 = *(((UINT16 *)texture[number].buffer) + to); // get texel color |
| 2057 | | return 0xff000000 + convert_r5g6b5_r8g8b8(r5g6b5); |
| 2058 | | case R8G8B8_RECT: |
| 2059 | | to = texture[number].rectangle_pitch*y + (x << 2); |
| 2060 | | return *((UINT32 *)(((UINT8 *)texture[number].buffer) + to)); |
| 2061 | | case A8R8G8B8_RECT: |
| 2062 | | to = texture[number].rectangle_pitch*y + (x << 2); |
| 2063 | | return *((UINT32 *)(((UINT8 *)texture[number].buffer) + to)); |
| 2064 | | case DXT5: |
| 2065 | | bx = x >> 2; |
| 2066 | | by = y >> 2; |
| 2067 | | x = x & 3; |
| 2068 | | y = y & 3; |
| 2069 | | to = (bx + by*(texture[number].sizeu >> 2)) << 1; |
| 2070 | | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 4); |
| 2071 | | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 5); |
| 2072 | | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 3); |
| 2073 | | alpha0 = *((UINT8 *)(((UINT64 *)texture[number].buffer) + to) + 0); |
| 2074 | | alpha1 = *((UINT8 *)(((UINT64 *)texture[number].buffer) + to) + 1); |
| 2075 | | alphas = *(((UINT64 *)texture[number].buffer) + to); |
| 2076 | | s = (y << 3) + (x << 1); |
| 2077 | | sa = ((y << 2) + x) * 3; |
| 2078 | | c = (codes >> s) & 3; |
| 2079 | | ca = (alphas >> sa) & 7; |
| 2080 | | ca = ca + (alpha0 > alpha1 ? 0 : 8); |
| 2081 | | switch (ca) { |
| 2082 | | case 0: |
| 2083 | | ca = alpha0; |
| 2084 | | break; |
| 2085 | | case 1: |
| 2086 | | ca = alpha1; |
| 2087 | | break; |
| 2088 | | case 2: |
| 2089 | | ca = (6 * alpha0 + 1 * alpha1) / 7; |
| 2090 | | break; |
| 2091 | | case 3: |
| 2092 | | ca = (5 * alpha0 + 2 * alpha1) / 7; |
| 2093 | | break; |
| 2094 | | case 4: |
| 2095 | | ca = (4 * alpha0 + 3 * alpha1) / 7; |
| 2096 | | break; |
| 2097 | | case 5: |
| 2098 | | ca = (3 * alpha0 + 4 * alpha1) / 7; |
| 2099 | | break; |
| 2100 | | case 6: |
| 2101 | | ca = (2 * alpha0 + 5 * alpha1) / 7; |
| 2102 | | break; |
| 2103 | | case 7: |
| 2104 | | ca = (1 * alpha0 + 6 * alpha1) / 7; |
| 2105 | | break; |
| 2106 | | case 8: |
| 2107 | | ca = alpha0; |
| 2108 | | break; |
| 2109 | | case 9: |
| 2110 | | ca = alpha1; |
| 2111 | | break; |
| 2112 | | case 10: |
| 2113 | | ca = (4 * alpha0 + 1 * alpha1) / 5; |
| 2114 | | break; |
| 2115 | | case 11: |
| 2116 | | ca = (3 * alpha0 + 2 * alpha1) / 5; |
| 2117 | | break; |
| 2118 | | case 12: |
| 2119 | | ca = (2 * alpha0 + 3 * alpha1) / 5; |
| 2120 | | break; |
| 2121 | | case 13: |
| 2122 | | ca = (1 * alpha0 + 4 * alpha1) / 5; |
| 2123 | | break; |
| 2124 | | case 14: |
| 2125 | | ca = 0; |
| 2126 | | break; |
| 2127 | | case 15: |
| 2128 | | ca = 255; |
| 2129 | | break; |
| 2130 | | } |
| 2131 | | switch (c) { |
| 2132 | | case 0: |
| 2133 | | return (ca << 24) + convert_r5g6b5_r8g8b8(color0); |
| 2134 | | case 1: |
| 2135 | | return (ca << 24) + convert_r5g6b5_r8g8b8(color1); |
| 2136 | | case 2: |
| 2137 | | cb = pal5bit((2 * (color0 & 0x001f) + (color1 & 0x001f)) / 3); |
| 2138 | | cg = pal6bit((2 * (color0 & 0x07e0) + (color1 & 0x07e0)) / 3 >> 5); |
| 2139 | | cr = pal5bit((2 * (color0 & 0xf800) + (color1 & 0xf800)) / 3 >> 11); |
| 2140 | | return (ca << 24) | (cr << 16) | (cg << 8) | (cb); |
| 2141 | | default: |
| 2142 | | cb = pal5bit(((color0 & 0x001f) + 2 * (color1 & 0x001f)) / 3); |
| 2143 | | cg = pal6bit(((color0 & 0x07e0) + 2 * (color1 & 0x07e0)) / 3 >> 5); |
| 2144 | | cr = pal5bit(((color0 & 0xf800) + 2 * (color1 & 0xf800)) / 3 >> 11); |
| 2145 | | return (ca << 24) | (cr << 16) | (cg << 8) | (cb); |
| 2146 | | } |
| 2147 | | default: |
| 2148 | | return 0xff00ff00; |
| 2149 | | } |
| 2150 | | } |
| 2151 | | |
| 2152 | | void nv2a_renderer::write_pixel(int x, int y, UINT32 color) |
| 2153 | | { |
| 2154 | | void *addr; |
| 2155 | | UINT32 fbcolor; |
| 2156 | | UINT32 c[4], fb[4], s[4], d[4], cc[4]; |
| 2157 | | |
| 2158 | | addr = this->fb.raw_pixptr(y, x); |
| 2159 | | fbcolor = *((UINT32 *)addr); |
| 2160 | | c[3] = color >> 24; |
| 2161 | | c[2] = (color >> 16) & 255; |
| 2162 | | c[1] = (color >> 8) & 255; |
| 2163 | | c[0] = color & 255; |
| 2164 | | fb[3] = fbcolor >> 24; |
| 2165 | | fb[2] = (fbcolor >> 16) & 255; |
| 2166 | | fb[1] = (fbcolor >> 8) & 255; |
| 2167 | | fb[0] = fbcolor & 255; |
| 2168 | | cc[3] = blend_color >> 24; |
| 2169 | | cc[2] = (blend_color >> 16) & 255; |
| 2170 | | cc[1] = (blend_color >> 8) & 255; |
| 2171 | | cc[0] = blend_color & 255; |
| 2172 | | // ownership test and scissor test not done |
| 2173 | | // alpha test |
| 2174 | | if (alpha_test_enabled) { |
| 2175 | | switch (alpha_func) { |
| 2176 | | case nv2a_renderer::NEVER: |
| 2177 | | return; |
| 2178 | | case nv2a_renderer::ALWAYS: |
| 2179 | | default: |
| 2180 | | break; |
| 2181 | | case nv2a_renderer::LESS: |
| 2182 | | if (c[3] >= alpha_reference) |
| 2183 | | return; |
| 2184 | | break; |
| 2185 | | case nv2a_renderer::LEQUAL: |
| 2186 | | if (c[3] > alpha_reference) |
| 2187 | | return; |
| 2188 | | break; |
| 2189 | | case nv2a_renderer::EQUAL: |
| 2190 | | if (c[3] != alpha_reference) |
| 2191 | | return; |
| 2192 | | break; |
| 2193 | | case nv2a_renderer::GEQUAL: |
| 2194 | | if (c[3] < alpha_reference) |
| 2195 | | return; |
| 2196 | | break; |
| 2197 | | case nv2a_renderer::GREATER: |
| 2198 | | if (c[3] <= alpha_reference) |
| 2199 | | return; |
| 2200 | | break; |
| 2201 | | case nv2a_renderer::NOTEQUAL: |
| 2202 | | if (c[3] == alpha_reference) |
| 2203 | | return; |
| 2204 | | break; |
| 2205 | | } |
| 2206 | | } |
| 2207 | | // stencil test not done |
| 2208 | | // depth buffer test not done |
| 2209 | | // blending |
| 2210 | | if (blending_enabled) { |
| 2211 | | switch (blend_function_source) { |
| 2212 | | case nv2a_renderer::ZERO: |
| 2213 | | s[3] = s[2] = s[1] = s[0] = 0; |
| 2214 | | break; |
| 2215 | | case nv2a_renderer::ONE: |
| 2216 | | default: |
| 2217 | | s[3] = s[2] = s[1] = s[0] = 255; |
| 2218 | | break; |
| 2219 | | case nv2a_renderer::DST_COLOR: |
| 2220 | | s[3] = fb[3]; |
| 2221 | | s[2] = fb[2]; |
| 2222 | | s[1] = fb[1]; |
| 2223 | | s[0] = fb[0]; |
| 2224 | | break; |
| 2225 | | case nv2a_renderer::ONE_MINUS_DST_COLOR: |
| 2226 | | s[3] = fb[3] ^ 255; |
| 2227 | | s[2] = fb[2] ^ 255; |
| 2228 | | s[1] = fb[1] ^ 255; |
| 2229 | | s[0] = fb[0] ^ 255; |
| 2230 | | break; |
| 2231 | | case nv2a_renderer::SRC_ALPHA: |
| 2232 | | s[3] = s[2] = s[1] = s[0] = c[3]; |
| 2233 | | break; |
| 2234 | | case nv2a_renderer::ONE_MINUS_SRC_ALPHA: |
| 2235 | | s[3] = s[2] = s[1] = s[0] = c[3] ^ 255; |
| 2236 | | break; |
| 2237 | | case nv2a_renderer::DST_ALPHA: |
| 2238 | | s[3] = s[2] = s[1] = s[0] = fb[3]; |
| 2239 | | break; |
| 2240 | | case nv2a_renderer::ONE_MINUS_DST_ALPHA: |
| 2241 | | s[3] = s[2] = s[1] = s[0] = fb[3] ^ 255; |
| 2242 | | break; |
| 2243 | | case nv2a_renderer::CONSTANT_COLOR: |
| 2244 | | s[3] = cc[3]; |
| 2245 | | s[2] = cc[2]; |
| 2246 | | s[1] = cc[1]; |
| 2247 | | s[0] = cc[0]; |
| 2248 | | break; |
| 2249 | | case nv2a_renderer::ONE_MINUS_CONSTANT_COLOR: |
| 2250 | | s[3] = cc[3] ^ 255; |
| 2251 | | s[2] = cc[2] ^ 255; |
| 2252 | | s[1] = cc[1] ^ 255; |
| 2253 | | s[0] = cc[0] ^ 255; |
| 2254 | | break; |
| 2255 | | case nv2a_renderer::CONSTANT_ALPHA: |
| 2256 | | s[3] = s[2] = s[1] = s[0] = cc[3]; |
| 2257 | | break; |
| 2258 | | case nv2a_renderer::ONE_MINUS_CONSTANT_ALPHA: |
| 2259 | | s[3] = s[2] = s[1] = s[0] = cc[3] ^ 255; |
| 2260 | | break; |
| 2261 | | case nv2a_renderer::SRC_ALPHA_SATURATE: |
| 2262 | | s[3] = 255; |
| 2263 | | if (c[3] < (fb[3] ^ 255)) |
| 2264 | | s[2] = c[3]; |
| 2265 | | else |
| 2266 | | s[2] = fb[3]; |
| 2267 | | s[1] = s[0] = s[2]; |
| 2268 | | break; |
| 2269 | | } |
| 2270 | | switch (blend_function_destination) { |
| 2271 | | case nv2a_renderer::ZERO: |
| 2272 | | default: |
| 2273 | | d[3] = d[2] = d[1] = d[0] = 0; |
| 2274 | | break; |
| 2275 | | case nv2a_renderer::ONE: |
| 2276 | | d[3] = d[2] = d[1] = d[0] = 255; |
| 2277 | | break; |
| 2278 | | case nv2a_renderer::SRC_COLOR: |
| 2279 | | d[3] = c[3]; |
| 2280 | | d[2] = c[2]; |
| 2281 | | d[1] = c[1]; |
| 2282 | | d[0] = c[0]; |
| 2283 | | break; |
| 2284 | | case nv2a_renderer::ONE_MINUS_SRC_COLOR: |
| 2285 | | d[3] = c[3] ^ 255; |
| 2286 | | d[2] = c[2] ^ 255; |
| 2287 | | d[1] = c[1] ^ 255; |
| 2288 | | d[0] = c[0] ^ 255; |
| 2289 | | break; |
| 2290 | | case nv2a_renderer::SRC_ALPHA: |
| 2291 | | d[3] = d[2] = d[1] = d[0] = c[3]; |
| 2292 | | break; |
| 2293 | | case nv2a_renderer::ONE_MINUS_SRC_ALPHA: |
| 2294 | | d[3] = d[2] = d[1] = d[0] = c[3] ^ 255; |
| 2295 | | break; |
| 2296 | | case nv2a_renderer::DST_ALPHA: |
| 2297 | | d[3] = d[2] = d[1] = d[0] = fb[3]; |
| 2298 | | break; |
| 2299 | | case nv2a_renderer::ONE_MINUS_DST_ALPHA: |
| 2300 | | d[3] = d[2] = d[1] = d[0] = fb[3] ^ 255; |
| 2301 | | break; |
| 2302 | | case nv2a_renderer::CONSTANT_COLOR: |
| 2303 | | d[3] = cc[3]; |
| 2304 | | d[2] = cc[2]; |
| 2305 | | d[1] = cc[1]; |
| 2306 | | d[0] = cc[0]; |
| 2307 | | break; |
| 2308 | | case nv2a_renderer::ONE_MINUS_CONSTANT_COLOR: |
| 2309 | | d[3] = cc[3] ^ 255; |
| 2310 | | d[2] = cc[2] ^ 255; |
| 2311 | | d[1] = cc[1] ^ 255; |
| 2312 | | d[0] = cc[0] ^ 255; |
| 2313 | | break; |
| 2314 | | case nv2a_renderer::CONSTANT_ALPHA: |
| 2315 | | d[3] = d[2] = d[1] = d[0] = cc[3]; |
| 2316 | | break; |
| 2317 | | case nv2a_renderer::ONE_MINUS_CONSTANT_ALPHA: |
| 2318 | | d[3] = d[2] = d[1] = d[0] = cc[3] ^ 255; |
| 2319 | | break; |
| 2320 | | } |
| 2321 | | switch (blend_equation) { |
| 2322 | | case nv2a_renderer::FUNC_ADD: |
| 2323 | | c[3] = (c[3]*s[3] + fb[3]*d[3]) / 255; |
| 2324 | | if (c[3] > 255) |
| 2325 | | c[3] = 255; |
| 2326 | | c[2] = (c[2]*s[2] + fb[2]*d[2]) / 255; |
| 2327 | | if (c[2] > 255) |
| 2328 | | c[2] = 255; |
| 2329 | | c[1] = (c[1]*s[1] + fb[1]*d[1]) / 255; |
| 2330 | | if (c[1] > 255) |
| 2331 | | c[1] = 255; |
| 2332 | | c[0] = (c[0]*s[0] + fb[0]*d[0]) / 255; |
| 2333 | | if (c[0] > 255) |
| 2334 | | c[0] = 255; |
| 2335 | | break; |
| 2336 | | case nv2a_renderer::FUNC_SUBTRACT: |
| 2337 | | c[3] = (c[3]*s[3] - fb[3]*d[3]) / 255; |
| 2338 | | if (c[3] < 0) |
| 2339 | | c[3] = 255; |
| 2340 | | c[2] = (c[2]*s[2] - fb[2]*d[2]) / 255; |
| 2341 | | if (c[2] < 0) |
| 2342 | | c[2] = 255; |
| 2343 | | c[1] = (c[1]*s[1] - fb[1]*d[1]) / 255; |
| 2344 | | if (c[1] < 0) |
| 2345 | | c[1] = 255; |
| 2346 | | c[0] = (c[0]*s[0] - fb[0]*d[0]) / 255; |
| 2347 | | if (c[0] < 0) |
| 2348 | | c[0] = 255; |
| 2349 | | break; |
| 2350 | | case nv2a_renderer::FUNC_REVERSE_SUBTRACT: |
| 2351 | | c[3] = (fb[3] * d[3] - c[3] * s[3]) / 255; |
| 2352 | | if (c[3] < 0) |
| 2353 | | c[3] = 255; |
| 2354 | | c[2] = (fb[2] * d[2] - c[2] * s[2]) / 255; |
| 2355 | | if (c[2] < 0) |
| 2356 | | c[2] = 255; |
| 2357 | | c[1] = (fb[1] * d[1] - c[1] * s[1]) / 255; |
| 2358 | | if (c[1] < 0) |
| 2359 | | c[1] = 255; |
| 2360 | | c[0] = (fb[0] * d[0] - c[0] * s[0]) / 255; |
| 2361 | | if (c[0] < 0) |
| 2362 | | c[0] = 255; |
| 2363 | | break; |
| 2364 | | case nv2a_renderer::MIN: |
| 2365 | | c[3] = s[3]; |
| 2366 | | if (d[3] < c[3]) |
| 2367 | | c[3] = d[3]; |
| 2368 | | c[2] = s[2]; |
| 2369 | | if (d[2] < c[2]) |
| 2370 | | c[2] = d[2]; |
| 2371 | | c[1] = s[1]; |
| 2372 | | if (d[1] < c[1]) |
| 2373 | | c[1] = d[1]; |
| 2374 | | c[0] = s[0]; |
| 2375 | | if (d[0] < c[0]) |
| 2376 | | c[0] = d[0]; |
| 2377 | | break; |
| 2378 | | case nv2a_renderer::MAX: |
| 2379 | | c[3] = s[3]; |
| 2380 | | if (d[3] > c[3]) |
| 2381 | | c[3] = d[3]; |
| 2382 | | c[2] = s[2]; |
| 2383 | | if (d[2] > c[2]) |
| 2384 | | c[2] = d[2]; |
| 2385 | | c[1] = s[1]; |
| 2386 | | if (d[1] > c[1]) |
| 2387 | | c[1] = d[1]; |
| 2388 | | c[0] = s[0]; |
| 2389 | | if (d[0] > c[0]) |
| 2390 | | c[0] = d[0]; |
| 2391 | | break; |
| 2392 | | } |
| 2393 | | } |
| 2394 | | // dithering not done |
| 2395 | | // logical operation |
| 2396 | | if (logical_operation_enabled) { |
| 2397 | | switch (logical_operation) { |
| 2398 | | case nv2a_renderer::CLEAR: |
| 2399 | | c[3] = 0; |
| 2400 | | c[2] = 0; |
| 2401 | | c[1] = 0; |
| 2402 | | c[0] = 0; |
| 2403 | | break; |
| 2404 | | case nv2a_renderer::AND: |
| 2405 | | c[3] = c[3] & fb[3]; |
| 2406 | | c[2] = c[2] & fb[2]; |
| 2407 | | c[1] = c[1] & fb[1]; |
| 2408 | | c[0] = c[0] & fb[0]; |
| 2409 | | break; |
| 2410 | | case nv2a_renderer::AND_REVERSE: |
| 2411 | | c[3] = c[3] & (fb[3] ^ 255); |
| 2412 | | c[2] = c[2] & (fb[2] ^ 255); |
| 2413 | | c[1] = c[1] & (fb[1] ^ 255); |
| 2414 | | c[0] = c[0] & (fb[0] ^ 255); |
| 2415 | | break; |
| 2416 | | case nv2a_renderer::COPY: |
| 2417 | | default: |
| 2418 | | break; |
| 2419 | | case nv2a_renderer::AND_INVERTED: |
| 2420 | | c[3] = (c[3] ^ 255) & fb[3]; |
| 2421 | | c[2] = (c[2] ^ 255) & fb[2]; |
| 2422 | | c[1] = (c[1] ^ 255) & fb[1]; |
| 2423 | | c[0] = (c[0] ^ 255) & fb[0]; |
| 2424 | | break; |
| 2425 | | case nv2a_renderer::NOOP: |
| 2426 | | c[3] = fb[3]; |
| 2427 | | c[2] = fb[2]; |
| 2428 | | c[1] = fb[1]; |
| 2429 | | c[0] = fb[0]; |
| 2430 | | break; |
| 2431 | | case nv2a_renderer::XOR: |
| 2432 | | c[3] = c[3] ^ fb[3]; |
| 2433 | | c[2] = c[2] ^ fb[2]; |
| 2434 | | c[1] = c[1] ^ fb[1]; |
| 2435 | | c[0] = c[0] ^ fb[0]; |
| 2436 | | break; |
| 2437 | | case nv2a_renderer::OR: |
| 2438 | | c[3] = c[3] | fb[3]; |
| 2439 | | c[2] = c[2] | fb[2]; |
| 2440 | | c[1] = c[1] | fb[1]; |
| 2441 | | c[0] = c[0] | fb[0]; |
| 2442 | | break; |
| 2443 | | case nv2a_renderer::NOR: |
| 2444 | | c[3] = (c[3] | fb[3]) ^ 255; |
| 2445 | | c[2] = (c[2] | fb[2]) ^ 255; |
| 2446 | | c[1] = (c[1] | fb[1]) ^ 255; |
| 2447 | | c[0] = (c[0] | fb[0]) ^ 255; |
| 2448 | | break; |
| 2449 | | case nv2a_renderer::EQUIV: |
| 2450 | | c[3] = (c[3] ^ fb[3]) ^ 255; |
| 2451 | | c[2] = (c[2] ^ fb[2]) ^ 255; |
| 2452 | | c[1] = (c[1] ^ fb[1]) ^ 255; |
| 2453 | | c[0] = (c[0] ^ fb[0]) ^ 255; |
| 2454 | | break; |
| 2455 | | case nv2a_renderer::INVERT: |
| 2456 | | c[3] = fb[3] ^ 255; |
| 2457 | | c[2] = fb[2] ^ 255; |
| 2458 | | c[1] = fb[1] ^ 255; |
| 2459 | | c[0] = fb[0] ^ 255; |
| 2460 | | break; |
| 2461 | | case nv2a_renderer::OR_REVERSE: |
| 2462 | | c[3] = c[3] | (fb[3] ^ 255); |
| 2463 | | c[2] = c[2] | (fb[2] ^ 255); |
| 2464 | | c[1] = c[1] | (fb[1] ^ 255); |
| 2465 | | c[0] = c[0] | (fb[0] ^ 255); |
| 2466 | | break; |
| 2467 | | case nv2a_renderer::COPY_INVERTED: |
| 2468 | | c[3] = c[3] ^ 255; |
| 2469 | | c[2] = c[2] ^ 255; |
| 2470 | | c[1] = c[1] ^ 255; |
| 2471 | | c[0] = c[0] ^ 255; |
| 2472 | | break; |
| 2473 | | case nv2a_renderer::OR_INVERTED: |
| 2474 | | c[3] = (c[3] ^ 255) | fb[3]; |
| 2475 | | c[2] = (c[2] ^ 255) | fb[2]; |
| 2476 | | c[1] = (c[1] ^ 255) | fb[1]; |
| 2477 | | c[0] = (c[0] ^ 255) | fb[0]; |
| 2478 | | break; |
| 2479 | | case nv2a_renderer::NAND: |
| 2480 | | c[3] = (c[3] & fb[3]) ^ 255; |
| 2481 | | c[2] = (c[2] & fb[2]) ^ 255; |
| 2482 | | c[1] = (c[1] & fb[1]) ^ 255; |
| 2483 | | c[0] = (c[0] & fb[0]) ^ 255; |
| 2484 | | break; |
| 2485 | | case nv2a_renderer::SET: |
| 2486 | | c[3] = 255; |
| 2487 | | c[2] = 255; |
| 2488 | | c[1] = 255; |
| 2489 | | c[0] = 255; |
| 2490 | | break; |
| 2491 | | } |
| 2492 | | } |
| 2493 | | fbcolor = (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0]; |
| 2494 | | *((UINT32 *)addr) = fbcolor; |
| 2495 | | } |
| 2496 | | |
| 2497 | | void nv2a_renderer::render_color(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid) |
| 2498 | | { |
| 2499 | | int x; |
| 2500 | | |
| 2501 | | x=extent.stopx-extent.startx-1; // number of pixels to draw |
| 2502 | | while (x >= 0) { |
| 2503 | | UINT32 a8r8g8b8; |
| 2504 | | int ca,cr,cg,cb; |
| 2505 | | int xp=extent.startx+x; // x coordinate of current pixel |
| 2506 | | |
| 2507 | | cb=(extent.param[0].start+(float)x*extent.param[0].dpdx); |
| 2508 | | cg=(extent.param[1].start+(float)x*extent.param[1].dpdx); |
| 2509 | | cr=(extent.param[2].start+(float)x*extent.param[2].dpdx); |
| 2510 | | ca=(extent.param[3].start+(float)x*extent.param[3].dpdx); |
| 2511 | | a8r8g8b8=(ca << 24)+(cr << 16)+(cg << 8)+cb; // pixel color obtained by interpolating the colors of the vertices |
| 2512 | | write_pixel(xp, scanline, a8r8g8b8); |
| 2513 | | x--; |
| 2514 | | } |
| 2515 | | } |
| 2516 | | |
| 2517 | | void nv2a_renderer::render_texture_simple(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid) |
| 2518 | | { |
| 2519 | | int x; |
| 2520 | | UINT32 a8r8g8b8; |
| 2521 | | |
| 2522 | | if (!objectdata.data->texture[0].enabled) { |
| 2523 | | return; |
| 2524 | | } |
| 2525 | | x=extent.stopx-extent.startx-1; |
| 2526 | | while (x >= 0) { |
| 2527 | | int up,vp; |
| 2528 | | int xp=extent.startx+x; // x coordinate of current pixel |
| 2529 | | |
| 2530 | | up=(extent.param[4].start+(float)x*extent.param[4].dpdx)*(float)(objectdata.data->texture[0].sizeu-1); // x coordinate of texel in texture |
| 2531 | | vp=extent.param[5].start*(float)(objectdata.data->texture[0].sizev-1); // y coordinate of texel in texture |
| 2532 | | a8r8g8b8=texture_get_texel(0, up, vp); |
| 2533 | | write_pixel(xp, scanline, a8r8g8b8); |
| 2534 | | x--; |
| 2535 | | } |
| 2536 | | } |
| 2537 | | |
| 2538 | | void nv2a_renderer::render_register_combiners(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid) |
| 2539 | | { |
| 2540 | | int x,xp; |
| 2541 | | int up,vp; |
| 2542 | | int ca,cr,cg,cb; |
| 2543 | | UINT32 color[6]; |
| 2544 | | UINT32 a8r8g8b8; |
| 2545 | | int n;//,m,i,j,k; |
| 2546 | | |
| 2547 | | color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0; |
| 2548 | | |
| 2549 | | osd_lock_acquire(combiner.lock); // needed since multithreading is not supported yet |
| 2550 | | x=extent.stopx-extent.startx-1; // number of pixels to draw |
| 2551 | | while (x >= 0) { |
| 2552 | | xp=extent.startx+x; |
| 2553 | | // 1: fetch data |
| 2554 | | // 1.1: interpolated color from vertices |
| 2555 | | cb=(extent.param[0].start+(float)x*extent.param[0].dpdx); |
| 2556 | | cg=(extent.param[1].start+(float)x*extent.param[1].dpdx); |
| 2557 | | cr=(extent.param[2].start+(float)x*extent.param[2].dpdx); |
| 2558 | | ca=(extent.param[3].start+(float)x*extent.param[3].dpdx); |
| 2559 | | color[0]=(ca << 24)+(cr << 16)+(cg << 8)+cb; // pixel color obtained by interpolating the colors of the vertices |
| 2560 | | color[1]=0; // lighting not yet |
| 2561 | | // 1.2: color for each of the 4 possible textures |
| 2562 | | for (n=0;n < 4;n++) { |
| 2563 | | if (texture[n].enabled) { |
| 2564 | | up=(extent.param[4+n*2].start+(float)x*extent.param[4+n*2].dpdx)*(float)(objectdata.data->texture[n].sizeu-1); |
| 2565 | | vp=extent.param[5+n*2].start*(float)(objectdata.data->texture[n].sizev-1); |
| 2566 | | color[n+2]=texture_get_texel(n, up, vp); |
| 2567 | | } |
| 2568 | | } |
| 2569 | | // 2: compute |
| 2570 | | // 2.1: initialize |
| 2571 | | combiner_initialize_registers(color); |
| 2572 | | // 2.2: general cmbiner stages |
| 2573 | | for (n=0;n < combiner.stages;n++) { |
| 2574 | | // 2.2.1 initialize |
| 2575 | | combiner_initialize_stage(n); |
| 2576 | | // 2.2.2 map inputs |
| 2577 | | combiner_map_input(n); |
| 2578 | | // 2.2.3 compute possible outputs |
| 2579 | | combiner_compute_rgb_outputs(n); |
| 2580 | | combiner_compute_a_outputs(n); |
| 2581 | | // 2.2.4 map outputs to registers |
| 2582 | | combiner_map_output(n); |
| 2583 | | } |
| 2584 | | // 2.3: final cmbiner stage |
| 2585 | | combiner_initialize_final(); |
| 2586 | | combiner_map_final_input(); |
| 2587 | | combiner_final_output(); |
| 2588 | | a8r8g8b8=combiner_float_argb8(combiner.output); |
| 2589 | | // 3: write pixel |
| 2590 | | write_pixel(xp, scanline, a8r8g8b8); |
| 2591 | | x--; |
| 2592 | | } |
| 2593 | | osd_lock_release(combiner.lock); |
| 2594 | | } |
| 2595 | | |
| 2596 | | #if 0 |
| 2597 | | const char *rc_mapping_str[]={ |
| 2598 | | "UNSIGNED_IDENTITY", |
| 2599 | | "UNSIGNED_INVERT", |
| 2600 | | "EXPAND_NORMAL", |
| 2601 | | "EXPAND_NEGATE", |
| 2602 | | "HALF_BIAS_NORMAL", |
| 2603 | | "HALF_BIAS_NEGATE", |
| 2604 | | "SIGNED_IDENTITY", |
| 2605 | | "SIGNED_NEGATE" |
| 2606 | | }; |
| 2607 | | |
| 2608 | | const char *rc_usage_rgb_str[]={ |
| 2609 | | "RGB", |
| 2610 | | "ALPHA" |
| 2611 | | }; |
| 2612 | | |
| 2613 | | const char *rc_usage_alpha_str[]={ |
| 2614 | | "BLUE", |
| 2615 | | "ALPHA" |
| 2616 | | }; |
| 2617 | | |
| 2618 | | const char *rc_variable_str[]={ |
| 2619 | | "ZERO", |
| 2620 | | "CONSTANT_COLOR0", |
| 2621 | | "CONSTANT_COLOR1", |
| 2622 | | "FOG", |
| 2623 | | "PRIMARY_COLOR", |
| 2624 | | "SECONDARY_COLOR", |
| 2625 | | "???", |
| 2626 | | "???", |
| 2627 | | "TEXTURE0", |
| 2628 | | "TEXTURE1", |
| 2629 | | "TEXTURE2", |
| 2630 | | "TEXTURE3", |
| 2631 | | "SPARE0", |
| 2632 | | "SPARE1", |
| 2633 | | "SPARE0_PLUS_SECONDARY_COLOR", |
| 2634 | | "E_TIMES_F" |
| 2635 | | }; |
| 2636 | | |
| 2637 | | const char *rc_bias_str[]={ |
| 2638 | | "NONE", |
| 2639 | | "BIAS_BY_NEGATIVE_ONE_HALF" |
| 2640 | | }; |
| 2641 | | |
| 2642 | | const char *rc_scale_str[]={ |
| 2643 | | "NONE", |
| 2644 | | "SCALE_BY_TWO", |
| 2645 | | "SCALE_BY_FOUR", |
| 2646 | | "SCALE_BY_ONE_HALF" |
| 2647 | | }; |
| 2648 | | |
| 2649 | | /* Dump the current setup of the register combiners */ |
| 2650 | | void dumpcombiners(UINT32 *m) |
| 2651 | | { |
| 2652 | | int a,b,n,v; |
| 2653 | | |
| 2654 | | n=m[0x1e60/4] & 0xf; |
| 2655 | | printf("Combiners active: %d\n\r",n); |
| 2656 | | for (a=0;a < n;a++) { |
| 2657 | | printf("Combiner %d\n\r",a+1); |
| 2658 | | printf(" RC_IN_ALPHA %08X\n\r",m[0x0260/4+a]); |
| 2659 | | for (b=24;b >= 0;b=b-8) { |
| 2660 | | v=(m[0x0260/4+a] >> b) & 0xf; |
| 2661 | | printf(" %c_INPUT %s\n\r",'A'+3-b/8,rc_variable_str[v]); |
| 2662 | | v=(m[0x0260/4+a] >> (b+4)) & 1; |
| 2663 | | printf(" %c_COMPONENT_USAGE %s\n\r",'A'+3-b/8,rc_usage_alpha_str[v]); |
| 2664 | | v=(m[0x0260/4+a] >> (b+5)) & 7; |
| 2665 | | printf(" %c_MAPPING %s\n\r",'A'+3-b/8,rc_mapping_str[v]); |
| 2666 | | } |
| 2667 | | printf(" RC_IN_RGB %08X\n\r",m[0x0ac0/4+a]); |
| 2668 | | for (b=24;b >= 0;b=b-8) { |
| 2669 | | v=(m[0x0ac0/4+a] >> b) & 0xf; |
| 2670 | | printf(" %c_INPUT %s\n\r",'A'+3-b/8,rc_variable_str[v]); |
| 2671 | | v=(m[0x0ac0/4+a] >> (b+4)) & 1; |
| 2672 | | printf(" %c_COMPONENT_USAGE %s\n\r",'A'+3-b/8,rc_usage_rgb_str[v]); |
| 2673 | | v=(m[0x0ac0/4+a] >> (b+5)) & 7; |
| 2674 | | printf(" %c_MAPPING %s\n\r",'A'+3-b/8,rc_mapping_str[v]); |
| 2675 | | } |
| 2676 | | printf(" RC_OUT_ALPHA %08X\n\r",m[0x0aa0/4+a]); |
| 2677 | | v=m[0x0aa0/4+a] & 0xf; |
| 2678 | | printf(" CD_OUTPUT %s\n\r",rc_variable_str[v]); |
| 2679 | | v=(m[0x0aa0/4+a] >> 4) & 0xf; |
| 2680 | | printf(" AB_OUTPUT %s\n\r",rc_variable_str[v]); |
| 2681 | | v=(m[0x0aa0/4+a] >> 8) & 0xf; |
| 2682 | | printf(" SUM_OUTPUT %s\n\r",rc_variable_str[v]); |
| 2683 | | v=(m[0x0aa0/4+a] >> 12) & 1; |
| 2684 | | printf(" CD_DOT_PRODUCT %d\n\r",v); |
| 2685 | | v=(m[0x0aa0/4+a] >> 13) & 1; |
| 2686 | | printf(" AB_DOT_PRODUCT %d\n\r",v); |
| 2687 | | v=(m[0x0aa0/4+a] >> 14) & 1; |
| 2688 | | printf(" MUX_SUM %d\n\r",v); |
| 2689 | | v=(m[0x0aa0/4+a] >> 15) & 1; |
| 2690 | | printf(" BIAS %s\n\r",rc_bias_str[v]); |
| 2691 | | v=(m[0x0aa0/4+a] >> 16) & 3; |
| 2692 | | printf(" SCALE %s\n\r",rc_scale_str[v]); |
| 2693 | | //v=(m[0x0aa0/4+a] >> 27) & 7; |
| 2694 | | printf(" RC_OUT_RGB %08X\n\r",m[0x1e40/4+a]); |
| 2695 | | v=m[0x1e40/4+a] & 0xf; |
| 2696 | | printf(" CD_OUTPUT %s\n\r",rc_variable_str[v]); |
| 2697 | | v=(m[0x1e40/4+a] >> 4) & 0xf; |
| 2698 | | printf(" AB_OUTPUT %s\n\r",rc_variable_str[v]); |
| 2699 | | v=(m[0x1e40/4+a] >> 8) & 0xf; |
| 2700 | | printf(" SUM_OUTPUT %s\n\r",rc_variable_str[v]); |
| 2701 | | v=(m[0x1e40/4+a] >> 12) & 1; |
| 2702 | | printf(" CD_DOT_PRODUCT %d\n\r",v); |
| 2703 | | v=(m[0x1e40/4+a] >> 13) & 1; |
| 2704 | | printf(" AB_DOT_PRODUCT %d\n\r",v); |
| 2705 | | v=(m[0x1e40/4+a] >> 14) & 1; |
| 2706 | | printf(" MUX_SUM %d\n\r",v); |
| 2707 | | v=(m[0x1e40/4+a] >> 15) & 1; |
| 2708 | | printf(" BIAS %s\n\r",rc_bias_str[v]); |
| 2709 | | v=(m[0x1e40/4+a] >> 16) & 3; |
| 2710 | | printf(" SCALE %s\n\r",rc_scale_str[v]); |
| 2711 | | //v=(m[0x1e40/4+a] >> 27) & 7; |
| 2712 | | printf("\n\r"); |
| 2713 | | } |
| 2714 | | printf("Combiner final %08X %08X\n\r",m[0x0288/4],m[0x028c/4]); |
| 2715 | | for (a=24;a >= 0;a=a-8) { |
| 2716 | | n=(m[0x0288/4] >> a) & 0xf; |
| 2717 | | printf(" %c_INPUT %s\n\r",'A'+3-a/8,rc_variable_str[n]); |
| 2718 | | n=(m[0x0288/4] >> (a+4)) & 1; |
| 2719 | | printf(" %c_COMPONENT_USAGE %s\n\r",'A'+3-a/8,rc_usage_rgb_str[n]); |
| 2720 | | n=(m[0x0288/4] >> (a+5)) & 7; |
| 2721 | | printf(" %c_MAPPING %s\n\r",'A'+3-a/8,rc_mapping_str[n]); |
| 2722 | | } |
| 2723 | | for (a=24;a >= 8;a=a-8) { |
| 2724 | | n=(m[0x028c/4] >> a) & 0xf; |
| 2725 | | printf(" %c_INPUT %s\n\r",'E'+3-a/8,rc_variable_str[n]); |
| 2726 | | n=(m[0x028c/4] >> (a+4)) & 1; |
| 2727 | | printf(" %c_COMPONENT_USAGE %s\n\r",'E'+3-a/8,rc_usage_rgb_str[n]); |
| 2728 | | n=(m[0x028c/4] >> (a+5)) & 7; |
| 2729 | | printf(" %c_MAPPING %s\n\r",'E'+3-a/8,rc_mapping_str[n]); |
| 2730 | | } |
| 2731 | | n=(m[0x028c/4] >> 7) & 1; |
| 2732 | | printf(" color sum clamp: %d\n\r",n); |
| 2733 | | } |
| 2734 | | #endif |
| 2735 | | |
| 2736 | | /* Read vertices data from system memory. Method 0x1810 */ |
| 2737 | | int nv2a_renderer::read_vertices_0x1810(address_space & space, vertex *destination, int offset, int limit) |
| 2738 | | { |
| 2739 | | UINT32 m, u; |
| 2740 | | |
| 2741 | | for (m = 0; m < limit; m++) { |
| 2742 | | destination[m].attribute[0].iv[0] = space.read_dword(vertexbuffer_address[0] + (m + offset)*vertexbuffer_stride[0] + 0); |
| 2743 | | destination[m].attribute[0].iv[1] = space.read_dword(vertexbuffer_address[0] + (m + offset)*vertexbuffer_stride[0] + 4); |
| 2744 | | destination[m].attribute[0].iv[2] = space.read_dword(vertexbuffer_address[0] + (m + offset)*vertexbuffer_stride[0] + 8); |
| 2745 | | destination[m].attribute[0].iv[3] = space.read_dword(vertexbuffer_address[0] + (m + offset)*vertexbuffer_stride[0] + 12); |
| 2746 | | destination[m].attribute[3].iv[0] = space.read_dword(vertexbuffer_address[3] + (m + offset)*vertexbuffer_stride[3] + 0); // color |
| 2747 | | for (u = 0; u < 4; u++) { |
| 2748 | | destination[m].attribute[9 + u].iv[0] = space.read_dword(vertexbuffer_address[9 + u] + (m + offset)*vertexbuffer_stride[9 + u] + 0); |
| 2749 | | destination[m].attribute[9 + u].iv[1] = space.read_dword(vertexbuffer_address[9 + u] + (m + offset)*vertexbuffer_stride[9 + u] + 4); |
| 2750 | | } |
| 2751 | | } |
| 2752 | | return m; |
| 2753 | | } |
| 2754 | | |
| 2755 | | /* Read vertices data from system memory. Method 0x1800 */ |
| 2756 | | int nv2a_renderer::read_vertices_0x1800(address_space & space, vertex *destination, UINT32 address, int limit) |
| 2757 | | { |
| 2758 | | UINT32 data; |
| 2759 | | UINT32 m, u, i, c; |
| 2760 | | |
| 2761 | | c = 0; |
| 2762 | | for (m = 0; m < limit; m++) { |
| 2763 | | if (indexesleft_count == 0) { |
| 2764 | | data = space.read_dword(address); |
| 2765 | | i = (indexesleft_first + indexesleft_count) & 7; |
| 2766 | | indexesleft[i] = data & 0xffff; |
| 2767 | | indexesleft[(i + 1) & 7] = (data >> 16) & 0xffff; |
| 2768 | | indexesleft_count = indexesleft_count + 2; |
| 2769 | | address += 4; |
| 2770 | | c++; |
| 2771 | | } |
| 2772 | | destination[m].attribute[0].iv[0] = space.read_dword(vertexbuffer_address[0] + indexesleft[indexesleft_first] * vertexbuffer_stride[0] + 0); |
| 2773 | | destination[m].attribute[0].iv[1] = space.read_dword(vertexbuffer_address[0] + indexesleft[indexesleft_first] * vertexbuffer_stride[0] + 4); |
| 2774 | | destination[m].attribute[0].iv[2] = space.read_dword(vertexbuffer_address[0] + indexesleft[indexesleft_first] * vertexbuffer_stride[0] + 8); |
| 2775 | | destination[m].attribute[0].iv[3] = space.read_dword(vertexbuffer_address[0] + indexesleft[indexesleft_first] * vertexbuffer_stride[0] + 12); |
| 2776 | | destination[m].attribute[3].iv[0] = space.read_dword(vertexbuffer_address[3] + indexesleft[indexesleft_first] * vertexbuffer_stride[3] + 0); // color |
| 2777 | | for (u = 0; u < 4; u++) { |
| 2778 | | destination[m].attribute[9 + u].iv[0] = space.read_dword(vertexbuffer_address[9 + u] + indexesleft[indexesleft_first] * vertexbuffer_stride[9 + u] + 0); |
| 2779 | | destination[m].attribute[9 + u].iv[1] = space.read_dword(vertexbuffer_address[9 + u] + indexesleft[indexesleft_first] * vertexbuffer_stride[9 + u] + 4); |
| 2780 | | } |
| 2781 | | indexesleft_first = (indexesleft_first + 1) & 7; |
| 2782 | | indexesleft_count--; |
| 2783 | | } |
| 2784 | | return (int)c; |
| 2785 | | } |
| 2786 | | |
| 2787 | | /* Read vertices data from system memory. Method 0x1818 */ |
| 2788 | | int nv2a_renderer::read_vertices_0x1818(address_space & space, vertex *destination, UINT32 address, int limit) |
| 2789 | | { |
| 2790 | | UINT32 m, u, vwords; |
| 2791 | | |
| 2792 | | vwords = vertex_attribute_words[15] + vertex_attribute_offset[15]; |
| 2793 | | for (m = 0; m < limit; m++) { |
| 2794 | | destination[m].attribute[0].iv[0] = space.read_dword(address + vertex_attribute_offset[0] * 4 + 0); |
| 2795 | | destination[m].attribute[0].iv[1] = space.read_dword(address + vertex_attribute_offset[0] * 4 + 4); |
| 2796 | | destination[m].attribute[0].iv[2] = space.read_dword(address + vertex_attribute_offset[0] * 4 + 8); |
| 2797 | | destination[m].attribute[0].iv[3] = space.read_dword(address + vertex_attribute_offset[0] * 4 + 12); |
| 2798 | | destination[m].attribute[3].iv[0] = space.read_dword(address + vertex_attribute_offset[3] * 4 + 0); // color |
| 2799 | | for (u = 0; u < 4; u++) { |
| 2800 | | destination[m].attribute[9 + u].iv[0] = space.read_dword(address + vertex_attribute_offset[9 + u] * 4 + 0); |
| 2801 | | destination[m].attribute[9 + u].iv[1] = space.read_dword(address + vertex_attribute_offset[9 + u] * 4 + 4); |
| 2802 | | } |
| 2803 | | address = address + vwords * 4; |
| 2804 | | } |
| 2805 | | return (int)(m*vwords); |
| 2806 | | } |
| 2807 | | |
| 2808 | | void nv2a_renderer::convert_vertices_poly(vertex *source, vertex_t *destination, int count) |
| 2809 | | { |
| 2810 | | int m, u; |
| 2811 | | |
| 2812 | | for (m = 0; m < count; m++) { |
| 2813 | | destination[m].x = source[m].attribute[0].fv[0]; |
| 2814 | | destination[m].y = source[m].attribute[0].fv[1]; |
| 2815 | | u = source[m].attribute[3].iv[0]; |
| 2816 | | destination[m].p[0] = u & 0xff; // b |
| 2817 | | destination[m].p[1] = (u & 0xff00) >> 8; // g |
| 2818 | | destination[m].p[2] = (u & 0xff0000) >> 16; // r |
| 2819 | | destination[m].p[3] = (u & 0xff000000) >> 24; // a |
| 2820 | | for (u = 0; u < 4; u++) { |
| 2821 | | destination[m].p[4 + u * 2] = 0; |
| 2822 | | destination[m].p[5 + u * 2] = 0; |
| 2823 | | if (texture[u].enabled) { |
| 2824 | | destination[m].p[4 + u * 2] = source[m].attribute[9 + u].fv[0]; |
| 2825 | | destination[m].p[5 + u * 2] = source[m].attribute[9 + u].fv[1]; |
| 2826 | | } |
| 2827 | | } |
| 2828 | | } |
| 2829 | | } |
| 2830 | | |
| 2831 | | void nv2a_renderer::geforce_exec_method(address_space & space,UINT32 chanel,UINT32 subchannel,UINT32 method,UINT32 address,int &countlen) |
| 2832 | | { |
| 2833 | | UINT32 maddress; |
| 2834 | | UINT32 data; |
| 2835 | | |
| 2836 | | maddress=method*4; |
| 2837 | | data=space.read_dword(address); |
| 2838 | | channel[chanel][subchannel].object.method[method]=data; |
| 2839 | | if (maddress == 0x17fc) { |
| 2840 | | indexesleft_count = 0; |
| 2841 | | indexesleft_first = 0; |
| 2842 | | primitives_count = 0; |
| 2843 | | countlen--; |
| 2844 | | } |
| 2845 | | if (maddress == 0x1810) { |
| 2846 | | // draw vertices |
| 2847 | | int offset,count,type; |
| 2848 | | UINT32 n; |
| 2849 | | render_delegate renderspans; |
| 2850 | | |
| 2851 | | offset=data & 0xffffff; |
| 2852 | | count=(data >> 24) & 0xff; |
| 2853 | | type=channel[chanel][subchannel].object.method[0x17fc/4]; |
| 2854 | | if (((channel[chanel][subchannel].object.method[0x1e60/4] & 7) > 0) && (combiner.used != 0)) { |
| 2855 | | renderspans=render_delegate(FUNC(nv2a_renderer::render_register_combiners),this); |
| 2856 | | } else if (texture[0].enabled) { |
| 2857 | | renderspans=render_delegate(FUNC(nv2a_renderer::render_texture_simple),this); |
| 2858 | | } else |
| 2859 | | renderspans=render_delegate(FUNC(nv2a_renderer::render_color),this); |
| 2860 | | #ifdef LOG_NV2A |
| 2861 | | printf("vertex %d %d %d\n\r",type,offset,count); |
| 2862 | | #endif |
| 2863 | | if (type == nv2a_renderer::QUADS) { |
| 2864 | | for (n = 0; n <= count; n += 4) { |
| 2865 | | vertex vert[4]; |
| 2866 | | vertex_t xy[4]; |
| 2867 | | |
| 2868 | | read_vertices_0x1810(space, vert, n+offset, 4); |
| 2869 | | convert_vertices_poly(vert, xy, 4); |
| 2870 | | render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv |
| 2871 | | } |
| 2872 | | wait(); |
| 2873 | | } else if (type == nv2a_renderer::TRIANGLE_STRIP) { |
| 2874 | | vertex vert[4]; |
| 2875 | | vertex_t xy[4]; |
| 2876 | | |
| 2877 | | read_vertices_0x1810(space, vert, offset, 2); |
| 2878 | | convert_vertices_poly(vert, xy, 2); |
| 2879 | | count = count - 2; |
| 2880 | | offset = offset + 2; |
| 2881 | | for (n = 0; n <= count; n++) { |
| 2882 | | read_vertices_0x1810(space, vert + ((n+2) & 3), offset + n, 1); |
| 2883 | | convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1); |
| 2884 | | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1)+n) & 3], xy[((~n & 1)+n) & 3], xy[(2+n) & 3]); |
| 2885 | | } |
| 2886 | | wait(); |
| 2887 | | } else { |
| 2888 | | logerror("Unsupported primitive %d for method 0x1810\n",type); |
| 2889 | | } |
| 2890 | | countlen--; |
| 2891 | | } |
| 2892 | | if (maddress == 0x1800) { |
| 2893 | | UINT32 type, n; |
| 2894 | | render_delegate renderspans; |
| 2895 | | |
| 2896 | | // vertices are selected from the vertex buffer using an array of indexes |
| 2897 | | // each dword after 1800 contains two 16 bit index values to select the vartices |
| 2898 | | type = channel[chanel][subchannel].object.method[0x17fc / 4]; |
| 2899 | | if (((channel[chanel][subchannel].object.method[0x1e60 / 4] & 7) > 0) && (combiner.used != 0)) { |
| 2900 | | renderspans = render_delegate(FUNC(nv2a_renderer::render_register_combiners), this); |
| 2901 | | } |
| 2902 | | else if (texture[0].enabled) { |
| 2903 | | renderspans = render_delegate(FUNC(nv2a_renderer::render_texture_simple), this); |
| 2904 | | } |
| 2905 | | else |
| 2906 | | renderspans = render_delegate(FUNC(nv2a_renderer::render_color), this); |
| 2907 | | #ifdef LOG_NV2A |
| 2908 | | printf("vertex %d %d %d\n\r", type, offset, count); |
| 2909 | | #endif |
| 2910 | | if (type == nv2a_renderer::QUADS) { |
| 2911 | | while (1) { |
| 2912 | | vertex vert[4]; |
| 2913 | | vertex_t xy[4]; |
| 2914 | | int c; |
| 2915 | | |
| 2916 | | if ((countlen * 2 + indexesleft_count) < 4) |
| 2917 | | break; |
| 2918 | | c=read_vertices_0x1800(space, vert, address, 4); |
| 2919 | | address = address + c*4; |
| 2920 | | countlen = countlen - c; |
| 2921 | | convert_vertices_poly(vert, xy, 4); |
| 2922 | | render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv |
| 2923 | | } |
| 2924 | | while (countlen > 0) { |
| 2925 | | data = space.read_dword(address); |
| 2926 | | n = (indexesleft_first + indexesleft_count) & 7; |
| 2927 | | indexesleft[n] = data & 0xffff; |
| 2928 | | indexesleft[(n + 1) & 7] = (data >> 16) & 0xffff; |
| 2929 | | indexesleft_count = indexesleft_count + 2; |
| 2930 | | address += 4; |
| 2931 | | countlen--; |
| 2932 | | } |
| 2933 | | wait(); |
| 2934 | | } |
| 2935 | | else if (type == nv2a_renderer::TRIANGLES) { |
| 2936 | | while (1) { |
| 2937 | | vertex vert[3]; |
| 2938 | | vertex_t xy[3]; |
| 2939 | | int c; |
| 2940 | | |
| 2941 | | if ((countlen * 2 + indexesleft_count) < 3) |
| 2942 | | break; |
| 2943 | | c = read_vertices_0x1800(space, vert, address, 3); |
| 2944 | | address = address + c * 4; |
| 2945 | | countlen = countlen - c; |
| 2946 | | convert_vertices_poly(vert, xy, 3); |
| 2947 | | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[0], xy[1], xy[2]); // 4 rgba, 4 texture units 2 uv |
| 2948 | | } |
| 2949 | | while (countlen > 0) { |
| 2950 | | data = space.read_dword(address); |
| 2951 | | n = (indexesleft_first + indexesleft_count) & 7; |
| 2952 | | indexesleft[n] = data & 0xffff; |
| 2953 | | indexesleft[(n + 1) & 7] = (data >> 16) & 0xffff; |
| 2954 | | indexesleft_count = indexesleft_count + 2; |
| 2955 | | address += 4; |
| 2956 | | countlen--; |
| 2957 | | } |
| 2958 | | wait(); |
| 2959 | | } |
| 2960 | | else if (type == nv2a_renderer::TRIANGLE_STRIP) { |
| 2961 | | if ((countlen * 2 + indexesleft_count) >= 3) { |
| 2962 | | vertex vert[4]; |
| 2963 | | vertex_t xy[4]; |
| 2964 | | int c, count; |
| 2965 | | |
| 2966 | | c = read_vertices_0x1800(space, vert, address, 2); |
| 2967 | | convert_vertices_poly(vert, xy, 2); |
| 2968 | | address = address + c * 4; |
| 2969 | | countlen = countlen - c; |
| 2970 | | count = countlen * 2 + indexesleft_count; |
| 2971 | | for (n = 0; n < count; n++) { // <= |
| 2972 | | c = read_vertices_0x1800(space, vert + ((n + 2) & 3), address, 1); |
| 2973 | | address = address + c * 4; |
| 2974 | | countlen = countlen - c; |
| 2975 | | convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1); |
| 2976 | | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]); |
| 2977 | | } |
| 2978 | | } |
| 2979 | | while (countlen > 0) { |
| 2980 | | data = space.read_dword(address); |
| 2981 | | n = (indexesleft_first + indexesleft_count) & 7; |
| 2982 | | indexesleft[n] = data & 0xffff; |
| 2983 | | indexesleft[(n + 1) & 7] = (data >> 16) & 0xffff; |
| 2984 | | indexesleft_count = indexesleft_count + 2; |
| 2985 | | address += 4; |
| 2986 | | countlen--; |
| 2987 | | } |
| 2988 | | wait(); |
| 2989 | | } |
| 2990 | | else { |
| 2991 | | logerror("Unsupported primitive %d for method 0x1800\n", type); |
| 2992 | | countlen = 0; |
| 2993 | | } |
| 2994 | | } |
| 2995 | | if (maddress == 0x1818) { |
| 2996 | | int n; |
| 2997 | | int type; |
| 2998 | | render_delegate renderspans; |
| 2999 | | |
| 3000 | | if (((channel[chanel][subchannel].object.method[0x1e60/4] & 7) > 0) && (combiner.used != 0)) { |
| 3001 | | renderspans=render_delegate(FUNC(nv2a_renderer::render_register_combiners),this); |
| 3002 | | } else if (texture[0].enabled) { |
| 3003 | | renderspans=render_delegate(FUNC(nv2a_renderer::render_texture_simple),this); |
| 3004 | | } else |
| 3005 | | renderspans=render_delegate(FUNC(nv2a_renderer::render_color),this); |
| 3006 | | // vertices are taken from the next words, not from a vertex buffer |
| 3007 | | // first send primitive type with 17fc |
| 3008 | | // then countlen number of dwords with 1818 |
| 3009 | | // end with 17fc primitive type 0 |
| 3010 | | // at 1760 16 words specify the vertex format:for each possible vertex attribute the number of components (0=not present) and type of each |
| 3011 | | type=channel[chanel][subchannel].object.method[0x17fc/4]; |
| 3012 | | if (type == nv2a_renderer::TRIANGLE_FAN) { |
| 3013 | | vertex vert[3]; |
| 3014 | | vertex_t xy[3]; |
| 3015 | | int c; |
| 3016 | | |
| 3017 | | c=read_vertices_0x1818(space, vert, address, 2); |
| 3018 | | convert_vertices_poly(vert, xy, 2); |
| 3019 | | countlen = countlen - c; |
| 3020 | | if (countlen < 0) { |
| 3021 | | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 3022 | | countlen = 0; |
| 3023 | | return; |
| 3024 | | } |
| 3025 | | address = address + c * 4; |
| 3026 | | for (n = 1; countlen > 0; n++) { |
| 3027 | | c=read_vertices_0x1818(space, vert + ((n & 1) + 1), address, 1); |
| 3028 | | countlen = countlen - c; |
| 3029 | | if (countlen < 0) { |
| 3030 | | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 3031 | | countlen = 0; |
| 3032 | | break; |
| 3033 | | } |
| 3034 | | address = address + c * 4; |
| 3035 | | convert_vertices_poly(vert + ((n & 1) + 1), xy + ((n & 1) + 1), 1); |
| 3036 | | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[0], xy[(~n & 1) + 1], xy[(n & 1) + 1]); |
| 3037 | | } |
| 3038 | | wait(); |
| 3039 | | } else if (type == nv2a_renderer::TRIANGLE_STRIP) { |
| 3040 | | vertex vert[4]; |
| 3041 | | vertex_t xy[4]; |
| 3042 | | int c; |
| 3043 | | |
| 3044 | | c=read_vertices_0x1818(space, vert, address, 2); |
| 3045 | | convert_vertices_poly(vert, xy, 2); |
| 3046 | | countlen = countlen - c; |
| 3047 | | if (countlen < 0) { |
| 3048 | | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 3049 | | countlen = 0; |
| 3050 | | return; |
| 3051 | | } |
| 3052 | | address = address + c * 4; |
| 3053 | | for (n = 0;countlen > 0; n++) { |
| 3054 | | c=read_vertices_0x1818(space, vert + ((n + 2) & 3), address, 1); |
| 3055 | | convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1); |
| 3056 | | countlen = countlen - c; |
| 3057 | | if (countlen < 0) { |
| 3058 | | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 3059 | | countlen = 0; |
| 3060 | | break; |
| 3061 | | } |
| 3062 | | address = address + c * 4; |
| 3063 | | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]); |
| 3064 | | } |
| 3065 | | wait(); |
| 3066 | | } else if (type == nv2a_renderer::QUADS) { |
| 3067 | | while (countlen > 0) { |
| 3068 | | vertex vert[4]; |
| 3069 | | vertex_t xy[4]; |
| 3070 | | int c; |
| 3071 | | |
| 3072 | | c = read_vertices_0x1818(space, vert, address, 4); |
| 3073 | | convert_vertices_poly(vert, xy, 4); |
| 3074 | | countlen = countlen - c; |
| 3075 | | if (countlen < 0) { |
| 3076 | | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 3077 | | countlen = 0; |
| 3078 | | break; |
| 3079 | | } |
| 3080 | | address = address + c * 4; |
| 3081 | | render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv |
| 3082 | | } |
| 3083 | | wait(); |
| 3084 | | } else if (type == nv2a_renderer::QUAD_STRIP) { |
| 3085 | | vertex vert[4]; |
| 3086 | | vertex_t xy[4]; |
| 3087 | | int c; |
| 3088 | | |
| 3089 | | c=read_vertices_0x1818(space, vert, address, 2); |
| 3090 | | convert_vertices_poly(vert, xy, 2); |
| 3091 | | countlen = countlen - c; |
| 3092 | | if (countlen < 0) { |
| 3093 | | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 3094 | | countlen = 0; |
| 3095 | | return; |
| 3096 | | } |
| 3097 | | address = address + c * 4; |
| 3098 | | for (n = 0; countlen > 0; n+=2) { |
| 3099 | | c = read_vertices_0x1818(space, vert + ((n + 2) & 3), address + ((n + 2) & 3), 2); |
| 3100 | | convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 2); |
| 3101 | | countlen = countlen - c; |
| 3102 | | if (countlen < 0) { |
| 3103 | | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 3104 | | countlen = 0; |
| 3105 | | return; |
| 3106 | | } |
| 3107 | | address = address + c * 4; |
| 3108 | | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[n & 3], xy[(n + 1) & 3], xy[(n + 2) & 3]); |
| 3109 | | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[(n + 2) & 3], xy[(n + 1) & 3], xy[(n + 3) & 3]); |
| 3110 | | } |
| 3111 | | wait(); |
| 3112 | | } else { |
| 3113 | | logerror("Unsupported primitive %d for method 0x1818\n",type); |
| 3114 | | countlen = 0; |
| 3115 | | } |
| 3116 | | } |
| 3117 | | if ((maddress >= 0x1720) && (maddress < 0x1760)) { |
| 3118 | | int bit = method - 0x1720 / 4; |
| 3119 | | |
| 3120 | | if (data & 0x80000000) |
| 3121 | | vertexbuffer_address[bit] = (data & 0x0fffffff) + dma_offset[1]; |
| 3122 | | else |
| 3123 | | vertexbuffer_address[bit] = (data & 0x0fffffff) + dma_offset[0]; |
| 3124 | | } |
| 3125 | | if ((maddress >= 0x1760) && (maddress < 0x17A0)) { |
| 3126 | | int bit=method-0x1760/4; |
| 3127 | | |
| 3128 | | vertexbuffer_stride[bit] = (data >> 8) & 255; |
| 3129 | | //vertexbuffer_kind[n]=tmp & 15; |
| 3130 | | //vertexbuffer_size[n]=(tmp >> 4) & 15; |
| 3131 | | data = data & 255; |
| 3132 | | switch (data & 15) { |
| 3133 | | case 0: |
| 3134 | | vertex_attribute_words[bit]=(((data >> 4) + 3) & 15) >> 2; |
| 3135 | | break; |
| 3136 | | case nv2a_renderer::FLOAT: |
| 3137 | | vertex_attribute_words[bit]=(data >> 4); |
| 3138 | | break; |
| 3139 | | case nv2a_renderer::UBYTE: |
| 3140 | | vertex_attribute_words[bit]=(((data >> 4) + 3) & 15) >> 2; |
| 3141 | | break; |
| 3142 | | case nv2a_renderer::USHORT: |
| 3143 | | vertex_attribute_words[bit]=(((data >> 4) + 1) & 15) >> 1; |
| 3144 | | break; |
| 3145 | | default: |
| 3146 | | vertex_attribute_words[bit]=0; |
| 3147 | | } |
| 3148 | | if (data > 15) |
| 3149 | | enabled_vertex_attributes |= (1 << bit); |
| 3150 | | else |
| 3151 | | enabled_vertex_attributes &= ~(1 << bit); |
| 3152 | | for (int n = bit+1; n < 16; n++) { |
| 3153 | | if ((enabled_vertex_attributes & (1 << (n - 1))) != 0) |
| 3154 | | vertex_attribute_offset[n] = vertex_attribute_offset[n - 1] + vertex_attribute_words[n - 1]; |
| 3155 | | else |
| 3156 | | vertex_attribute_offset[n] = vertex_attribute_offset[n - 1]; |
| 3157 | | } |
| 3158 | | countlen--; |
| 3159 | | } |
| 3160 | | if ((maddress == 0x1d6c) || (maddress == 0x1d70) || (maddress == 0x1a4)) |
| 3161 | | countlen--; |
| 3162 | | if (maddress == 0x019c) { |
| 3163 | | geforce_read_dma_object(data, dma_offset[0], dma_size[0]); |
| 3164 | | } |
| 3165 | | if (maddress == 0x01a0) { |
| 3166 | | geforce_read_dma_object(data, dma_offset[1], dma_size[1]); |
| 3167 | | } |
| 3168 | | if (maddress == 0x1d70) { |
| 3169 | | // with 1d70 write the value at offest [1d6c] inside dma object [1a4] |
| 3170 | | UINT32 offset,base; |
| 3171 | | UINT32 dmahand,dmaoff,smasiz; |
| 3172 | | |
| 3173 | | offset=channel[chanel][subchannel].object.method[0x1d6c/4]; |
| 3174 | | dmahand=channel[chanel][subchannel].object.method[0x1a4/4]; |
| 3175 | | geforce_read_dma_object(dmahand,dmaoff,smasiz); |
| 3176 | | base=dmaoff; |
| 3177 | | space.write_dword(base+offset,data); |
| 3178 | | countlen--; |
| 3179 | | } |
| 3180 | | if (maddress == 0x1d94) { |
| 3181 | | // possible buffers: color, depth, stencil, and accumulation |
| 3182 | | // clear framebuffer |
| 3183 | | if (data & 0xf0) { |
| 3184 | | // clear colors |
| 3185 | | UINT32 color=channel[chanel][subchannel].object.method[0x1d90/4]; |
| 3186 | | fb.fill(color); |
| 3187 | | //printf("clearscreen\n\r"); |
| 3188 | | } |
| 3189 | | if (data & 0x03) { |
| 3190 | | // clear stencil+zbuffer |
| 3191 | | } |
| 3192 | | countlen--; |
| 3193 | | } |
| 3194 | | if (maddress == 0x0300) { |
| 3195 | | alpha_test_enabled = data != 0; |
| 3196 | | } |
| 3197 | | if (maddress == 0x033c) { |
| 3198 | | alpha_func = data; |
| 3199 | | } |
| 3200 | | if (maddress == 0x0340) { |
| 3201 | | alpha_reference = data; |
| 3202 | | } |
| 3203 | | if (maddress == 0x0304) { |
| 3204 | | if (logical_operation_enabled) |
| 3205 | | blending_enabled = false; |
| 3206 | | else |
| 3207 | | blending_enabled = data != 0; |
| 3208 | | } |
| 3209 | | if (maddress == 0x0344) { |
| 3210 | | blend_function_source = data; |
| 3211 | | } |
| 3212 | | if (maddress == 0x0348) { |
| 3213 | | blend_function_destination = data; |
| 3214 | | } |
| 3215 | | if (maddress == 0x034c) { |
| 3216 | | blend_color = data; |
| 3217 | | } |
| 3218 | | if (maddress == 0x0350) { |
| 3219 | | blend_equation = data; |
| 3220 | | } |
| 3221 | | if (maddress == 0x0d40) { |
| 3222 | | if (data != 0) |
| 3223 | | blending_enabled = false; |
| 3224 | | else |
| 3225 | | blending_enabled = channel[chanel][subchannel].object.method[0x0304 / 4] != 0; |
| 3226 | | logical_operation_enabled = data != 0; |
| 3227 | | } |
| 3228 | | if (maddress == 0x0d44) { |
| 3229 | | logical_operation = data; |
| 3230 | | } |
| 3231 | | // Texture Units |
| 3232 | | if ((maddress >= 0x1b00) && (maddress < 0x1c00)) { |
| 3233 | | int unit;//,off; |
| 3234 | | |
| 3235 | | unit=(maddress >> 6) & 3; |
| 3236 | | //off=maddress & 0xc0; |
| 3237 | | maddress=maddress & ~0xc0; |
| 3238 | | if (maddress == 0x1b00) { |
| 3239 | | UINT32 offset;//,base; |
| 3240 | | //UINT32 dmahand,dmaoff,dmasiz; |
| 3241 | | |
| 3242 | | offset=data; |
| 3243 | | texture[unit].buffer=space.get_read_ptr(offset); |
| 3244 | | /*if (dma0 != 0) { |
| 3245 | | dmahand=channel[channel][subchannel].object.method[0x184/4]; |
| 3246 | | geforce_read_dma_object(dmahand,dmaoff,smasiz); |
| 3247 | | } else if (dma1 != 0) { |
| 3248 | | dmahand=channel[channel][subchannel].object.method[0x188/4]; |
| 3249 | | geforce_read_dma_object(dmahand,dmaoff,smasiz); |
| 3250 | | }*/ |
| 3251 | | } |
| 3252 | | if (maddress == 0x1b04) { |
| 3253 | | //int dma0,dma1,cubic,noborder,dims,mipmap; |
| 3254 | | int basesizeu,basesizev,basesizew,format; |
| 3255 | | |
| 3256 | | //dma0=(data >> 0) & 1; |
| 3257 | | //dma1=(data >> 1) & 1; |
| 3258 | | //cubic=(data >> 2) & 1; |
| 3259 | | //noborder=(data >> 3) & 1; |
| 3260 | | //dims=(data >> 4) & 15; |
| 3261 | | //mipmap=(data >> 19) & 1; |
| 3262 | | format=(data >> 8) & 255; |
| 3263 | | basesizeu=(data >> 20) & 15; |
| 3264 | | basesizev=(data >> 24) & 15; |
| 3265 | | basesizew=(data >> 28) & 15; |
| 3266 | | texture[unit].sizeu=1 << basesizeu; |
| 3267 | | texture[unit].sizev=1 << basesizev; |
| 3268 | | texture[unit].sizew=1 << basesizew; |
| 3269 | | texture[unit].dilate=dilatechose[(basesizeu << 4)+basesizev]; |
| 3270 | | texture[unit].format=format; |
| 3271 | | if (debug_grab_texttype == format) { |
| 3272 | | FILE *f; |
| 3273 | | int written; |
| 3274 | | |
| 3275 | | debug_grab_texttype = -1; |
| 3276 | | f = fopen(debug_grab_textfile, "wb"); |
| 3277 | | if (f) { |
| 3278 | | written=(int)fwrite(texture[unit].buffer, texture[unit].sizeu*texture[unit].sizev*4, 1, f); |
| 3279 | | fclose(f); |
| 3280 | | logerror("Written %d bytes of texture to specified file\n", written); |
| 3281 | | } else |
| 3282 | | logerror("Unable to save texture to specified file\n"); |
| 3283 | | } |
| 3284 | | } |
| 3285 | | if (maddress == 0x1b0c) { |
| 3286 | | // enable texture |
| 3287 | | int enable; |
| 3288 | | |
| 3289 | | enable=(data >> 30) & 1; |
| 3290 | | texture[unit].enabled=enable; |
| 3291 | | } |
| 3292 | | if (maddress == 0x1b10) { |
| 3293 | | texture[unit].rectangle_pitch=data >> 16; |
| 3294 | | } |
| 3295 | | countlen--; |
| 3296 | | } |
| 3297 | | // modelview matrix |
| 3298 | | if ((maddress >= 0x0480) && (maddress < 0x04c0)) { |
| 3299 | | maddress = (maddress - 0x0480) / 4; |
| 3300 | | *(UINT32 *)(&matrix.modelview[maddress]) = data; |
| 3301 | | countlen--; |
| 3302 | | } |
| 3303 | | // inverse modelview matrix |
| 3304 | | if ((maddress >= 0x0580) && (maddress < 0x05c0)) { |
| 3305 | | maddress = (maddress - 0x0580) / 4; |
| 3306 | | *(UINT32 *)(&matrix.modelview_inverse[maddress]) = data; |
| 3307 | | countlen--; |
| 3308 | | } |
| 3309 | | // projection matrix |
| 3310 | | if ((maddress >= 0x0680) && (maddress < 0x06c0)) { |
| 3311 | | maddress = (maddress - 0x0680) / 4; |
| 3312 | | *(UINT32 *)(&matrix.projection[maddress]) = data; |
| 3313 | | countlen--; |
| 3314 | | } |
| 3315 | | // viewport translate |
| 3316 | | if ((maddress >= 0x0a20) && (maddress < 0x0a30)) { |
| 3317 | | maddress = (maddress - 0x0a20) / 4; |
| 3318 | | *(UINT32 *)(&matrix.translate[maddress]) = data; |
| 3319 | | countlen--; |
| 3320 | | } |
| 3321 | | // viewport scale |
| 3322 | | if ((maddress >= 0x0af0) && (maddress < 0x0b00)) { |
| 3323 | | maddress = (maddress - 0x0af0) / 4; |
| 3324 | | *(UINT32 *)(&matrix.scale[maddress]) = data; |
| 3325 | | countlen--; |
| 3326 | | } |
| 3327 | | // Vertex program (shader) |
| 3328 | | if (maddress == 0x1e94) { |
| 3329 | | /*if (data == 2) |
| 3330 | | logerror("Enabled vertex program\n"); |
| 3331 | | else if (data == 4) |
| 3332 | | logerror("Enabled fixed function pipeline\n"); |
| 3333 | | else if (data == 6) |
| 3334 | | logerror("Enabled both fixed function pipeline and vertex program ?\n"); |
| 3335 | | else |
| 3336 | | logerror("Unknown value %d to method 0x1e94\n",data);*/ |
| 3337 | | vertex_pipeline = data & 6; |
| 3338 | | countlen--; |
| 3339 | | } |
| 3340 | | if (maddress == 0x1e9c) { |
| 3341 | | //logerror("VP_UPLOAD_FROM_ID %d\n",data); |
| 3342 | | vertexprogram.upload_instruction=data*4; |
| 3343 | | countlen--; |
| 3344 | | } |
| 3345 | | if (maddress == 0x1ea0) { |
| 3346 | | //logerror("VP_START_FROM_ID %d\n",data); |
| 3347 | | vertexprogram.instructions=vertexprogram.upload_instruction/4; |
| 3348 | | vertexprogram.start_instruction = data * 4; |
| 3349 | | countlen--; |
| 3350 | | } |
| 3351 | | if (maddress == 0x1ea4) { |
| 3352 | | //logerror("VP_UPLOAD_CONST_ID %d\n",data); |
| 3353 | | vertexprogram.upload_parameter=data*4; |
| 3354 | | countlen--; |
| 3355 | | } |
| 3356 | | if ((maddress >= 0x0b00) && (maddress < 0x0b80)) { |
| 3357 | | //logerror("VP_UPLOAD_INST\n"); |
| 3358 | | if (vertexprogram.upload_instruction < 1024) |
| 3359 | | vertexprogram.instruction[vertexprogram.upload_instruction]=data; |
| 3360 | | else |
| 3361 | | logerror("Need to increase size of vertexprogram.instruction to %d\n\r", vertexprogram.upload_parameter); |
| 3362 | | vertexprogram.upload_instruction++; |
| 3363 | | } |
| 3364 | | if ((maddress >= 0x0b80) && (maddress < 0x0c00)) { |
| 3365 | | //logerror("VP_UPLOAD_CONST\n"); |
| 3366 | | if (vertexprogram.upload_parameter < 1024) |
| 3367 | | *(UINT32 *)(&vertexprogram.parameter[vertexprogram.upload_parameter]) = data; |
| 3368 | | else |
| 3369 | | logerror("Need to increase size of vertexprogram.parameter to %d\n\r", vertexprogram.upload_parameter); |
| 3370 | | vertexprogram.upload_parameter++; |
| 3371 | | } |
| 3372 | | // Register combiners |
| 3373 | | if (maddress == 0x1e60) { |
| 3374 | | combiner.stages=data & 15; |
| 3375 | | countlen--; |
| 3376 | | } |
| 3377 | | if (maddress == 0x0288) { |
| 3378 | | combiner.final.mapin_rgbD_input=data & 15; |
| 3379 | | combiner.final.mapin_rgbD_component=(data >> 4) & 1; |
| 3380 | | combiner.final.mapin_rgbD_mapping=(data >> 5) & 7; |
| 3381 | | combiner.final.mapin_rgbC_input=(data >> 8) & 15; |
| 3382 | | combiner.final.mapin_rgbC_component=(data >> 12) & 1; |
| 3383 | | combiner.final.mapin_rgbC_mapping=(data >> 13) & 7; |
| 3384 | | combiner.final.mapin_rgbB_input=(data >> 16) & 15; |
| 3385 | | combiner.final.mapin_rgbB_component=(data >> 20) & 1; |
| 3386 | | combiner.final.mapin_rgbB_mapping=(data >> 21) & 7; |
| 3387 | | combiner.final.mapin_rgbA_input=(data >> 24) & 15; |
| 3388 | | combiner.final.mapin_rgbA_component=(data >> 28) & 1; |
| 3389 | | combiner.final.mapin_rgbA_mapping=(data >> 29) & 7; |
| 3390 | | countlen--; |
| 3391 | | } |
| 3392 | | if (maddress == 0x028c) { |
| 3393 | | combiner.final.color_sum_clamp=(data >> 7) & 1; |
| 3394 | | combiner.final.mapin_aG_input=(data >> 8) & 15; |
| 3395 | | combiner.final.mapin_aG_component=(data >> 12) & 1; |
| 3396 | | combiner.final.mapin_aG_mapping=(data >> 13) & 7; |
| 3397 | | combiner.final.mapin_rgbF_input=(data >> 16) & 15; |
| 3398 | | combiner.final.mapin_rgbF_component=(data >> 20) & 1; |
| 3399 | | combiner.final.mapin_rgbF_mapping=(data >> 21) & 7; |
| 3400 | | combiner.final.mapin_rgbE_input=(data >> 24) & 15; |
| 3401 | | combiner.final.mapin_rgbE_component=(data >> 28) & 1; |
| 3402 | | combiner.final.mapin_rgbE_mapping=(data >> 29) & 7; |
| 3403 | | countlen--; |
| 3404 | | } |
| 3405 | | if (maddress == 0x1e20) { |
| 3406 | | combiner_argb8_float(data,combiner.final.register_constantcolor0); |
| 3407 | | countlen--; |
| 3408 | | } |
| 3409 | | if (maddress == 0x1e24) { |
| 3410 | | combiner_argb8_float(data,combiner.final.register_constantcolor1); |
| 3411 | | countlen--; |
| 3412 | | } |
| 3413 | | if ((maddress >= 0x0260) && (maddress < 0x0280)) { |
| 3414 | | int n; |
| 3415 | | |
| 3416 | | n=(maddress-0x0260) >> 2; |
| 3417 | | combiner.stage[n].mapin_aD_input=data & 15; |
| 3418 | | combiner.stage[n].mapin_aD_component=(data >> 4) & 1; |
| 3419 | | combiner.stage[n].mapin_aD_mapping=(data >> 5) & 7; |
| 3420 | | combiner.stage[n].mapin_aC_input=(data >> 8) & 15; |
| 3421 | | combiner.stage[n].mapin_aC_component=(data >> 12) & 1; |
| 3422 | | combiner.stage[n].mapin_aC_mapping=(data >> 13) & 7; |
| 3423 | | combiner.stage[n].mapin_aB_input=(data >> 16) & 15; |
| 3424 | | combiner.stage[n].mapin_aB_component=(data >> 20) & 1; |
| 3425 | | combiner.stage[n].mapin_aB_mapping=(data >> 21) & 7; |
| 3426 | | combiner.stage[n].mapin_aA_input=(data >> 24) & 15; |
| 3427 | | combiner.stage[n].mapin_aA_component=(data >> 28) & 1; |
| 3428 | | combiner.stage[n].mapin_aA_mapping=(data >> 29) & 7; |
| 3429 | | countlen--; |
| 3430 | | } |
| 3431 | | if ((maddress >= 0x0ac0) && (maddress < 0x0ae0)) { |
| 3432 | | int n; |
| 3433 | | |
| 3434 | | n=(maddress-0x0ac0) >> 2; |
| 3435 | | combiner.stage[n].mapin_rgbD_input=data & 15; |
| 3436 | | combiner.stage[n].mapin_rgbD_component=(data >> 4) & 1; |
| 3437 | | combiner.stage[n].mapin_rgbD_mapping=(data >> 5) & 7; |
| 3438 | | combiner.stage[n].mapin_rgbC_input=(data >> 8) & 15; |
| 3439 | | combiner.stage[n].mapin_rgbC_component=(data >> 12) & 1; |
| 3440 | | combiner.stage[n].mapin_rgbC_mapping=(data >> 13) & 7; |
| 3441 | | combiner.stage[n].mapin_rgbB_input=(data >> 16) & 15; |
| 3442 | | combiner.stage[n].mapin_rgbB_component=(data >> 20) & 1; |
| 3443 | | combiner.stage[n].mapin_rgbB_mapping=(data >> 21) & 7; |
| 3444 | | combiner.stage[n].mapin_rgbA_input=(data >> 24) & 15; |
| 3445 | | combiner.stage[n].mapin_rgbA_component=(data >> 28) & 1; |
| 3446 | | combiner.stage[n].mapin_rgbA_mapping=(data >> 29) & 7; |
| 3447 | | countlen--; |
| 3448 | | } |
| 3449 | | if ((maddress >= 0x0a60) && (maddress < 0x0a80)) { |
| 3450 | | int n; |
| 3451 | | |
| 3452 | | n=(maddress-0x0a60) >> 2; |
| 3453 | | combiner_argb8_float(data,combiner.stage[n].register_constantcolor0); |
| 3454 | | countlen--; |
| 3455 | | } |
| 3456 | | if ((maddress >= 0x0a80) && (maddress < 0x0aa0)) { |
| 3457 | | int n; |
| 3458 | | |
| 3459 | | n=(maddress-0x0a80) >> 2; |
| 3460 | | combiner_argb8_float(data,combiner.stage[n].register_constantcolor1); |
| 3461 | | countlen--; |
| 3462 | | } |
| 3463 | | if ((maddress >= 0x0aa0) && (maddress < 0x0ac0)) { |
| 3464 | | int n; |
| 3465 | | |
| 3466 | | n=(maddress-0x0aa0) >> 2; |
| 3467 | | combiner.stage[n].mapout_aCD_output=data & 15; |
| 3468 | | combiner.stage[n].mapout_aAB_output=(data >> 4) & 15; |
| 3469 | | combiner.stage[n].mapout_aSUM_output=(data >> 8) & 15; |
| 3470 | | combiner.stage[n].mapout_aCD_dotproduct=(data >> 12) & 1; |
| 3471 | | combiner.stage[n].mapout_aAB_dotproduct=(data >> 13) & 1; |
| 3472 | | combiner.stage[n].mapout_a_muxsum=(data >> 14) & 1; |
| 3473 | | combiner.stage[n].mapout_a_bias=(data >> 15) & 1; |
| 3474 | | combiner.stage[n].mapout_a_scale=(data >> 16) & 3; |
| 3475 | | //combiner.=(data >> 27) & 7; |
| 3476 | | countlen--; |
| 3477 | | } |
| 3478 | | if ((maddress >= 0x1e40) && (maddress < 0x1e60)) { |
| 3479 | | int n; |
| 3480 | | |
| 3481 | | n=(maddress-0x1e40) >> 2; |
| 3482 | | combiner.stage[n].mapout_rgbCD_output=data & 15; |
| 3483 | | combiner.stage[n].mapout_rgbAB_output=(data >> 4) & 15; |
| 3484 | | combiner.stage[n].mapout_rgbSUM_output=(data >> 8) & 15; |
| 3485 | | combiner.stage[n].mapout_rgbCD_dotproduct=(data >> 12) & 1; |
| 3486 | | combiner.stage[n].mapout_rgbAB_dotproduct=(data >> 13) & 1; |
| 3487 | | combiner.stage[n].mapout_rgb_muxsum=(data >> 14) & 1; |
| 3488 | | combiner.stage[n].mapout_rgb_bias=(data >> 15) & 1; |
| 3489 | | combiner.stage[n].mapout_rgb_scale=(data >> 16) & 3; |
| 3490 | | //combiner.=(data >> 27) & 7; |
| 3491 | | countlen--; |
| 3492 | | } |
| 3493 | | } |
| 3494 | | |
| 3495 | | int nv2a_renderer::toggle_register_combiners_usage() |
| 3496 | | { |
| 3497 | | combiner.used=1-combiner.used; |
| 3498 | | return combiner.used; |
| 3499 | | } |
| 3500 | | |
| 3501 | | void nv2a_renderer::debug_grab_texture(int type, const char *filename) |
| 3502 | | { |
| 3503 | | debug_grab_texttype = type; |
| 3504 | | if (debug_grab_textfile == NULL) |
| 3505 | | debug_grab_textfile = (char *)malloc(128); |
| 3506 | | strncpy(debug_grab_textfile, filename, 127); |
| 3507 | | } |
| 3508 | | |
| 3509 | | void nv2a_renderer::debug_grab_vertex_program_slot(int slot, UINT32 *instruction) |
| 3510 | | { |
| 3511 | | if (slot >= 1024 / 4) |
| 3512 | | return; |
| 3513 | | instruction[0] = vertexprogram.instruction[slot * 4 + 0]; |
| 3514 | | instruction[1] = vertexprogram.instruction[slot * 4 + 1]; |
| 3515 | | instruction[2] = vertexprogram.instruction[slot * 4 + 2]; |
| 3516 | | instruction[3] = vertexprogram.instruction[slot * 4 + 3]; |
| 3517 | | } |
| 3518 | | |
| 3519 | | void nv2a_renderer::savestate_items() |
| 3520 | | { |
| 3521 | | } |
| 3522 | | |
| 3523 | | void nv2a_renderer::combiner_argb8_float(UINT32 color,float reg[4]) |
| 3524 | | { |
| 3525 | | reg[0]=(float)(color & 0xff)/255.0; |
| 3526 | | reg[1]=(float)((color >> 8) & 0xff)/255.0; |
| 3527 | | reg[2]=(float)((color >> 16) & 0xff)/255.0; |
| 3528 | | reg[3]=(float)((color >> 24) & 0xff)/255.0; |
| 3529 | | } |
| 3530 | | |
| 3531 | | UINT32 nv2a_renderer::combiner_float_argb8(float reg[4]) |
| 3532 | | { |
| 3533 | | UINT32 r,g,b,a; |
| 3534 | | |
| 3535 | | a=reg[3]*255.0; |
| 3536 | | b=reg[2]*255.0; |
| 3537 | | g=reg[1]*255.0; |
| 3538 | | r=reg[0]*255.0; |
| 3539 | | return (a << 24) | (r << 16) | (g << 8) | b; |
| 3540 | | } |
| 3541 | | |
| 3542 | | float nv2a_renderer::combiner_map_input_select(int code,int index) |
| 3543 | | { |
| 3544 | | switch (code) { |
| 3545 | | case 0: |
| 3546 | | default: |
| 3547 | | return combiner.register_zero[index]; |
| 3548 | | case 1: |
| 3549 | | return combiner.register_color0[index]; |
| 3550 | | case 2: |
| 3551 | | return combiner.register_color1[index]; |
| 3552 | | case 3: |
| 3553 | | return combiner.register_fogcolor[index]; |
| 3554 | | case 4: |
| 3555 | | return combiner.register_primarycolor[index]; |
| 3556 | | case 5: |
| 3557 | | return combiner.register_secondarycolor[index]; |
| 3558 | | case 8: |
| 3559 | | return combiner.register_texture0color[index]; |
| 3560 | | case 9: |
| 3561 | | return combiner.register_texture1color[index]; |
| 3562 | | case 10: |
| 3563 | | return combiner.register_texture2color[index]; |
| 3564 | | case 11: |
| 3565 | | return combiner.register_texture3color[index]; |
| 3566 | | case 12: |
| 3567 | | return combiner.register_spare0[index]; |
| 3568 | | case 13: |
| 3569 | | return combiner.register_spare1[index]; |
| 3570 | | case 14: |
| 3571 | | return combiner.variable_sumclamp[index]; |
| 3572 | | case 15: |
| 3573 | | return combiner.variable_EF[index]; |
| 3574 | | } |
| 3575 | | |
| 3576 | | // never executed |
| 3577 | | //return 0; |
| 3578 | | } |
| 3579 | | |
| 3580 | | float *nv2a_renderer::combiner_map_input_select3(int code) |
| 3581 | | { |
| 3582 | | switch (code) { |
| 3583 | | case 0: |
| 3584 | | default: |
| 3585 | | return combiner.register_zero; |
| 3586 | | case 1: |
| 3587 | | return combiner.register_color0; |
| 3588 | | case 2: |
| 3589 | | return combiner.register_color1; |
| 3590 | | case 3: |
| 3591 | | return combiner.register_fogcolor; |
| 3592 | | case 4: |
| 3593 | | return combiner.register_primarycolor; |
| 3594 | | case 5: |
| 3595 | | return combiner.register_secondarycolor; |
| 3596 | | case 8: |
| 3597 | | return combiner.register_texture0color; |
| 3598 | | case 9: |
| 3599 | | return combiner.register_texture1color; |
| 3600 | | case 10: |
| 3601 | | return combiner.register_texture2color; |
| 3602 | | case 11: |
| 3603 | | return combiner.register_texture3color; |
| 3604 | | case 12: |
| 3605 | | return combiner.register_spare0; |
| 3606 | | case 13: |
| 3607 | | return combiner.register_spare1; |
| 3608 | | case 14: |
| 3609 | | return combiner.variable_sumclamp; |
| 3610 | | case 15: |
| 3611 | | return combiner.variable_EF; |
| 3612 | | } |
| 3613 | | |
| 3614 | | // never executed |
| 3615 | | //return 0; |
| 3616 | | } |
| 3617 | | |
| 3618 | | float *nv2a_renderer::combiner_map_output_select3(int code) |
| 3619 | | { |
| 3620 | | switch (code) { |
| 3621 | | case 0: |
| 3622 | | return 0; |
| 3623 | | case 1: |
| 3624 | | return 0; |
| 3625 | | case 2: |
| 3626 | | return 0; |
| 3627 | | case 3: |
| 3628 | | return 0; |
| 3629 | | case 4: |
| 3630 | | return combiner.register_primarycolor; |
| 3631 | | case 5: |
| 3632 | | return combiner.register_secondarycolor; |
| 3633 | | case 8: |
| 3634 | | return combiner.register_texture0color; |
| 3635 | | case 9: |
| 3636 | | return combiner.register_texture1color; |
| 3637 | | case 10: |
| 3638 | | return combiner.register_texture2color; |
| 3639 | | case 11: |
| 3640 | | return combiner.register_texture3color; |
| 3641 | | case 12: |
| 3642 | | return combiner.register_spare0; |
| 3643 | | case 13: |
| 3644 | | return combiner.register_spare1; |
| 3645 | | case 14: |
| 3646 | | return 0; |
| 3647 | | case 15: |
| 3648 | | default: |
| 3649 | | return 0; |
| 3650 | | } |
| 3651 | | } |
| 3652 | | |
| 3653 | | float nv2a_renderer::combiner_map_input_function(int code,float value) |
| 3654 | | { |
| 3655 | | float t; |
| 3656 | | |
| 3657 | | switch (code) { |
| 3658 | | case 0: |
| 3659 | | return MAX(0.0,value); |
| 3660 | | case 1: |
| 3661 | | t=MAX(value, 0.0); |
| 3662 | | return 1.0 - MIN(t, 1.0); |
| 3663 | | case 2: |
| 3664 | | return 2.0 * MAX(0.0, value) - 1.0; |
| 3665 | | case 3: |
| 3666 | | return -2.0 * MAX(0.0, value) + 1.0; |
| 3667 | | case 4: |
| 3668 | | return MAX(0.0, value) - 0.5; |
| 3669 | | case 5: |
| 3670 | | return -MAX(0.0, value) + 0.5; |
| 3671 | | case 6: |
| 3672 | | return value; |
| 3673 | | case 7: |
| 3674 | | default: |
| 3675 | | return -value; |
| 3676 | | } |
| 3677 | | |
| 3678 | | // never executed |
| 3679 | | //return 0; |
| 3680 | | } |
| 3681 | | |
| 3682 | | void nv2a_renderer::combiner_map_input_function3(int code,float *data) |
| 3683 | | { |
| 3684 | | float t; |
| 3685 | | |
| 3686 | | switch (code) { |
| 3687 | | case 0: |
| 3688 | | data[0]=MAX(0.0,data[0]); |
| 3689 | | data[1]=MAX(0.0,data[1]); |
| 3690 | | data[2]=MAX(0.0,data[2]); |
| 3691 | | break; |
| 3692 | | case 1: |
| 3693 | | t=MAX(data[0], 0.0); |
| 3694 | | data[0]=1.0 - MIN(t, 1.0); |
| 3695 | | t=MAX(data[1], 0.0); |
| 3696 | | data[1]=1.0 - MIN(t, 1.0); |
| 3697 | | t=MAX(data[2], 0.0); |
| 3698 | | data[2]=1.0 - MIN(t, 1.0); |
| 3699 | | break; |
| 3700 | | case 2: |
| 3701 | | data[0]=2.0 * MAX(0.0, data[0]) - 1.0; |
| 3702 | | data[1]=2.0 * MAX(0.0, data[1]) - 1.0; |
| 3703 | | data[2]=2.0 * MAX(0.0, data[2]) - 1.0; |
| 3704 | | break; |
| 3705 | | case 3: |
| 3706 | | data[0]=-2.0 * MAX(0.0, data[0]) + 1.0; |
| 3707 | | data[1]=-2.0 * MAX(0.0, data[1]) + 1.0; |
| 3708 | | data[2]=-2.0 * MAX(0.0, data[2]) + 1.0; |
| 3709 | | break; |
| 3710 | | case 4: |
| 3711 | | data[0]=MAX(0.0, data[0]) - 0.5; |
| 3712 | | data[1]=MAX(0.0, data[1]) - 0.5; |
| 3713 | | data[2]=MAX(0.0, data[2]) - 0.5; |
| 3714 | | break; |
| 3715 | | case 5: |
| 3716 | | data[0]=-MAX(0.0, data[0]) + 0.5; |
| 3717 | | data[1]=-MAX(0.0, data[1]) + 0.5; |
| 3718 | | data[2]=-MAX(0.0, data[2]) + 0.5; |
| 3719 | | break; |
| 3720 | | case 6: |
| 3721 | | return; |
| 3722 | | case 7: |
| 3723 | | default: |
| 3724 | | data[0]=-data[0]; |
| 3725 | | data[1]=-data[1]; |
| 3726 | | data[2]=-data[2]; |
| 3727 | | break; |
| 3728 | | } |
| 3729 | | } |
| 3730 | | |
| 3731 | | void nv2a_renderer::combiner_initialize_registers(UINT32 argb8[6]) |
| 3732 | | { |
| 3733 | | combiner_argb8_float(argb8[0],combiner.register_primarycolor); |
| 3734 | | combiner_argb8_float(argb8[1],combiner.register_secondarycolor); |
| 3735 | | combiner_argb8_float(argb8[2],combiner.register_texture0color); |
| 3736 | | combiner_argb8_float(argb8[3],combiner.register_texture1color); |
| 3737 | | combiner_argb8_float(argb8[4],combiner.register_texture2color); |
| 3738 | | combiner_argb8_float(argb8[5],combiner.register_texture3color); |
| 3739 | | combiner.register_spare0[3]=combiner.register_texture0color[3]; |
| 3740 | | combiner.register_zero[0]=combiner.register_zero[1]=combiner.register_zero[2]=combiner.register_zero[3]=0; |
| 3741 | | } |
| 3742 | | |
| 3743 | | void nv2a_renderer::combiner_initialize_stage(int stage_number) |
| 3744 | | { |
| 3745 | | int n=stage_number; |
| 3746 | | |
| 3747 | | // put register_constantcolor0 in register_color0 |
| 3748 | | combiner.register_color0[0]=combiner.stage[n].register_constantcolor0[0]; |
| 3749 | | combiner.register_color0[1]=combiner.stage[n].register_constantcolor0[1]; |
| 3750 | | combiner.register_color0[2]=combiner.stage[n].register_constantcolor0[2]; |
| 3751 | | combiner.register_color0[3]=combiner.stage[n].register_constantcolor0[3]; |
| 3752 | | // put register_constantcolor1 in register_color1 |
| 3753 | | combiner.register_color1[0]=combiner.stage[n].register_constantcolor1[0]; |
| 3754 | | combiner.register_color1[1]=combiner.stage[n].register_constantcolor1[1]; |
| 3755 | | combiner.register_color1[2]=combiner.stage[n].register_constantcolor1[2]; |
| 3756 | | combiner.register_color1[3]=combiner.stage[n].register_constantcolor1[3]; |
| 3757 | | } |
| 3758 | | |
| 3759 | | void nv2a_renderer::combiner_initialize_final() |
| 3760 | | { |
| 3761 | | // put register_constantcolor0 in register_color0 |
| 3762 | | combiner.register_color0[0]=combiner.final.register_constantcolor0[0]; |
| 3763 | | combiner.register_color0[1]=combiner.final.register_constantcolor0[1]; |
| 3764 | | combiner.register_color0[2]=combiner.final.register_constantcolor0[2]; |
| 3765 | | combiner.register_color0[3]=combiner.final.register_constantcolor0[3]; |
| 3766 | | // put register_constantcolor1 in register_color1 |
| 3767 | | combiner.register_color1[0]=combiner.final.register_constantcolor1[0]; |
| 3768 | | combiner.register_color1[1]=combiner.final.register_constantcolor1[1]; |
| 3769 | | combiner.register_color1[2]=combiner.final.register_constantcolor1[2]; |
| 3770 | | combiner.register_color1[3]=combiner.final.register_constantcolor1[3]; |
| 3771 | | } |
| 3772 | | |
| 3773 | | void nv2a_renderer::combiner_map_input(int stage_number) |
| 3774 | | { |
| 3775 | | int n=stage_number; |
| 3776 | | int c,d,i; |
| 3777 | | float v,*pv; |
| 3778 | | |
| 3779 | | // A |
| 3780 | | v=combiner_map_input_select(combiner.stage[n].mapin_aA_input,2+combiner.stage[n].mapin_aA_component); |
| 3781 | | combiner.variable_A[3]=combiner_map_input_function(combiner.stage[n].mapin_aA_mapping,v); |
| 3782 | | // B |
| 3783 | | v=combiner_map_input_select(combiner.stage[n].mapin_aB_input,2+combiner.stage[n].mapin_aB_component); |
| 3784 | | combiner.variable_B[3]=combiner_map_input_function(combiner.stage[n].mapin_aB_mapping,v); |
| 3785 | | // C |
| 3786 | | v=combiner_map_input_select(combiner.stage[n].mapin_aC_input,2+combiner.stage[n].mapin_aC_component); |
| 3787 | | combiner.variable_C[3]=combiner_map_input_function(combiner.stage[n].mapin_aC_mapping,v); |
| 3788 | | // D |
| 3789 | | v=combiner_map_input_select(combiner.stage[n].mapin_aD_input,2+combiner.stage[n].mapin_aD_component); |
| 3790 | | combiner.variable_D[3]=combiner_map_input_function(combiner.stage[n].mapin_aD_mapping,v); |
| 3791 | | |
| 3792 | | // A |
| 3793 | | pv=combiner_map_input_select3(combiner.stage[n].mapin_rgbA_input); |
| 3794 | | c=combiner.stage[n].mapin_rgbA_component*3; |
| 3795 | | i=~combiner.stage[n].mapin_rgbA_component & 1; |
| 3796 | | for (d=0;d < 3;d++) { |
| 3797 | | combiner.variable_A[d]=pv[c]; |
| 3798 | | c=c+i; |
| 3799 | | } |
| 3800 | | combiner_map_input_function3(combiner.stage[n].mapin_rgbA_mapping,combiner.variable_A); |
| 3801 | | // B |
| 3802 | | pv=combiner_map_input_select3(combiner.stage[n].mapin_rgbB_input); |
| 3803 | | c=combiner.stage[n].mapin_rgbB_component*3; |
| 3804 | | i=~combiner.stage[n].mapin_rgbB_component & 1; |
| 3805 | | for (d=0;d < 3;d++) { |
| 3806 | | combiner.variable_B[d]=pv[c]; |
| 3807 | | c=c+i; |
| 3808 | | } |
| 3809 | | combiner_map_input_function3(combiner.stage[n].mapin_rgbB_mapping,combiner.variable_B); |
| 3810 | | // C |
| 3811 | | pv=combiner_map_input_select3(combiner.stage[n].mapin_rgbC_input); |
| 3812 | | c=combiner.stage[n].mapin_rgbC_component*3; |
| 3813 | | i=~combiner.stage[n].mapin_rgbC_component & 1; |
| 3814 | | for (d=0;d < 3;d++) { |
| 3815 | | combiner.variable_C[d]=pv[c]; |
| 3816 | | c=c+i; |
| 3817 | | } |
| 3818 | | combiner_map_input_function3(combiner.stage[n].mapin_rgbC_mapping,combiner.variable_C); |
| 3819 | | // D |
| 3820 | | pv=combiner_map_input_select3(combiner.stage[n].mapin_rgbD_input); |
| 3821 | | c=combiner.stage[n].mapin_rgbD_component*3; |
| 3822 | | i=~combiner.stage[n].mapin_rgbD_component & 1; |
| 3823 | | for (d=0;d < 3;d++) { |
| 3824 | | combiner.variable_D[d]=pv[c]; |
| 3825 | | c=c+i; |
| 3826 | | } |
| 3827 | | combiner_map_input_function3(combiner.stage[n].mapin_rgbD_mapping,combiner.variable_D); |
| 3828 | | } |
| 3829 | | |
| 3830 | | void nv2a_renderer::combiner_map_output(int stage_number) |
| 3831 | | { |
| 3832 | | int n=stage_number; |
| 3833 | | float *f; |
| 3834 | | |
| 3835 | | // rgb |
| 3836 | | f=combiner_map_output_select3(combiner.stage[n].mapout_rgbAB_output); |
| 3837 | | if (f) { |
| 3838 | | f[0]=combiner.function_RGBop1[0]; |
| 3839 | | f[1]=combiner.function_RGBop1[1]; |
| 3840 | | f[2]=combiner.function_RGBop1[2]; |
| 3841 | | } |
| 3842 | | f=combiner_map_output_select3(combiner.stage[n].mapout_rgbCD_output); |
| 3843 | | if (f) { |
| 3844 | | f[0]=combiner.function_RGBop2[0]; |
| 3845 | | f[1]=combiner.function_RGBop2[1]; |
| 3846 | | f[2]=combiner.function_RGBop2[2]; |
| 3847 | | } |
| 3848 | | if ((combiner.stage[n].mapout_rgbAB_dotproduct | combiner.stage[n].mapout_rgbCD_dotproduct) == 0) { |
| 3849 | | f=combiner_map_output_select3(combiner.stage[n].mapout_rgbSUM_output); |
| 3850 | | if (f) { |
| 3851 | | f[0]=combiner.function_RGBop3[0]; |
| 3852 | | f[1]=combiner.function_RGBop3[1]; |
| 3853 | | f[2]=combiner.function_RGBop3[2]; |
| 3854 | | } |
| 3855 | | } |
| 3856 | | // a |
| 3857 | | f=combiner_map_output_select3(combiner.stage[n].mapout_aAB_output); |
| 3858 | | if (f) |
| 3859 | | f[3]=combiner.function_Aop1; |
| 3860 | | f=combiner_map_output_select3(combiner.stage[n].mapout_aCD_output); |
| 3861 | | if (f) |
| 3862 | | f[3]=combiner.function_Aop2; |
| 3863 | | f=combiner_map_output_select3(combiner.stage[n].mapout_aSUM_output); |
| 3864 | | if (f) |
| 3865 | | f[3]=combiner.function_Aop3; |
| 3866 | | } |
| 3867 | | |
| 3868 | | void nv2a_renderer::combiner_map_final_input() |
| 3869 | | { |
| 3870 | | int i,c,d; |
| 3871 | | float *pv; |
| 3872 | | |
| 3873 | | // E |
| 3874 | | pv=combiner_map_input_select3(combiner.final.mapin_rgbE_input); |
| 3875 | | c=combiner.final.mapin_rgbE_component*3; |
| 3876 | | i=~combiner.final.mapin_rgbE_component & 1; |
| 3877 | | for (d=0;d < 3;d++) { |
| 3878 | | combiner.variable_E[d]=pv[c]; |
| 3879 | | c=c+i; |
| 3880 | | } |
| 3881 | | combiner_map_input_function3(combiner.final.mapin_rgbE_mapping,combiner.variable_E); |
| 3882 | | // F |
| 3883 | | pv=combiner_map_input_select3(combiner.final.mapin_rgbF_input); |
| 3884 | | c=combiner.final.mapin_rgbF_component*3; |
| 3885 | | i=~combiner.final.mapin_rgbF_component & 1; |
| 3886 | | for (d=0;d < 3;d++) { |
| 3887 | | combiner.variable_F[d]=pv[c]; |
| 3888 | | c=c+i; |
| 3889 | | } |
| 3890 | | combiner_map_input_function3(combiner.final.mapin_rgbF_mapping,combiner.variable_F); |
| 3891 | | // EF |
| 3892 | | combiner.variable_EF[0]=combiner.variable_E[0]*combiner.variable_F[0]; |
| 3893 | | combiner.variable_EF[1]=combiner.variable_E[1]*combiner.variable_F[1]; |
| 3894 | | combiner.variable_EF[2]=combiner.variable_E[2]*combiner.variable_F[2]; |
| 3895 | | // sumclamp |
| 3896 | | combiner.variable_sumclamp[0]=MAX(0,combiner.register_spare0[0])+MAX(0,combiner.register_secondarycolor[0]); |
| 3897 | | combiner.variable_sumclamp[1]=MAX(0,combiner.register_spare0[1])+MAX(0,combiner.register_secondarycolor[1]); |
| 3898 | | combiner.variable_sumclamp[2]=MAX(0,combiner.register_spare0[2])+MAX(0,combiner.register_secondarycolor[2]); |
| 3899 | | if (combiner.final.color_sum_clamp != 0) { |
| 3900 | | combiner.variable_sumclamp[0]=MIN(combiner.variable_sumclamp[0],1.0); |
| 3901 | | combiner.variable_sumclamp[1]=MIN(combiner.variable_sumclamp[1],1.0); |
| 3902 | | combiner.variable_sumclamp[2]=MIN(combiner.variable_sumclamp[2],1.0); |
| 3903 | | } |
| 3904 | | // A |
| 3905 | | pv=combiner_map_input_select3(combiner.final.mapin_rgbA_input); |
| 3906 | | c=combiner.final.mapin_rgbA_component*3; |
| 3907 | | i=~combiner.final.mapin_rgbA_component & 1; |
| 3908 | | for (d=0;d < 3;d++) { |
| 3909 | | combiner.variable_A[d]=pv[c]; |
| 3910 | | c=c+i; |
| 3911 | | } |
| 3912 | | combiner_map_input_function3(combiner.final.mapin_rgbA_mapping,combiner.variable_A); |
| 3913 | | // B |
| 3914 | | pv=combiner_map_input_select3(combiner.final.mapin_rgbB_input); |
| 3915 | | c=combiner.final.mapin_rgbB_component*3; |
| 3916 | | i=~combiner.final.mapin_rgbB_component & 1; |
| 3917 | | for (d=0;d < 3;d++) { |
| 3918 | | combiner.variable_B[d]=pv[c]; |
| 3919 | | c=c+i; |
| 3920 | | } |
| 3921 | | combiner_map_input_function3(combiner.final.mapin_rgbB_mapping,combiner.variable_B); |
| 3922 | | // C |
| 3923 | | pv=combiner_map_input_select3(combiner.final.mapin_rgbC_input); |
| 3924 | | c=combiner.final.mapin_rgbC_component*3; |
| 3925 | | i=~combiner.final.mapin_rgbC_component & 1; |
| 3926 | | for (d=0;d < 3;d++) { |
| 3927 | | combiner.variable_C[d]=pv[c]; |
| 3928 | | c=c+i; |
| 3929 | | } |
| 3930 | | combiner_map_input_function3(combiner.final.mapin_rgbC_mapping,combiner.variable_C); |
| 3931 | | // D |
| 3932 | | pv=combiner_map_input_select3(combiner.final.mapin_rgbD_input); |
| 3933 | | c=combiner.final.mapin_rgbD_component*3; |
| 3934 | | i=~combiner.final.mapin_rgbD_component & 1; |
| 3935 | | for (d=0;d < 3;d++) { |
| 3936 | | combiner.variable_D[d]=pv[c]; |
| 3937 | | c=c+i; |
| 3938 | | } |
| 3939 | | combiner_map_input_function3(combiner.final.mapin_rgbD_mapping,combiner.variable_D); |
| 3940 | | // G |
| 3941 | | combiner.variable_G=combiner_map_input_select(combiner.final.mapin_aG_input,2+combiner.final.mapin_aG_component); |
| 3942 | | } |
| 3943 | | |
| 3944 | | void nv2a_renderer::combiner_final_output() |
| 3945 | | { |
| 3946 | | // rgb |
| 3947 | | combiner.output[0]=combiner.variable_A[0]*combiner.variable_B[0]+(1.0-combiner.variable_A[0])*combiner.variable_C[0]+combiner.variable_D[0]; |
| 3948 | | combiner.output[1]=combiner.variable_A[1]*combiner.variable_B[1]+(1.0-combiner.variable_A[1])*combiner.variable_C[1]+combiner.variable_D[1]; |
| 3949 | | combiner.output[2]=combiner.variable_A[2]*combiner.variable_B[2]+(1.0-combiner.variable_A[2])*combiner.variable_C[2]+combiner.variable_D[2]; |
| 3950 | | combiner.output[0]=MIN(combiner.output[0],1.0); |
| 3951 | | combiner.output[1]=MIN(combiner.output[1],1.0); |
| 3952 | | combiner.output[2]=MIN(combiner.output[2],1.0); |
| 3953 | | // a |
| 3954 | | combiner.output[3]=combiner_map_input_function(combiner.final.mapin_aG_mapping,combiner.variable_G); |
| 3955 | | } |
| 3956 | | |
| 3957 | | void nv2a_renderer::combiner_function_AB(float result[4]) |
| 3958 | | { |
| 3959 | | result[0]=combiner.variable_A[0]*combiner.variable_B[0]; |
| 3960 | | result[1]=combiner.variable_A[1]*combiner.variable_B[1]; |
| 3961 | | result[2]=combiner.variable_A[2]*combiner.variable_B[2]; |
| 3962 | | } |
| 3963 | | |
| 3964 | | void nv2a_renderer::combiner_function_AdotB(float result[4]) |
| 3965 | | { |
| 3966 | | result[0]=combiner.variable_A[0]*combiner.variable_B[0]+combiner.variable_A[1]*combiner.variable_B[1]+combiner.variable_A[2]*combiner.variable_B[2]; |
| 3967 | | result[1]=result[0]; |
| 3968 | | result[2]=result[0]; |
| 3969 | | } |
| 3970 | | |
| 3971 | | void nv2a_renderer::combiner_function_CD(float result[4]) |
| 3972 | | { |
| 3973 | | result[0]=combiner.variable_C[0]*combiner.variable_D[0]; |
| 3974 | | result[1]=combiner.variable_C[1]*combiner.variable_D[1]; |
| 3975 | | result[2]=combiner.variable_C[2]*combiner.variable_D[2]; |
| 3976 | | } |
| 3977 | | |
| 3978 | | void nv2a_renderer::combiner_function_CdotD(float result[4]) |
| 3979 | | { |
| 3980 | | result[0]=combiner.variable_C[0]*combiner.variable_D[0]+combiner.variable_C[1]*combiner.variable_D[1]+combiner.variable_C[2]*combiner.variable_D[2]; |
| 3981 | | result[1]=result[0]; |
| 3982 | | result[2]=result[0]; |
| 3983 | | } |
| 3984 | | |
| 3985 | | void nv2a_renderer::combiner_function_ABmuxCD(float result[4]) |
| 3986 | | { |
| 3987 | | if (combiner.register_spare0[3] >= 0.5) |
| 3988 | | combiner_function_AB(result); |
| 3989 | | else |
| 3990 | | combiner_function_CD(result); |
| 3991 | | } |
| 3992 | | |
| 3993 | | void nv2a_renderer::combiner_function_ABsumCD(float result[4]) |
| 3994 | | { |
| 3995 | | result[0]=combiner.variable_A[0]*combiner.variable_B[0]+combiner.variable_C[0]*combiner.variable_D[0]; |
| 3996 | | result[1]=combiner.variable_A[1]*combiner.variable_B[1]+combiner.variable_C[1]*combiner.variable_D[1]; |
| 3997 | | result[2]=combiner.variable_A[2]*combiner.variable_B[2]+combiner.variable_C[2]*combiner.variable_D[2]; |
| 3998 | | } |
| 3999 | | |
| 4000 | | void nv2a_renderer::combiner_compute_rgb_outputs(int stage_number) |
| 4001 | | { |
| 4002 | | int n=stage_number; |
| 4003 | | int m; |
| 4004 | | float biasrgb,scalergb; |
| 4005 | | |
| 4006 | | if (combiner.stage[n].mapout_rgb_bias) |
| 4007 | | biasrgb= -0.5; |
| 4008 | | else |
| 4009 | | biasrgb=0; |
| 4010 | | switch (combiner.stage[n].mapout_rgb_scale) { |
| 4011 | | case 0: |
| 4012 | | default: |
| 4013 | | scalergb=1.0; |
| 4014 | | break; |
| 4015 | | case 1: |
| 4016 | | scalergb=2.0; |
| 4017 | | break; |
| 4018 | | case 2: |
| 4019 | | scalergb=4.0; |
| 4020 | | break; |
| 4021 | | case 3: |
| 4022 | | scalergb=0.5; |
| 4023 | | break; |
| 4024 | | } |
| 4025 | | if (combiner.stage[n].mapout_rgbAB_dotproduct) { |
| 4026 | | m=1; |
| 4027 | | combiner_function_AdotB(combiner.function_RGBop1); |
| 4028 | | } else { |
| 4029 | | m=0; |
| 4030 | | combiner_function_AB(combiner.function_RGBop1); |
| 4031 | | } |
| 4032 | | combiner.function_RGBop1[0]=MAX(MIN((combiner.function_RGBop1[0] + biasrgb) * scalergb, 1.0), -1.0); |
| 4033 | | combiner.function_RGBop1[1]=MAX(MIN((combiner.function_RGBop1[1] + biasrgb) * scalergb, 1.0), -1.0); |
| 4034 | | combiner.function_RGBop1[2]=MAX(MIN((combiner.function_RGBop1[2] + biasrgb) * scalergb, 1.0), -1.0); |
| 4035 | | if (combiner.stage[n].mapout_rgbCD_dotproduct) { |
| 4036 | | m=m | 1; |
| 4037 | | combiner_function_CdotD(combiner.function_RGBop2); |
| 4038 | | } else |
| 4039 | | combiner_function_CD(combiner.function_RGBop2); |
| 4040 | | combiner.function_RGBop2[0]=MAX(MIN((combiner.function_RGBop2[0] + biasrgb) * scalergb, 1.0), -1.0); |
| 4041 | | combiner.function_RGBop2[1]=MAX(MIN((combiner.function_RGBop2[1] + biasrgb) * scalergb, 1.0), -1.0); |
| 4042 | | combiner.function_RGBop2[2]=MAX(MIN((combiner.function_RGBop2[2] + biasrgb) * scalergb, 1.0), -1.0); |
| 4043 | | if (m == 0) { |
| 4044 | | if (combiner.stage[n].mapout_rgb_muxsum) |
| 4045 | | combiner_function_ABmuxCD(combiner.function_RGBop3); |
| 4046 | | else |
| 4047 | | combiner_function_ABsumCD(combiner.function_RGBop3); |
| 4048 | | combiner.function_RGBop3[0]=MAX(MIN((combiner.function_RGBop3[0] + biasrgb) * scalergb, 1.0), -1.0); |
| 4049 | | combiner.function_RGBop3[1]=MAX(MIN((combiner.function_RGBop3[1] + biasrgb) * scalergb, 1.0), -1.0); |
| 4050 | | combiner.function_RGBop3[2]=MAX(MIN((combiner.function_RGBop3[2] + biasrgb) * scalergb, 1.0), -1.0); |
| 4051 | | } |
| 4052 | | } |
| 4053 | | |
| 4054 | | void nv2a_renderer::combiner_compute_a_outputs(int stage_number) |
| 4055 | | { |
| 4056 | | int n=stage_number; |
| 4057 | | float biasa,scalea; |
| 4058 | | |
| 4059 | | if (combiner.stage[n].mapout_a_bias) |
| 4060 | | biasa= -0.5; |
| 4061 | | else |
| 4062 | | biasa=0; |
| 4063 | | switch (combiner.stage[n].mapout_a_scale) { |
| 4064 | | case 0: |
| 4065 | | default: |
| 4066 | | scalea=1.0; |
| 4067 | | break; |
| 4068 | | case 1: |
| 4069 | | scalea=2.0; |
| 4070 | | break; |
| 4071 | | case 2: |
| 4072 | | scalea=4.0; |
| 4073 | | break; |
| 4074 | | case 3: |
| 4075 | | scalea=0.5; |
| 4076 | | break; |
| 4077 | | } |
| 4078 | | combiner.function_Aop1=combiner.variable_A[3]*combiner.variable_B[3]; |
| 4079 | | combiner.function_Aop1=MAX(MIN((combiner.function_Aop1 + biasa) * scalea, 1.0), -1.0); |
| 4080 | | combiner.function_Aop2=combiner.variable_C[3]*combiner.variable_D[3]; |
| 4081 | | combiner.function_Aop2=MAX(MIN((combiner.function_Aop2 + biasa) * scalea, 1.0), -1.0); |
| 4082 | | if (combiner.stage[n].mapout_a_muxsum) { |
| 4083 | | if (combiner.register_spare0[3] >= 0.5) |
| 4084 | | combiner.function_Aop3=combiner.variable_A[3]*combiner.variable_B[3]; |
| 4085 | | else |
| 4086 | | combiner.function_Aop3=combiner.variable_C[3]*combiner.variable_D[3]; |
| 4087 | | } else |
| 4088 | | combiner.function_Aop3=combiner.variable_A[3]*combiner.variable_B[3]+combiner.variable_C[3]*combiner.variable_D[3]; |
| 4089 | | combiner.function_Aop3=MAX(MIN((combiner.function_Aop3 + biasa) * scalea, 1.0), -1.0); |
| 4090 | | } |
| 4091 | | |
| 4092 | | void nv2a_renderer::vblank_callback(screen_device &screen, bool state) |
| 4093 | | { |
| 4094 | | chihiro_state *chst=machine().driver_data<chihiro_state>(); |
| 4095 | | |
| 4096 | | //printf("vblank_callback\n\r"); |
| 4097 | | if (state == true) |
| 4098 | | pcrtc[0x100/4] |= 1; |
| 4099 | | else |
| 4100 | | pcrtc[0x100/4] &= ~1; |
| 4101 | | if (pcrtc[0x100/4] & pcrtc[0x140/4]) |
| 4102 | | pmc[0x100/4] |= 0x1000000; |
| 4103 | | else |
| 4104 | | pmc[0x100/4] &= ~0x1000000; |
| 4105 | | if ((pmc[0x100/4] != 0) && (pmc[0x140/4] != 0)) { |
| 4106 | | // send interrupt |
| 4107 | | chst->chihiro_devs.pic8259_1->ir3_w(1); // IRQ 3 |
| 4108 | | } else |
| 4109 | | chst->chihiro_devs.pic8259_1->ir3_w(0); // IRQ 3 |
| 4110 | | } |
| 4111 | | |
| 4112 | | UINT32 nv2a_renderer::screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 4113 | | { |
| 4114 | | UINT32 *dst=(UINT32 *)bitmap.raw_pixptr(0,0); |
| 4115 | | UINT32 *src=(UINT32 *)fb.raw_pixptr(0,0); |
| 4116 | | |
| 4117 | | //printf("updatescreen\n\r"); |
| 4118 | | memcpy(dst,src,bitmap.rowbytes()*bitmap.height()); |
| 4119 | | return 0; |
| 4120 | | } |
| 4121 | | |
| 4122 | | void chihiro_state::debug_generate_irq(int irq,bool active) |
| 4123 | | { |
| 4124 | 901 | int state; |
| 4125 | 902 | |
| 4126 | 903 | if (active) |
| 4127 | 904 | { |
| 4128 | | debug_irq_active=true; |
| 4129 | | debug_irq_number=irq; |
| 4130 | | state=1; |
| 905 | debug_irq_active = true; |
| 906 | debug_irq_number = irq; |
| 907 | state = 1; |
| 4131 | 908 | } |
| 4132 | 909 | else |
| 4133 | 910 | { |
| 4134 | | debug_irq_active=false; |
| 4135 | | state=0; |
| 911 | debug_irq_active = false; |
| 912 | state = 0; |
| 4136 | 913 | } |
| 4137 | 914 | switch (irq) |
| 4138 | 915 | { |
| r242208 | r242209 | |
| 4186 | 963 | |
| 4187 | 964 | void chihiro_state::vblank_callback(screen_device &screen, bool state) |
| 4188 | 965 | { |
| 4189 | | nvidia_nv2a->vblank_callback(screen,state); |
| 966 | if (nvidia_nv2a->vblank_callback(screen, state)) |
| 967 | chihiro_devs.pic8259_1->ir3_w(1); // IRQ 3 |
| 968 | else |
| 969 | chihiro_devs.pic8259_1->ir3_w(0); // IRQ 3 |
| 4190 | 970 | } |
| 4191 | 971 | |
| 4192 | 972 | UINT32 chihiro_state::screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| r242208 | r242209 | |
| 4194 | 974 | return nvidia_nv2a->screen_update_callback(screen, bitmap, cliprect); |
| 4195 | 975 | } |
| 4196 | 976 | |
| 4197 | | READ32_MEMBER( nv2a_renderer::geforce_r ) |
| 977 | READ32_MEMBER(chihiro_state::geforce_r) |
| 4198 | 978 | { |
| 4199 | | static int x,ret; |
| 4200 | | |
| 4201 | | ret=0; |
| 4202 | | if (offset == 0x1804f6) { |
| 4203 | | x = x ^ 0x08080808; |
| 4204 | | ret=x; |
| 4205 | | } |
| 4206 | | if ((offset >= 0x00101000/4) && (offset < 0x00102000/4)) { |
| 4207 | | //logerror("NV_2A: read STRAPS[%06X] mask %08X value %08X\n",offset*4-0x00101000,mem_mask,ret); |
| 4208 | | } else if ((offset >= 0x00002000/4) && (offset < 0x00004000/4)) { |
| 4209 | | ret=pfifo[offset-0x00002000/4]; |
| 4210 | | // PFIFO.CACHE1.STATUS or PFIFO.RUNOUT_STATUS |
| 4211 | | if ((offset == 0x3214/4) || (offset == 0x2400/4)) |
| 4212 | | ret=0x10; |
| 4213 | | //logerror("NV_2A: read PFIFO[%06X] value %08X\n",offset*4-0x00002000,ret); |
| 4214 | | } else if ((offset >= 0x00700000/4) && (offset < 0x00800000/4)) { |
| 4215 | | ret=ramin[offset-0x00700000/4]; |
| 4216 | | //logerror("NV_2A: read PRAMIN[%06X] value %08X\n",offset*4-0x00700000,ret); |
| 4217 | | } else if ((offset >= 0x00400000/4) && (offset < 0x00402000/4)) { |
| 4218 | | //logerror("NV_2A: read PGRAPH[%06X] value %08X\n",offset*4-0x00400000,ret); |
| 4219 | | } else if ((offset >= 0x00600000/4) && (offset < 0x00601000/4)) { |
| 4220 | | ret=pcrtc[offset-0x00600000/4]; |
| 4221 | | //logerror("NV_2A: read PCRTC[%06X] value %08X\n",offset*4-0x00600000,ret); |
| 4222 | | } else if ((offset >= 0x00000000/4) && (offset < 0x00001000/4)) { |
| 4223 | | ret=pmc[offset-0x00000000/4]; |
| 4224 | | //logerror("NV_2A: read PMC[%06X] value %08X\n",offset*4-0x00000000,ret); |
| 4225 | | } else if ((offset >= 0x00800000/4) && (offset < 0x00900000/4)) { |
| 4226 | | // 32 channels size 0x10000 each, 8 subchannels per channel size 0x2000 each |
| 4227 | | int chanel,subchannel,suboffset; |
| 4228 | | |
| 4229 | | suboffset=offset-0x00800000/4; |
| 4230 | | chanel=(suboffset >> (16-2)) & 31; |
| 4231 | | subchannel=(suboffset >> (13-2)) & 7; |
| 4232 | | suboffset=suboffset & 0x7ff; |
| 4233 | | if (suboffset < 0x80/4) |
| 4234 | | ret=channel[chanel][subchannel].regs[suboffset]; |
| 4235 | | //logerror("NV_2A: read channel[%02X,%d,%04X]=%08X\n",chanel,subchannel,suboffset*4,ret); |
| 4236 | | return ret; |
| 4237 | | } else ; |
| 4238 | | //logerror("NV_2A: read at %08X mask %08X value %08X\n",0xfd000000+offset*4,mem_mask,ret); |
| 4239 | | return ret; |
| 979 | return nvidia_nv2a->geforce_r(space, offset, mem_mask); |
| 4240 | 980 | } |
| 4241 | 981 | |
| 4242 | | WRITE32_MEMBER( nv2a_renderer::geforce_w ) |
| 982 | WRITE32_MEMBER(chihiro_state::geforce_w) |
| 4243 | 983 | { |
| 4244 | | if ((offset >= 0x00101000/4) && (offset < 0x00102000/4)) { |
| 4245 | | //logerror("NV_2A: write STRAPS[%06X] mask %08X value %08X\n",offset*4-0x00101000,mem_mask,data); |
| 4246 | | } else if ((offset >= 0x00002000/4) && (offset < 0x00004000/4)) { |
| 4247 | | COMBINE_DATA(pfifo+offset-0x00002000/4); |
| 4248 | | //logerror("NV_2A: read PFIFO[%06X]=%08X\n",offset*4-0x00002000,data & mem_mask); // 2210 pfifo ramht & 1f0 << 12 |
| 4249 | | } else if ((offset >= 0x00700000/4) && (offset < 0x00800000/4)) { |
| 4250 | | COMBINE_DATA(ramin+offset-0x00700000/4); |
| 4251 | | //logerror("NV_2A: write PRAMIN[%06X]=%08X\n",offset*4-0x00700000,data & mem_mask); |
| 4252 | | } else if ((offset >= 0x00400000/4) && (offset < 0x00402000/4)) { |
| 4253 | | //logerror("NV_2A: write PGRAPH[%06X]=%08X\n",offset*4-0x00400000,data & mem_mask); |
| 4254 | | } else if ((offset >= 0x00600000/4) && (offset < 0x00601000/4)) { |
| 4255 | | COMBINE_DATA(pcrtc+offset-0x00600000/4); |
| 4256 | | //logerror("NV_2A: write PCRTC[%06X]=%08X\n",offset*4-0x00600000,data & mem_mask); |
| 4257 | | } else if ((offset >= 0x00000000/4) && (offset < 0x00001000/4)) { |
| 4258 | | COMBINE_DATA(pmc+offset-0x00000000/4); |
| 4259 | | //logerror("NV_2A: write PMC[%06X]=%08X\n",offset*4-0x00000000,data & mem_mask); |
| 4260 | | } else if ((offset >= 0x00800000/4) && (offset < 0x00900000/4)) { |
| 4261 | | // 32 channels size 0x10000 each, 8 subchannels per channel size 0x2000 each |
| 4262 | | int chanel,subchannel,suboffset; |
| 4263 | | int method,count,handle,objclass; |
| 4264 | | #ifdef LOG_NV2A |
| 4265 | | int subch; |
| 4266 | | #endif |
| 4267 | | |
| 4268 | | suboffset=offset-0x00800000/4; |
| 4269 | | chanel=(suboffset >> (16-2)) & 31; |
| 4270 | | subchannel=(suboffset >> (13-2)) & 7; |
| 4271 | | suboffset=suboffset & 0x7ff; |
| 4272 | | //logerror("NV_2A: write channel[%02X,%d,%04X]=%08X\n",chanel,subchannel,suboffset*4,data & mem_mask); |
| 4273 | | if (suboffset >= 0x80/4) |
| 4274 | | return; |
| 4275 | | COMBINE_DATA(&channel[chanel][subchannel].regs[suboffset]); |
| 4276 | | if ((suboffset == 0x40/4) || (suboffset == 0x44/4)) { // DMA_PUT or DMA_GET |
| 4277 | | UINT32 *dmaput,*dmaget; |
| 4278 | | UINT32 cmd,cmdtype; |
| 4279 | | int countlen; |
| 4280 | | |
| 4281 | | dmaput=&channel[chanel][subchannel].regs[0x40/4]; |
| 4282 | | dmaget=&channel[chanel][subchannel].regs[0x44/4]; |
| 4283 | | //printf("dmaget %08X dmaput %08X\n\r",*dmaget,*dmaput); |
| 4284 | | if ((*dmaput == 0x048cf000) && (*dmaget == 0x07f4d000)) |
| 4285 | | *dmaget = *dmaput; |
| 4286 | | while (*dmaget != *dmaput) { |
| 4287 | | cmd=space.read_dword(*dmaget); |
| 4288 | | *dmaget += 4; |
| 4289 | | cmdtype=geforce_commandkind(cmd); |
| 4290 | | switch (cmdtype) |
| 4291 | | { |
| 4292 | | case 6: // jump |
| 4293 | | #ifdef LOG_NV2A |
| 4294 | | printf("jump dmaget %08X",*dmaget); |
| 4295 | | #endif |
| 4296 | | *dmaget=cmd & 0xfffffffc; |
| 4297 | | #ifdef LOG_NV2A |
| 4298 | | printf(" -> %08X\n\r",*dmaget); |
| 4299 | | #endif |
| 4300 | | break; |
| 4301 | | case 0: // increasing method |
| 4302 | | method=(cmd >> 2) & 2047; // method*4 is address // if method >= 0x40 send it to assigned object |
| 4303 | | #ifdef LOG_NV2A |
| 4304 | | subch=(cmd >> 13) & 7; |
| 4305 | | #endif |
| 4306 | | count=(cmd >> 18) & 2047; |
| 4307 | | if ((method == 0) && (count == 1)) { |
| 4308 | | handle=space.read_dword(*dmaget); |
| 4309 | | handle=geforce_object_offset(handle); |
| 4310 | | #ifdef LOG_NV2A |
| 4311 | | logerror(" assign to subchannel %d object at %d\n",subch,handle); |
| 4312 | | #endif |
| 4313 | | channel[chanel][subchannel].object.objhandle=handle; |
| 4314 | | handle=ramin[handle/4]; |
| 4315 | | objclass=handle & 0xff; |
| 4316 | | channel[chanel][subchannel].object.objclass=objclass; |
| 4317 | | *dmaget += 4; |
| 4318 | | } else { |
| 4319 | | #ifdef LOG_NV2A |
| 4320 | | logerror(" subch. %d method %04x offset %04x count %d\n",subch,method,method*4,count); |
| 4321 | | #endif |
| 4322 | | while (count > 0) { |
| 4323 | | countlen=1; |
| 4324 | | geforce_exec_method(space,chanel,subchannel,method,*dmaget,countlen); |
| 4325 | | count--; |
| 4326 | | method++; |
| 4327 | | *dmaget += 4; |
| 4328 | | } |
| 4329 | | } |
| 4330 | | break; |
| 4331 | | case 5: // non-increasing method |
| 4332 | | method=(cmd >> 2) & 2047; |
| 4333 | | #ifdef LOG_NV2A |
| 4334 | | subch=(cmd >> 13) & 7; |
| 4335 | | #endif |
| 4336 | | count=(cmd >> 18) & 2047; |
| 4337 | | if ((method == 0) && (count == 1)) { |
| 4338 | | #ifdef LOG_NV2A |
| 4339 | | logerror(" assign channel %d\n",subch); |
| 4340 | | #endif |
| 4341 | | handle=space.read_dword(*dmaget); |
| 4342 | | handle=geforce_object_offset(handle); |
| 4343 | | #ifdef LOG_NV2A |
| 4344 | | logerror(" assign to subchannel %d object at %d\n",subch,handle); |
| 4345 | | #endif |
| 4346 | | channel[chanel][subchannel].object.objhandle=handle; |
| 4347 | | handle=ramin[handle/4]; |
| 4348 | | objclass=handle & 0xff; |
| 4349 | | channel[chanel][subchannel].object.objclass=objclass; |
| 4350 | | *dmaget += 4; |
| 4351 | | } else { |
| 4352 | | #ifdef LOG_NV2A |
| 4353 | | logerror(" subch. %d method %04x offset %04x count %d\n",subch,method,method*4,count); |
| 4354 | | #endif |
| 4355 | | while (count > 0) { |
| 4356 | | countlen=count; |
| 4357 | | geforce_exec_method(space,chanel,subchannel,method,*dmaget,countlen); |
| 4358 | | *dmaget += 4*(count-countlen); |
| 4359 | | count=countlen; |
| 4360 | | } |
| 4361 | | } |
| 4362 | | break; |
| 4363 | | case 3: // long non-increasing method |
| 4364 | | method=(cmd >> 2) & 2047; |
| 4365 | | #ifdef LOG_NV2A |
| 4366 | | subch=(cmd >> 13) & 7; |
| 4367 | | #endif |
| 4368 | | count=space.read_dword(*dmaget); |
| 4369 | | *dmaget += 4; |
| 4370 | | if ((method == 0) && (count == 1)) { |
| 4371 | | handle=space.read_dword(*dmaget); |
| 4372 | | handle=geforce_object_offset(handle); |
| 4373 | | #ifdef LOG_NV2A |
| 4374 | | logerror(" assign to subchannel %d object at %d\n",subch,handle); |
| 4375 | | #endif |
| 4376 | | channel[chanel][subchannel].object.objhandle=handle; |
| 4377 | | handle=ramin[handle/4]; |
| 4378 | | objclass=handle & 0xff; |
| 4379 | | channel[chanel][subchannel].object.objclass=objclass; |
| 4380 | | *dmaget += 4; |
| 4381 | | } else { |
| 4382 | | #ifdef LOG_NV2A |
| 4383 | | logerror(" subch. %d method %04x offset %04x count %d\n",subch,method,method*4,count); |
| 4384 | | #endif |
| 4385 | | while (count > 0) { |
| 4386 | | countlen=count; |
| 4387 | | geforce_exec_method(space,chanel,subchannel,method,*dmaget,countlen); |
| 4388 | | *dmaget += 4*(count-countlen); |
| 4389 | | count=countlen; |
| 4390 | | } |
| 4391 | | } |
| 4392 | | break; |
| 4393 | | default: |
| 4394 | | logerror(" unimplemented command %08X\n",cmd); |
| 4395 | | } |
| 4396 | | } |
| 4397 | | } |
| 4398 | | } else ; |
| 4399 | | // logerror("NV_2A: write at %08X mask %08X value %08X\n",0xfd000000+offset*4,mem_mask,data); |
| 984 | nvidia_nv2a->geforce_w(space, offset, data, mem_mask); |
| 4400 | 985 | } |
| 4401 | 986 | |
| 4402 | | READ32_MEMBER( chihiro_state::geforce_r ) |
| 4403 | | { |
| 4404 | | return nvidia_nv2a->geforce_r(space,offset,mem_mask); |
| 4405 | | } |
| 4406 | | |
| 4407 | | WRITE32_MEMBER( chihiro_state::geforce_w ) |
| 4408 | | { |
| 4409 | | nvidia_nv2a->geforce_w(space,offset,data,mem_mask); |
| 4410 | | } |
| 4411 | | |
| 4412 | 987 | static UINT32 geforce_pci_r(device_t *busdevice, device_t *device, int function, int reg, UINT32 mem_mask) |
| 4413 | 988 | { |
| 4414 | 989 | #ifdef LOG_PCI |
| 4415 | | // logerror(" bus:1 device:NV_2A function:%d register:%d mask:%08X\n",function,reg,mem_mask); |
| 990 | // logerror(" bus:1 device:NV_2A function:%d register:%d mask:%08X\n",function,reg,mem_mask); |
| 4416 | 991 | #endif |
| 4417 | 992 | return 0; |
| 4418 | 993 | } |
| r242208 | r242209 | |
| 4420 | 995 | static void geforce_pci_w(device_t *busdevice, device_t *device, int function, int reg, UINT32 data, UINT32 mem_mask) |
| 4421 | 996 | { |
| 4422 | 997 | #ifdef LOG_PCI |
| 4423 | | // logerror(" bus:1 device:NV_2A function:%d register:%d data:%08X mask:%08X\n",function,reg,data,mem_mask); |
| 998 | // logerror(" bus:1 device:NV_2A function:%d register:%d data:%08X mask:%08X\n",function,reg,data,mem_mask); |
| 4424 | 999 | #endif |
| 4425 | 1000 | } |
| 4426 | 1001 | |
| r242208 | r242209 | |
| 4429 | 1004 | */ |
| 4430 | 1005 | |
| 4431 | 1006 | #ifdef LOG_OHCI |
| 4432 | | static const char *const usbregnames[]={ |
| 1007 | static const char *const usbregnames[] = { |
| 4433 | 1008 | "HcRevision", |
| 4434 | 1009 | "HcControl", |
| 4435 | 1010 | "HcCommandStatus", |
| r242208 | r242209 | |
| 4455 | 1030 | }; |
| 4456 | 1031 | #endif |
| 4457 | 1032 | |
| 4458 | | READ32_MEMBER( chihiro_state::usbctrl_r ) |
| 1033 | READ32_MEMBER(chihiro_state::usbctrl_r) |
| 4459 | 1034 | { |
| 4460 | 1035 | if (offset == 0) { /* hack needed until usb (and jvs) is implemented */ |
| 4461 | 1036 | if (usbhack_counter == 0) { |
| 4462 | | m_maincpu->space(0).write_byte(0x6a79f,0x01); |
| 4463 | | m_maincpu->space(0).write_byte(0x6a7a0,0x00); |
| 4464 | | m_maincpu->space(0).write_byte(0x6b575,0x00); |
| 4465 | | m_maincpu->space(0).write_byte(0x6b576,0x00); |
| 4466 | | m_maincpu->space(0).write_byte(0x6b5af,0x75); |
| 4467 | | m_maincpu->space(0).write_byte(0x6b78a,0x75); |
| 4468 | | m_maincpu->space(0).write_byte(0x6b7ca,0x00); |
| 4469 | | m_maincpu->space(0).write_byte(0x6b7b8,0x00); |
| 4470 | | m_maincpu->space(0).write_byte(0x8f5b2,0x75); |
| 4471 | | m_maincpu->space(0).write_byte(0x79a9e,0x74); |
| 4472 | | m_maincpu->space(0).write_byte(0x79b80,0x74); |
| 4473 | | m_maincpu->space(0).write_byte(0x79b97,0x74); |
| 1037 | m_maincpu->space(0).write_byte(0x6a79f, 0x01); |
| 1038 | m_maincpu->space(0).write_byte(0x6a7a0, 0x00); |
| 1039 | m_maincpu->space(0).write_byte(0x6b575, 0x00); |
| 1040 | m_maincpu->space(0).write_byte(0x6b576, 0x00); |
| 1041 | m_maincpu->space(0).write_byte(0x6b5af, 0x75); |
| 1042 | m_maincpu->space(0).write_byte(0x6b78a, 0x75); |
| 1043 | m_maincpu->space(0).write_byte(0x6b7ca, 0x00); |
| 1044 | m_maincpu->space(0).write_byte(0x6b7b8, 0x00); |
| 1045 | m_maincpu->space(0).write_byte(0x8f5b2, 0x75); |
| 1046 | m_maincpu->space(0).write_byte(0x79a9e, 0x74); |
| 1047 | m_maincpu->space(0).write_byte(0x79b80, 0x74); |
| 1048 | m_maincpu->space(0).write_byte(0x79b97, 0x74); |
| 4474 | 1049 | } |
| 4475 | 1050 | // after game loaded |
| 4476 | 1051 | if (usbhack_counter == 1) { |
| 4477 | | m_maincpu->space(0).write_byte(0x12e4cf,0x01); |
| 4478 | | m_maincpu->space(0).write_byte(0x12e4d0,0x00); |
| 4479 | | m_maincpu->space(0).write_byte(0x4793e,0x01); |
| 4480 | | m_maincpu->space(0).write_byte(0x4793f,0x00); |
| 4481 | | m_maincpu->space(0).write_byte(0x47aa3,0x01); |
| 4482 | | m_maincpu->space(0).write_byte(0x47aa4,0x00); |
| 4483 | | m_maincpu->space(0).write_byte(0x14f2b6,0x84); |
| 4484 | | m_maincpu->space(0).write_byte(0x14f2d1,0x75); |
| 4485 | | m_maincpu->space(0).write_byte(0x8732f,0x7d); |
| 4486 | | m_maincpu->space(0).write_byte(0x87384,0x7d); |
| 4487 | | m_maincpu->space(0).write_byte(0x87388,0xeb); |
| 1052 | m_maincpu->space(0).write_byte(0x12e4cf, 0x01); |
| 1053 | m_maincpu->space(0).write_byte(0x12e4d0, 0x00); |
| 1054 | m_maincpu->space(0).write_byte(0x4793e, 0x01); |
| 1055 | m_maincpu->space(0).write_byte(0x4793f, 0x00); |
| 1056 | m_maincpu->space(0).write_byte(0x47aa3, 0x01); |
| 1057 | m_maincpu->space(0).write_byte(0x47aa4, 0x00); |
| 1058 | m_maincpu->space(0).write_byte(0x14f2b6, 0x84); |
| 1059 | m_maincpu->space(0).write_byte(0x14f2d1, 0x75); |
| 1060 | m_maincpu->space(0).write_byte(0x8732f, 0x7d); |
| 1061 | m_maincpu->space(0).write_byte(0x87384, 0x7d); |
| 1062 | m_maincpu->space(0).write_byte(0x87388, 0xeb); |
| 4488 | 1063 | } |
| 4489 | 1064 | usbhack_counter++; |
| 4490 | 1065 | } |
| 4491 | 1066 | #ifdef LOG_OHCI |
| 4492 | | if (offset >= 0x54/4) |
| 4493 | | logerror("usb controller 0 register HcRhPortStatus[%d] read\n",(offset-0x54/4)+1); |
| 1067 | if (offset >= 0x54 / 4) |
| 1068 | logerror("usb controller 0 register HcRhPortStatus[%d] read\n", (offset - 0x54 / 4) + 1); |
| 4494 | 1069 | else |
| 4495 | | logerror("usb controller 0 register %s read\n",usbregnames[offset]); |
| 1070 | logerror("usb controller 0 register %s read\n", usbregnames[offset]); |
| 4496 | 1071 | #endif |
| 4497 | 1072 | return 0; |
| 4498 | 1073 | } |
| 4499 | 1074 | |
| 4500 | | WRITE32_MEMBER( chihiro_state::usbctrl_w ) |
| 1075 | WRITE32_MEMBER(chihiro_state::usbctrl_w) |
| 4501 | 1076 | { |
| 4502 | 1077 | #ifdef LOG_OHCI |
| 4503 | | if (offset >= 0x54/4) |
| 4504 | | logerror("usb controller 0 register HcRhPortStatus[%d] write %08X\n",(offset-0x54/4)+1,data); |
| 1078 | if (offset >= 0x54 / 4) |
| 1079 | logerror("usb controller 0 register HcRhPortStatus[%d] write %08X\n", (offset - 0x54 / 4) + 1, data); |
| 4505 | 1080 | else |
| 4506 | | logerror("usb controller 0 register %s write %08X\n",usbregnames[offset],data); |
| 1081 | logerror("usb controller 0 register %s write %08X\n", usbregnames[offset], data); |
| 4507 | 1082 | #endif |
| 4508 | 1083 | } |
| 4509 | 1084 | |
| r242208 | r242209 | |
| 4511 | 1086 | * Audio |
| 4512 | 1087 | */ |
| 4513 | 1088 | |
| 4514 | | READ32_MEMBER( chihiro_state::audio_apu_r ) |
| 1089 | READ32_MEMBER(chihiro_state::audio_apu_r) |
| 4515 | 1090 | { |
| 4516 | | logerror("Audio_APU: read from %08X mask %08X\n",0xfe800000+offset*4,mem_mask); |
| 4517 | | if (offset == 0x20010/4) // some kind of internal counter or state value |
| 4518 | | return 0x20+4+8+0x48+0x80; |
| 1091 | logerror("Audio_APU: read from %08X mask %08X\n", 0xfe800000 + offset * 4, mem_mask); |
| 1092 | if (offset == 0x20010 / 4) // some kind of internal counter or state value |
| 1093 | return 0x20 + 4 + 8 + 0x48 + 0x80; |
| 4519 | 1094 | return apust.memory[offset]; |
| 4520 | 1095 | } |
| 4521 | 1096 | |
| 4522 | | WRITE32_MEMBER( chihiro_state::audio_apu_w ) |
| 1097 | WRITE32_MEMBER(chihiro_state::audio_apu_w) |
| 4523 | 1098 | { |
| 4524 | 1099 | //UINT32 old; |
| 4525 | 1100 | UINT32 v; |
| 4526 | 1101 | |
| 4527 | | logerror("Audio_APU: write at %08X mask %08X value %08X\n",0xfe800000+offset*4,mem_mask,data); |
| 1102 | logerror("Audio_APU: write at %08X mask %08X value %08X\n", 0xfe800000 + offset * 4, mem_mask, data); |
| 4528 | 1103 | //old = apust.memory[offset]; |
| 4529 | 1104 | apust.memory[offset] = data; |
| 4530 | | if (offset == 0x02040/4) // address of memory area with scatter-gather info (gpdsp scratch dma) |
| 4531 | | apust.gpdsp_sgaddress=data; |
| 4532 | | if (offset == 0x020d4/4) { // block count (gpdsp) |
| 4533 | | apust.gpdsp_sgblocks=data; |
| 4534 | | apust.gpdsp_address=apust.space->read_dword(apust.gpdsp_sgaddress); // memory address of first block |
| 1105 | if (offset == 0x02040 / 4) // address of memory area with scatter-gather info (gpdsp scratch dma) |
| 1106 | apust.gpdsp_sgaddress = data; |
| 1107 | if (offset == 0x020d4 / 4) { // block count (gpdsp) |
| 1108 | apust.gpdsp_sgblocks = data; |
| 1109 | apust.gpdsp_address = apust.space->read_dword(apust.gpdsp_sgaddress); // memory address of first block |
| 4535 | 1110 | apust.timer->enable(); |
| 4536 | | apust.timer->adjust(attotime::from_msec(1),0,attotime::from_msec(1)); |
| 1111 | apust.timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1)); |
| 4537 | 1112 | } |
| 4538 | 1113 | if (offset == 0x02048 / 4) // (epdsp scratch dma) |
| 4539 | | apust.epdsp_sgaddress=data; |
| 1114 | apust.epdsp_sgaddress = data; |
| 4540 | 1115 | if (offset == 0x020dc / 4) // (epdsp) |
| 4541 | | apust.epdsp_sgblocks=data; |
| 1116 | apust.epdsp_sgblocks = data; |
| 4542 | 1117 | if (offset == 0x0204c / 4) // address of memory area with information about blocks |
| 4543 | 1118 | apust.unknown_sgaddress = data; |
| 4544 | 1119 | if (offset == 0x020e0 / 4) // block count - 1 |
| r242208 | r242209 | |
| 4574 | 1149 | return; |
| 4575 | 1150 | if (offset == 0x20304 / 4) { // format |
| 4576 | 1151 | /* |
| 4577 | | bits 28-31 sample format: |
| 4578 | | 0 8-bit pcm |
| 4579 | | 5 16-bit pcm |
| 4580 | | 10 adpcm ? |
| 4581 | | 14 24-bit pcm |
| 4582 | | 15 32-bit pcm |
| 4583 | | bits 16-20 number of channels - 1: |
| 4584 | | 0 mono |
| 4585 | | 1 stereo |
| 1152 | bits 28-31 sample format: |
| 1153 | 0 8-bit pcm |
| 1154 | 5 16-bit pcm |
| 1155 | 10 adpcm ? |
| 1156 | 14 24-bit pcm |
| 1157 | 15 32-bit pcm |
| 1158 | bits 16-20 number of channels - 1: |
| 1159 | 0 mono |
| 1160 | 1 stereo |
| 4586 | 1161 | */ |
| 4587 | 1162 | return; |
| 4588 | 1163 | } |
| r242208 | r242209 | |
| 4597 | 1172 | if (offset == 0x203a0 / 4) // start offset of data in scatter-gather heap |
| 4598 | 1173 | return; |
| 4599 | 1174 | if (offset == 0x203a4 / 4) { // first sample to play |
| 4600 | | apust.voices_position_start[apust.voice_number] = data*1000; |
| 1175 | apust.voices_position_start[apust.voice_number] = data * 1000; |
| 4601 | 1176 | return; |
| 4602 | 1177 | } |
| 4603 | 1178 | if (offset == 0x203dc / 4) { // last sample to play |
| 4604 | | apust.voices_position_end[apust.voice_number] = data*1000; |
| 1179 | apust.voices_position_end[apust.voice_number] = data * 1000; |
| 4605 | 1180 | return; |
| 4606 | 1181 | } |
| 4607 | 1182 | if (offset == 0x2010c / 4) // voice processor 0 idle 1 not idle ? |
| r242208 | r242209 | |
| 4626 | 1201 | return; |
| 4627 | 1202 | } |
| 4628 | 1203 | |
| 4629 | | READ32_MEMBER( chihiro_state::audio_ac93_r ) |
| 1204 | READ32_MEMBER(chihiro_state::audio_ac93_r) |
| 4630 | 1205 | { |
| 4631 | | UINT32 ret=0; |
| 1206 | UINT32 ret = 0; |
| 4632 | 1207 | |
| 4633 | | logerror("Audio_AC3: read from %08X mask %08X\n",0xfec00000+offset*4,mem_mask); |
| 4634 | | if (offset < 0x80/4) |
| 1208 | logerror("Audio_AC3: read from %08X mask %08X\n", 0xfec00000 + offset * 4, mem_mask); |
| 1209 | if (offset < 0x80 / 4) |
| 4635 | 1210 | { |
| 4636 | | ret=ac97st.mixer_regs[offset]; |
| 1211 | ret = ac97st.mixer_regs[offset]; |
| 4637 | 1212 | } |
| 4638 | | if ((offset >= 0x100/4) && (offset <= 0x138/4)) |
| 1213 | if ((offset >= 0x100 / 4) && (offset <= 0x138 / 4)) |
| 4639 | 1214 | { |
| 4640 | | offset=offset-0x100/4; |
| 4641 | | if (offset == 0x18/4) |
| 1215 | offset = offset - 0x100 / 4; |
| 1216 | if (offset == 0x18 / 4) |
| 4642 | 1217 | { |
| 4643 | 1218 | ac97st.controller_regs[offset] &= ~0x02000000; // REGRST: register reset |
| 4644 | 1219 | } |
| 4645 | | if (offset == 0x30/4) |
| 1220 | if (offset == 0x30 / 4) |
| 4646 | 1221 | { |
| 4647 | 1222 | ac97st.controller_regs[offset] |= 0x100; // PCRDY: primary codec ready |
| 4648 | 1223 | } |
| 4649 | | if (offset == 0x34/4) |
| 1224 | if (offset == 0x34 / 4) |
| 4650 | 1225 | { |
| 4651 | 1226 | ac97st.controller_regs[offset] &= ~1; // CAS: codec access semaphore |
| 4652 | 1227 | } |
| 4653 | | ret=ac97st.controller_regs[offset]; |
| 1228 | ret = ac97st.controller_regs[offset]; |
| 4654 | 1229 | } |
| 4655 | 1230 | return ret; |
| 4656 | 1231 | } |
| 4657 | 1232 | |
| 4658 | | WRITE32_MEMBER( chihiro_state::audio_ac93_w ) |
| 1233 | WRITE32_MEMBER(chihiro_state::audio_ac93_w) |
| 4659 | 1234 | { |
| 4660 | | logerror("Audio_AC3: write at %08X mask %08X value %08X\n",0xfec00000+offset*4,mem_mask,data); |
| 4661 | | if (offset < 0x80/4) |
| 1235 | logerror("Audio_AC3: write at %08X mask %08X value %08X\n", 0xfec00000 + offset * 4, mem_mask, data); |
| 1236 | if (offset < 0x80 / 4) |
| 4662 | 1237 | { |
| 4663 | | COMBINE_DATA(ac97st.mixer_regs+offset); |
| 1238 | COMBINE_DATA(ac97st.mixer_regs + offset); |
| 4664 | 1239 | } |
| 4665 | | if ((offset >= 0x100/4) && (offset <= 0x138/4)) |
| 1240 | if ((offset >= 0x100 / 4) && (offset <= 0x138 / 4)) |
| 4666 | 1241 | { |
| 4667 | | offset=offset-0x100/4; |
| 4668 | | COMBINE_DATA(ac97st.controller_regs+offset); |
| 1242 | offset = offset - 0x100 / 4; |
| 1243 | COMBINE_DATA(ac97st.controller_regs + offset); |
| 4669 | 1244 | } |
| 4670 | 1245 | } |
| 4671 | 1246 | |
| r242208 | r242209 | |
| 4676 | 1251 | UINT64 bv; |
| 4677 | 1252 | UINT32 phys; |
| 4678 | 1253 | |
| 4679 | | cmd=apust.space->read_dword(apust.gpdsp_address+0x800+0x10); |
| 1254 | cmd = apust.space->read_dword(apust.gpdsp_address + 0x800 + 0x10); |
| 4680 | 1255 | if (cmd == 3) |
| 4681 | | apust.space->write_dword(apust.gpdsp_address+0x800+0x10,0); |
| 1256 | apust.space->write_dword(apust.gpdsp_address + 0x800 + 0x10, 0); |
| 4682 | 1257 | /*else |
| 4683 | | logerror("Audio_APU: unexpected value at address %d\n",apust.gpdsp_address+0x800+0x10);*/ |
| 1258 | logerror("Audio_APU: unexpected value at address %d\n",apust.gpdsp_address+0x800+0x10);*/ |
| 4684 | 1259 | for (b = 0; b < 4; b++) { |
| 4685 | 1260 | bv = 1; |
| 4686 | 1261 | for (bb = 0; bb < 64; bb++) { |
| r242208 | r242209 | |
| 4704 | 1279 | static UINT32 dummy_pci_r(device_t *busdevice, device_t *device, int function, int reg, UINT32 mem_mask) |
| 4705 | 1280 | { |
| 4706 | 1281 | #ifdef LOG_PCI |
| 4707 | | // logerror(" bus:0 function:%d register:%d mask:%08X\n",function,reg,mem_mask); |
| 1282 | // logerror(" bus:0 function:%d register:%d mask:%08X\n",function,reg,mem_mask); |
| 4708 | 1283 | #endif |
| 4709 | 1284 | return 0; |
| 4710 | 1285 | } |
| r242208 | r242209 | |
| 4712 | 1287 | static void dummy_pci_w(device_t *busdevice, device_t *device, int function, int reg, UINT32 data, UINT32 mem_mask) |
| 4713 | 1288 | { |
| 4714 | 1289 | #ifdef LOG_PCI |
| 4715 | | if (reg >= 16) logerror(" bus:0 function:%d register:%d data:%08X mask:%08X\n",function,reg,data,mem_mask); |
| 1290 | if (reg >= 16) logerror(" bus:0 function:%d register:%d data:%08X mask:%08X\n", function, reg, data, mem_mask); |
| 4716 | 1291 | #endif |
| 4717 | 1292 | } |
| 4718 | 1293 | |
| 4719 | | READ32_MEMBER( chihiro_state::dummy_r ) |
| 1294 | READ32_MEMBER(chihiro_state::dummy_r) |
| 4720 | 1295 | { |
| 4721 | 1296 | return 0; |
| 4722 | 1297 | } |
| 4723 | 1298 | |
| 4724 | | WRITE32_MEMBER( chihiro_state::dummy_w ) |
| 1299 | WRITE32_MEMBER(chihiro_state::dummy_w) |
| 4725 | 1300 | { |
| 4726 | 1301 | } |
| 4727 | 1302 | |
| r242208 | r242209 | |
| 4767 | 1342 | void ide_baseboard_device::device_start() |
| 4768 | 1343 | { |
| 4769 | 1344 | ata_mass_storage_device::device_start(); |
| 4770 | | chihirosystem=machine().driver_data<chihiro_state>(); |
| 1345 | chihirosystem = machine().driver_data<chihiro_state>(); |
| 4771 | 1346 | // savestates |
| 4772 | 1347 | save_item(NAME(read_buffer)); |
| 4773 | 1348 | save_item(NAME(write_buffer)); |
| r242208 | r242209 | |
| 4781 | 1356 | { |
| 4782 | 1357 | if (!m_can_identify_device) |
| 4783 | 1358 | { |
| 4784 | | m_num_cylinders=65535; |
| 4785 | | m_num_sectors=255; |
| 4786 | | m_num_heads=255; |
| 1359 | m_num_cylinders = 65535; |
| 1360 | m_num_sectors = 255; |
| 1361 | m_num_heads = 255; |
| 4787 | 1362 | ide_build_identify_device(); |
| 4788 | 1363 | m_can_identify_device = 1; |
| 4789 | 1364 | } |
| r242208 | r242209 | |
| 4798 | 1373 | |
| 4799 | 1374 | /* |
| 4800 | 1375 | It assumes there are 4 "partitions", the size of the first one depends on bits 3-0 of io port 40f4: |
| 4801 | | Value Size lba |
| 4802 | | 0 0x40000-0x8000 |
| 4803 | | ... |
| 4804 | | 4 0x400000-0x8000 |
| 1376 | Value Size lba |
| 1377 | 0 0x40000-0x8000 |
| 1378 | ... |
| 1379 | 4 0x400000-0x8000 |
| 4805 | 1380 | The size of the second one is always 0x8000 sectors, and is used as a special communication area |
| 4806 | 1381 | This is a list of the partitions in the minimum size case: |
| 4807 | | Name Start lba Size lba Size |
| 4808 | | \??\mbfs: 0x0 0x38000 112MB |
| 4809 | | \??\mbcom: 0x38000 0x8000 16MB |
| 4810 | | \??\mbrom0: 0x8000000 0x800 1MB |
| 4811 | | \??\mbrom1: 0x8000800 0x800 1MB |
| 1382 | Name Start lba Size lba Size |
| 1383 | \??\mbfs: 0x0 0x38000 112MB |
| 1384 | \??\mbcom: 0x38000 0x8000 16MB |
| 1385 | \??\mbrom0: 0x8000000 0x800 1MB |
| 1386 | \??\mbrom1: 0x8000800 0x800 1MB |
| 4812 | 1387 | This is a list of the partitions in the maximum size case: |
| 4813 | | Name Start lba Size lba Size |
| 4814 | | \??\mbfs: 0x0 0x3f8000 2032MB |
| 4815 | | \??\mbcom: 0x3f8000 0x8000 16MB |
| 4816 | | \??\mbrom0: 0x8000000 0x800 1MB |
| 4817 | | \??\mbrom1: 0x8000800 0x800 1MB |
| 1388 | Name Start lba Size lba Size |
| 1389 | \??\mbfs: 0x0 0x3f8000 2032MB |
| 1390 | \??\mbcom: 0x3f8000 0x8000 16MB |
| 1391 | \??\mbrom0: 0x8000000 0x800 1MB |
| 1392 | \??\mbrom1: 0x8000800 0x800 1MB |
| 4818 | 1393 | */ |
| 4819 | | logerror("baseboard: read sector lba %08x\n",lba); |
| 1394 | logerror("baseboard: read sector lba %08x\n", lba); |
| 4820 | 1395 | if (lba >= 0x08000000) { |
| 4821 | | off=(lba&0x7ff)*512; |
| 4822 | | data=memregion(":others")->base(); |
| 4823 | | memcpy(buffer,data+off,512); |
| 1396 | off = (lba & 0x7ff) * 512; |
| 1397 | data = memregion(":others")->base(); |
| 1398 | memcpy(buffer, data + off, 512); |
| 4824 | 1399 | return 1; |
| 4825 | 1400 | } |
| 4826 | 1401 | if (lba >= 0xf8000) { |
| 4827 | | memset(buffer,0,512); |
| 4828 | | lba=lba-0xf8000; |
| 1402 | memset(buffer, 0, 512); |
| 1403 | lba = lba - 0xf8000; |
| 4829 | 1404 | if (lba == 0x4800) |
| 4830 | | memcpy(buffer,read_buffer,0x20); |
| 1405 | memcpy(buffer, read_buffer, 0x20); |
| 4831 | 1406 | else if (lba == 0x4801) |
| 4832 | | memcpy(buffer,write_buffer,0x20); |
| 1407 | memcpy(buffer, write_buffer, 0x20); |
| 4833 | 1408 | return 1; |
| 4834 | 1409 | } |
| 4835 | 1410 | // in a type 1 chihiro this gets data from the dimm board memory |
| 4836 | | data=chihirosystem->baseboard_ide_dimmboard(lba); |
| 1411 | data = chihirosystem->baseboard_ide_dimmboard(lba); |
| 4837 | 1412 | if (data != NULL) |
| 4838 | | memcpy(buffer,data,512); |
| 1413 | memcpy(buffer, data, 512); |
| 4839 | 1414 | return 1; |
| 4840 | 1415 | } |
| 4841 | 1416 | |
| 4842 | 1417 | int ide_baseboard_device::write_sector(UINT32 lba, const void *buffer) |
| 4843 | 1418 | { |
| 4844 | | logerror("baseboard: write sector lba %08x\n",lba); |
| 1419 | logerror("baseboard: write sector lba %08x\n", lba); |
| 4845 | 1420 | if (lba >= 0xf8000) { |
| 4846 | | lba=lba-0xf8000; |
| 1421 | lba = lba - 0xf8000; |
| 4847 | 1422 | if (lba == 0x4800) |
| 4848 | | memcpy(read_buffer,buffer,0x20); |
| 1423 | memcpy(read_buffer, buffer, 0x20); |
| 4849 | 1424 | else if (lba == 0x4801) { |
| 4850 | | memcpy(write_buffer,buffer,0x20); |
| 1425 | memcpy(write_buffer, buffer, 0x20); |
| 4851 | 1426 | // call chihiro driver |
| 4852 | | chihirosystem->baseboard_ide_event(3,read_buffer,write_buffer); |
| 1427 | chihirosystem->baseboard_ide_event(3, read_buffer, write_buffer); |
| 4853 | 1428 | } |
| 4854 | 1429 | } |
| 4855 | 1430 | return 1; |
| r242208 | r242209 | |
| 4859 | 1434 | * Chihiro Type 1 baseboard |
| 4860 | 1435 | */ |
| 4861 | 1436 | |
| 4862 | | void chihiro_state::dword_write_le(UINT8 *addr,UINT32 d) |
| 1437 | void chihiro_state::dword_write_le(UINT8 *addr, UINT32 d) |
| 4863 | 1438 | { |
| 4864 | | addr[0]=d & 255; |
| 4865 | | addr[1]=(d >> 8) & 255; |
| 4866 | | addr[2]=(d >> 16) & 255; |
| 4867 | | addr[3]=(d >> 24) & 255; |
| 1439 | addr[0] = d & 255; |
| 1440 | addr[1] = (d >> 8) & 255; |
| 1441 | addr[2] = (d >> 16) & 255; |
| 1442 | addr[3] = (d >> 24) & 255; |
| 4868 | 1443 | } |
| 4869 | 1444 | |
| 4870 | | void chihiro_state::word_write_le(UINT8 *addr,UINT16 d) |
| 1445 | void chihiro_state::word_write_le(UINT8 *addr, UINT16 d) |
| 4871 | 1446 | { |
| 4872 | | addr[0]=d & 255; |
| 4873 | | addr[1]=(d >> 8) & 255; |
| 1447 | addr[0] = d & 255; |
| 1448 | addr[1] = (d >> 8) & 255; |
| 4874 | 1449 | } |
| 4875 | 1450 | |
| 4876 | | void chihiro_state::baseboard_ide_event(int type,UINT8 *read_buffer,UINT8 *write_buffer) |
| 1451 | void chihiro_state::baseboard_ide_event(int type, UINT8 *read_buffer, UINT8 *write_buffer) |
| 4877 | 1452 | { |
| 4878 | 1453 | int c; |
| 4879 | 1454 | |
| r242208 | r242209 | |
| 4881 | 1456 | return; |
| 4882 | 1457 | #ifdef LOG_BASEBOARD |
| 4883 | 1458 | logerror("Baseboard sector command:\n"); |
| 4884 | | for (int a=0;a < 32;a++) |
| 4885 | | logerror(" %02X",write_buffer[a]); |
| 1459 | for (int a = 0; a < 32; a++) |
| 1460 | logerror(" %02X", write_buffer[a]); |
| 4886 | 1461 | logerror("\n"); |
| 4887 | 1462 | #endif |
| 4888 | 1463 | // response |
| 4889 | 1464 | // second word 8001 (8000+counter), first word=first word of written data (command ?), second dword ? |
| 4890 | | read_buffer[0]=write_buffer[0]; |
| 4891 | | read_buffer[1]=write_buffer[1]; |
| 4892 | | read_buffer[2]=0x01; // write_buffer[2]; |
| 4893 | | read_buffer[3]=0x80; // write_buffer[3] | 0x80; |
| 4894 | | c=write_buffer[2]+(write_buffer[3] << 8); // 0001 0101 0103 |
| 1465 | read_buffer[0] = write_buffer[0]; |
| 1466 | read_buffer[1] = write_buffer[1]; |
| 1467 | read_buffer[2] = 0x01; // write_buffer[2]; |
| 1468 | read_buffer[3] = 0x80; // write_buffer[3] | 0x80; |
| 1469 | c = write_buffer[2] + (write_buffer[3] << 8); // 0001 0101 0103 |
| 4895 | 1470 | switch (c) |
| 4896 | 1471 | { |
| 4897 | | case 0x0001: |
| 4898 | | // second dword |
| 4899 | | dword_write_le(read_buffer+4,0x00f00000); // ? |
| 4900 | | break; |
| 4901 | | case 0x0100: |
| 4902 | | // second dword third dword |
| 4903 | | dword_write_le(read_buffer+4,5); // game data loading phase |
| 4904 | | dword_write_le(read_buffer+8,0); // completion % |
| 4905 | | break; |
| 4906 | | case 0x0101: |
| 4907 | | // third word fourth word |
| 4908 | | word_write_le(read_buffer+4,0xca); // ? |
| 4909 | | word_write_le(read_buffer+6,0xcb); // ? |
| 4910 | | break; |
| 4911 | | case 0x0102: |
| 4912 | | // second dword |
| 4913 | | dword_write_le(read_buffer+4,0); // bit 16 develop. mode |
| 4914 | | break; |
| 4915 | | case 0x0103: |
| 4916 | | // dwords 1 3 4 |
| 4917 | | memcpy(read_buffer+4,"-abc-abc12345678",16); // ? |
| 4918 | | break; |
| 1472 | case 0x0001: |
| 1473 | // second dword |
| 1474 | dword_write_le(read_buffer + 4, 0x00f00000); // ? |
| 1475 | break; |
| 1476 | case 0x0100: |
| 1477 | // second dword third dword |
| 1478 | dword_write_le(read_buffer + 4, 5); // game data loading phase |
| 1479 | dword_write_le(read_buffer + 8, 0); // completion % |
| 1480 | break; |
| 1481 | case 0x0101: |
| 1482 | // third word fourth word |
| 1483 | word_write_le(read_buffer + 4, 0xca); // ? |
| 1484 | word_write_le(read_buffer + 6, 0xcb); // ? |
| 1485 | break; |
| 1486 | case 0x0102: |
| 1487 | // second dword |
| 1488 | dword_write_le(read_buffer + 4, 0); // bit 16 develop. mode |
| 1489 | break; |
| 1490 | case 0x0103: |
| 1491 | // dwords 1 3 4 |
| 1492 | memcpy(read_buffer + 4, "-abc-abc12345678", 16); // ? |
| 1493 | break; |
| 4919 | 1494 | } |
| 4920 | 1495 | // clear |
| 4921 | | write_buffer[0]=write_buffer[1]=write_buffer[2]=write_buffer[3]=0; |
| 1496 | write_buffer[0] = write_buffer[1] = write_buffer[2] = write_buffer[3] = 0; |
| 4922 | 1497 | // irq 10 active |
| 4923 | 1498 | chihiro_devs.pic8259_2->ir2_w(1); |
| 4924 | 1499 | } |
| r242208 | r242209 | |
| 4927 | 1502 | { |
| 4928 | 1503 | // return pointer to memory containing decrypted gdrom data (contains an image of a fatx partition) |
| 4929 | 1504 | if (chihiro_devs.dimmboard != NULL) |
| 4930 | | return dimm_board_memory+lba*512; |
| 1505 | return dimm_board_memory + lba * 512; |
| 4931 | 1506 | return NULL; |
| 4932 | 1507 | } |
| 4933 | 1508 | |
| r242208 | r242209 | |
| 4942 | 1517 | |
| 4943 | 1518 | READ8_MEMBER(chihiro_state::get_slave_ack) |
| 4944 | 1519 | { |
| 4945 | | if (offset==2) { // IRQ = 2 |
| 1520 | if (offset == 2) { // IRQ = 2 |
| 4946 | 1521 | return chihiro_devs.pic8259_2->acknowledge(); |
| 4947 | 1522 | } |
| 4948 | 1523 | return 0x00; |
| r242208 | r242209 | |
| 4952 | 1527 | { |
| 4953 | 1528 | int r = 0; |
| 4954 | 1529 | r = chihiro_devs.pic8259_2->acknowledge(); |
| 4955 | | if (r==0) |
| 1530 | if (r == 0) |
| 4956 | 1531 | { |
| 4957 | 1532 | r = chihiro_devs.pic8259_1->acknowledge(); |
| 4958 | 1533 | } |
| 4959 | 1534 | if (debug_irq_active) |
| 4960 | | debug_generate_irq(debug_irq_number,false); |
| 1535 | debug_generate_irq(debug_irq_number, false); |
| 4961 | 1536 | return r; |
| 4962 | 1537 | } |
| 4963 | 1538 | |
| 4964 | 1539 | WRITE_LINE_MEMBER(chihiro_state::chihiro_pit8254_out0_changed) |
| 4965 | 1540 | { |
| 4966 | | if ( chihiro_devs.pic8259_1 ) |
| 1541 | if (chihiro_devs.pic8259_1) |
| 4967 | 1542 | { |
| 4968 | 1543 | chihiro_devs.pic8259_1->ir0_w(state); |
| 4969 | 1544 | } |
| r242208 | r242209 | |
| 4978 | 1553 | * SMbus devices |
| 4979 | 1554 | */ |
| 4980 | 1555 | |
| 4981 | | int smbus_callback_pic16lc(chihiro_state &chs,int command,int rw,int data) |
| 1556 | int smbus_callback_pic16lc(chihiro_state &chs, int command, int rw, int data) |
| 4982 | 1557 | { |
| 4983 | 1558 | return chs.smbus_pic16lc(command, rw, data); |
| 4984 | 1559 | } |
| 4985 | 1560 | |
| 4986 | | int chihiro_state::smbus_pic16lc(int command,int rw,int data) |
| 1561 | int chihiro_state::smbus_pic16lc(int command, int rw, int data) |
| 4987 | 1562 | { |
| 4988 | 1563 | if (rw == 1) { // read |
| 4989 | 1564 | if (command == 0) { |
| 4990 | 1565 | if (pic16lc_buffer[0] == 'D') |
| 4991 | | pic16lc_buffer[0]='X'; |
| 1566 | pic16lc_buffer[0] = 'X'; |
| 4992 | 1567 | else if (pic16lc_buffer[0] == 'X') |
| 4993 | | pic16lc_buffer[0]='B'; |
| 1568 | pic16lc_buffer[0] = 'B'; |
| 4994 | 1569 | else if (pic16lc_buffer[0] == 'B') |
| 4995 | | pic16lc_buffer[0]='D'; |
| 1570 | pic16lc_buffer[0] = 'D'; |
| 4996 | 1571 | } |
| 4997 | | logerror("pic16lc: %d %d %d\n",command,rw,pic16lc_buffer[command]); |
| 1572 | logerror("pic16lc: %d %d %d\n", command, rw, pic16lc_buffer[command]); |
| 4998 | 1573 | return pic16lc_buffer[command]; |
| 4999 | | } else |
| 1574 | } |
| 1575 | else |
| 5000 | 1576 | if (command == 0) |
| 5001 | | pic16lc_buffer[0]='B'; |
| 1577 | pic16lc_buffer[0] = 'B'; |
| 5002 | 1578 | else |
| 5003 | | pic16lc_buffer[command]=(UINT8)data; |
| 5004 | | logerror("pic16lc: %d %d %d\n",command,rw,data); |
| 1579 | pic16lc_buffer[command] = (UINT8)data; |
| 1580 | logerror("pic16lc: %d %d %d\n", command, rw, data); |
| 5005 | 1581 | return 0; |
| 5006 | 1582 | } |
| 5007 | 1583 | |
| 5008 | | int smbus_callback_cx25871(chihiro_state &chs,int command,int rw,int data) |
| 1584 | int smbus_callback_cx25871(chihiro_state &chs, int command, int rw, int data) |
| 5009 | 1585 | { |
| 5010 | 1586 | return chs.smbus_cx25871(command, rw, data); |
| 5011 | 1587 | } |
| 5012 | 1588 | |
| 5013 | | int chihiro_state::smbus_cx25871(int command,int rw,int data) |
| 1589 | int chihiro_state::smbus_cx25871(int command, int rw, int data) |
| 5014 | 1590 | { |
| 5015 | | logerror("cx25871: %d %d %d\n",command,rw,data); |
| 1591 | logerror("cx25871: %d %d %d\n", command, rw, data); |
| 5016 | 1592 | return 0; |
| 5017 | 1593 | } |
| 5018 | 1594 | |
| r242208 | r242209 | |
| 5023 | 1599 | 0x4F,0x6E,0x6C,0x69,0x6E,0x65,0x6B,0x65,0x79,0x69,0x6E,0x76,0x61,0x6C,0x69,0x64,0x00,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF, |
| 5024 | 1600 | 0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; |
| 5025 | 1601 | |
| 5026 | | int smbus_callback_eeprom(chihiro_state &chs,int command,int rw,int data) |
| 1602 | int smbus_callback_eeprom(chihiro_state &chs, int command, int rw, int data) |
| 5027 | 1603 | { |
| 5028 | 1604 | return chs.smbus_eeprom(command, rw, data); |
| 5029 | 1605 | } |
| 5030 | 1606 | |
| 5031 | | int chihiro_state::smbus_eeprom(int command,int rw,int data) |
| 1607 | int chihiro_state::smbus_eeprom(int command, int rw, int data) |
| 5032 | 1608 | { |
| 5033 | 1609 | if (command >= 112) |
| 5034 | 1610 | return 0; |
| r242208 | r242209 | |
| 5037 | 1613 | // hack to avoid hanging if eeprom contents are not correct |
| 5038 | 1614 | // this would need dumping the serial eeprom on the xbox board |
| 5039 | 1615 | if (command == 0) { |
| 5040 | | m_maincpu->space(0).write_byte(0x3b744,0x90); |
| 5041 | | m_maincpu->space(0).write_byte(0x3b745,0x90); |
| 5042 | | m_maincpu->space(0).write_byte(0x3b766,0xc9); |
| 5043 | | m_maincpu->space(0).write_byte(0x3b767,0xc3); |
| 1616 | m_maincpu->space(0).write_byte(0x3b744, 0x90); |
| 1617 | m_maincpu->space(0).write_byte(0x3b745, 0x90); |
| 1618 | m_maincpu->space(0).write_byte(0x3b766, 0xc9); |
| 1619 | m_maincpu->space(0).write_byte(0x3b767, 0xc3); |
| 5044 | 1620 | } |
| 5045 | | data = dummyeeprom[command]+dummyeeprom[command+1]*256; |
| 5046 | | logerror("eeprom: %d %d %d\n",command,rw,data); |
| 1621 | data = dummyeeprom[command] + dummyeeprom[command + 1] * 256; |
| 1622 | logerror("eeprom: %d %d %d\n", command, rw, data); |
| 5047 | 1623 | return data; |
| 5048 | 1624 | } |
| 5049 | | logerror("eeprom: %d %d %d\n",command,rw,data); |
| 5050 | | dummyeeprom[command]=data; |
| 1625 | logerror("eeprom: %d %d %d\n", command, rw, data); |
| 1626 | dummyeeprom[command] = data; |
| 5051 | 1627 | return 0; |
| 5052 | 1628 | } |
| 5053 | 1629 | |
| r242208 | r242209 | |
| 5055 | 1631 | * SMbus controller |
| 5056 | 1632 | */ |
| 5057 | 1633 | |
| 5058 | | void chihiro_state::smbus_register_device(int address,int (*handler)(chihiro_state &chs,int command,int rw,int data)) |
| 1634 | void chihiro_state::smbus_register_device(int address, int(*handler)(chihiro_state &chs, int command, int rw, int data)) |
| 5059 | 1635 | { |
| 5060 | 1636 | if (address < 128) |
| 5061 | | smbusst.devices[address]=handler; |
| 1637 | smbusst.devices[address] = handler; |
| 5062 | 1638 | } |
| 5063 | 1639 | |
| 5064 | | READ32_MEMBER( chihiro_state::smbus_r ) |
| 1640 | READ32_MEMBER(chihiro_state::smbus_r) |
| 5065 | 1641 | { |
| 5066 | 1642 | if ((offset == 0) && (mem_mask == 0xff)) // 0 smbus status |
| 5067 | 1643 | smbusst.words[offset] = (smbusst.words[offset] & ~mem_mask) | ((smbusst.status << 0) & mem_mask); |
| r242208 | r242209 | |
| 5070 | 1646 | return smbusst.words[offset]; |
| 5071 | 1647 | } |
| 5072 | 1648 | |
| 5073 | | WRITE32_MEMBER( chihiro_state::smbus_w ) |
| 1649 | WRITE32_MEMBER(chihiro_state::smbus_w) |
| 5074 | 1650 | { |
| 5075 | 1651 | COMBINE_DATA(smbusst.words); |
| 5076 | 1652 | if ((offset == 0) && (mem_mask == 0xff)) // 0 smbus status |
| r242208 | r242209 | |
| 5081 | 1657 | } |
| 5082 | 1658 | if ((offset == 0) && (mem_mask == 0xff0000)) // 2 smbus control |
| 5083 | 1659 | { |
| 5084 | | data=data>>16; |
| 1660 | data = data >> 16; |
| 5085 | 1661 | smbusst.control = data; |
| 5086 | 1662 | int cycletype = smbusst.control & 7; |
| 5087 | 1663 | if (smbusst.control & 8) { // start |
| r242208 | r242209 | |
| 5089 | 1665 | { |
| 5090 | 1666 | if (smbusst.devices[smbusst.address]) |
| 5091 | 1667 | if (smbusst.rw == 0) |
| 5092 | | smbusst.devices[smbusst.address](*this,smbusst.command,smbusst.rw,smbusst.data); |
| 1668 | smbusst.devices[smbusst.address](*this, smbusst.command, smbusst.rw, smbusst.data); |
| 5093 | 1669 | else |
| 5094 | | smbusst.data=smbusst.devices[smbusst.address](*this,smbusst.command,smbusst.rw,smbusst.data); |
| 1670 | smbusst.data = smbusst.devices[smbusst.address](*this, smbusst.command, smbusst.rw, smbusst.data); |
| 5095 | 1671 | else |
| 5096 | | logerror("SMBUS: access to missing device at address %d\n",smbusst.address); |
| 1672 | logerror("SMBUS: access to missing device at address %d\n", smbusst.address); |
| 5097 | 1673 | smbusst.status |= 0x10; |
| 5098 | 1674 | if (smbusst.control & 0x10) |
| 5099 | 1675 | { |
| r242208 | r242209 | |
| 5109 | 1685 | } |
| 5110 | 1686 | if ((offset == 1) && ((mem_mask == 0x00ff0000) || (mem_mask == 0xffff0000))) // 6 smbus data |
| 5111 | 1687 | { |
| 5112 | | data=data>>16; |
| 1688 | data = data >> 16; |
| 5113 | 1689 | smbusst.data = data; |
| 5114 | 1690 | } |
| 5115 | 1691 | if ((offset == 2) && (mem_mask == 0xff)) // 8 smbus command |
| 5116 | 1692 | smbusst.command = data; |
| 5117 | 1693 | } |
| 5118 | 1694 | |
| 5119 | | READ32_MEMBER( chihiro_state::mediaboard_r ) |
| 1695 | READ32_MEMBER(chihiro_state::mediaboard_r) |
| 5120 | 1696 | { |
| 5121 | 1697 | UINT32 r; |
| 5122 | 1698 | |
| 5123 | | logerror("I/O port read %04x mask %08X\n",offset*4+0x4000,mem_mask); |
| 5124 | | r=0; |
| 1699 | logerror("I/O port read %04x mask %08X\n", offset * 4 + 0x4000, mem_mask); |
| 1700 | r = 0; |
| 5125 | 1701 | if ((offset == 7) && ACCESSING_BITS_16_31) |
| 5126 | | r=0x10000000; |
| 1702 | r = 0x10000000; |
| 5127 | 1703 | if ((offset == 8) && ACCESSING_BITS_0_15) |
| 5128 | | r=0x000000a0; |
| 1704 | r = 0x000000a0; |
| 5129 | 1705 | if ((offset == 8) && ACCESSING_BITS_16_31) |
| 5130 | | r=0x42580000; |
| 1706 | r = 0x42580000; |
| 5131 | 1707 | if ((offset == 9) && ACCESSING_BITS_0_15) |
| 5132 | | r=0x00004d41; |
| 1708 | r = 0x00004d41; |
| 5133 | 1709 | if ((offset == 0x3c) && ACCESSING_BITS_0_15) |
| 5134 | | r=0x00000000; // bits 15-0 0 if media board present |
| 1710 | r = 0x00000000; // bits 15-0 0 if media board present |
| 5135 | 1711 | if ((offset == 0x3d) && ACCESSING_BITS_0_15) |
| 5136 | | r=0x00000002; // bits 3-0 size of dimm board memory. Must be 2 |
| 1712 | r = 0x00000002; // bits 3-0 size of dimm board memory. Must be 2 |
| 5137 | 1713 | return r; |
| 5138 | 1714 | } |
| 5139 | 1715 | |
| 5140 | | WRITE32_MEMBER( chihiro_state::mediaboard_w ) |
| 1716 | WRITE32_MEMBER(chihiro_state::mediaboard_w) |
| 5141 | 1717 | { |
| 5142 | | logerror("I/O port write %04x mask %08X value %08X\n",offset*4+0x4000,mem_mask,data); |
| 1718 | logerror("I/O port write %04x mask %08X value %08X\n", offset * 4 + 0x4000, mem_mask, data); |
| 5143 | 1719 | // irq 10 |
| 5144 | 1720 | if ((offset == 0x38) && ACCESSING_BITS_8_15) |
| 5145 | 1721 | chihiro_devs.pic8259_2->ir2_w(0); |
| 5146 | 1722 | } |
| 5147 | 1723 | |
| 5148 | | static ADDRESS_MAP_START( xbox_map, AS_PROGRAM, 32, chihiro_state ) |
| 1724 | static ADDRESS_MAP_START(xbox_map, AS_PROGRAM, 32, chihiro_state) |
| 5149 | 1725 | AM_RANGE(0x00000000, 0x07ffffff) AM_RAM // 128 megabytes |
| 5150 | 1726 | AM_RANGE(0xf0000000, 0xf0ffffff) AM_RAM |
| 5151 | 1727 | AM_RANGE(0xfd000000, 0xfdffffff) AM_RAM AM_READWRITE(geforce_r, geforce_w) |
| r242208 | r242209 | |
| 5155 | 1731 | AM_RANGE(0xff000000, 0xffffffff) AM_ROM AM_REGION("bios", 0) AM_MIRROR(0x00f80000) |
| 5156 | 1732 | ADDRESS_MAP_END |
| 5157 | 1733 | |
| 5158 | | static ADDRESS_MAP_START(xbox_map_io, AS_IO, 32, chihiro_state ) |
| 1734 | static ADDRESS_MAP_START(xbox_map_io, AS_IO, 32, chihiro_state) |
| 5159 | 1735 | AM_RANGE(0x0020, 0x0023) AM_DEVREADWRITE8("pic8259_1", pic8259_device, read, write, 0xffffffff) |
| 5160 | 1736 | AM_RANGE(0x0040, 0x0043) AM_DEVREADWRITE8("pit8254", pit8254_device, read, write, 0xffffffff) |
| 5161 | 1737 | AM_RANGE(0x00a0, 0x00a3) AM_DEVREADWRITE8("pic8259_2", pic8259_device, read, write, 0xffffffff) |
| r242208 | r242209 | |
| 5167 | 1743 | AM_RANGE(0xff60, 0xff67) AM_DEVREADWRITE("ide", bus_master_ide_controller_device, bmdma_r, bmdma_w) |
| 5168 | 1744 | ADDRESS_MAP_END |
| 5169 | 1745 | |
| 5170 | | static INPUT_PORTS_START( chihiro ) |
| 1746 | static INPUT_PORTS_START(chihiro) |
| 5171 | 1747 | INPUT_PORTS_END |
| 5172 | 1748 | |
| 5173 | 1749 | void chihiro_state::machine_start() |
| 5174 | 1750 | { |
| 5175 | | nvidia_nv2a=auto_alloc(machine(), nv2a_renderer(machine())); |
| 5176 | | memset(pic16lc_buffer,0,sizeof(pic16lc_buffer)); |
| 5177 | | pic16lc_buffer[0]='B'; |
| 5178 | | pic16lc_buffer[4]=0; // A/V connector, 2=vga |
| 5179 | | smbus_register_device(0x10,smbus_callback_pic16lc); |
| 5180 | | smbus_register_device(0x45,smbus_callback_cx25871); |
| 5181 | | smbus_register_device(0x54,smbus_callback_eeprom); |
| 5182 | | chihiro_devs.pic8259_1 = machine().device<pic8259_device>( "pic8259_1" ); |
| 5183 | | chihiro_devs.pic8259_2 = machine().device<pic8259_device>( "pic8259_2" ); |
| 5184 | | chihiro_devs.ide = machine().device<bus_master_ide_controller_device>( "ide" ); |
| 5185 | | chihiro_devs.dimmboard=machine().device<naomi_gdrom_board>("rom_board"); |
| 1751 | nvidia_nv2a = auto_alloc(machine(), nv2a_renderer(machine())); |
| 1752 | memset(pic16lc_buffer, 0, sizeof(pic16lc_buffer)); |
| 1753 | pic16lc_buffer[0] = 'B'; |
| 1754 | pic16lc_buffer[4] = 0; // A/V connector, 2=vga |
| 1755 | smbus_register_device(0x10, smbus_callback_pic16lc); |
| 1756 | smbus_register_device(0x45, smbus_callback_cx25871); |
| 1757 | smbus_register_device(0x54, smbus_callback_eeprom); |
| 1758 | chihiro_devs.pic8259_1 = machine().device<pic8259_device>("pic8259_1"); |
| 1759 | chihiro_devs.pic8259_2 = machine().device<pic8259_device>("pic8259_2"); |
| 1760 | chihiro_devs.ide = machine().device<bus_master_ide_controller_device>("ide"); |
| 1761 | chihiro_devs.dimmboard = machine().device<naomi_gdrom_board>("rom_board"); |
| 5186 | 1762 | if (chihiro_devs.dimmboard != NULL) { |
| 5187 | | dimm_board_memory=chihiro_devs.dimmboard->memory(dimm_board_memory_size); |
| 1763 | dimm_board_memory = chihiro_devs.dimmboard->memory(dimm_board_memory_size); |
| 5188 | 1764 | } |
| 5189 | 1765 | memset(apust.memory, 0, sizeof(apust.memory)); |
| 5190 | 1766 | memset(apust.voices_heap_blockaddr, 0, sizeof(apust.voices_heap_blockaddr)); |
| r242208 | r242209 | |
| 5194 | 1770 | memset(apust.voices_position_end, 0, sizeof(apust.voices_position_end)); |
| 5195 | 1771 | memset(apust.voices_position_increment, 0, sizeof(apust.voices_position_increment)); |
| 5196 | 1772 | apust.space = &m_maincpu->space(); |
| 5197 | | apust.timer=machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(chihiro_state::audio_apu_timer),this),(void *)"APU Timer"); |
| 1773 | apust.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(chihiro_state::audio_apu_timer), this), (void *)"APU Timer"); |
| 5198 | 1774 | apust.timer->enable(false); |
| 5199 | 1775 | if (machine().debug_flags & DEBUG_FLAG_ENABLED) |
| 5200 | | debug_console_register_command(machine(),"chihiro",CMDFLAG_NONE,0,1,4,chihiro_debug_commands); |
| 5201 | | usbhack_counter=0; |
| 1776 | debug_console_register_command(machine(), "chihiro", CMDFLAG_NONE, 0, 1, 4, chihiro_debug_commands); |
| 1777 | usbhack_counter = 0; |
| 5202 | 1778 | // savestates |
| 5203 | 1779 | save_item(NAME(debug_irq_active)); |
| 5204 | 1780 | save_item(NAME(debug_irq_number)); |
| r242208 | r242209 | |
| 5218 | 1794 | SLOT_INTERFACE("bb", IDE_BASEBOARD) |
| 5219 | 1795 | SLOT_INTERFACE_END |
| 5220 | 1796 | |
| 5221 | | static MACHINE_CONFIG_START( chihiro_base, chihiro_state ) |
| 1797 | static MACHINE_CONFIG_START(chihiro_base, chihiro_state) |
| 5222 | 1798 | |
| 5223 | 1799 | /* basic machine hardware */ |
| 5224 | 1800 | MCFG_CPU_ADD("maincpu", PENTIUM3, 733333333) /* Wrong! family 6 model 8 stepping 10 */ |
| 5225 | 1801 | MCFG_CPU_PROGRAM_MAP(xbox_map) |
| 5226 | 1802 | MCFG_CPU_IO_MAP(xbox_map_io) |
| 5227 | | MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(chihiro_state,irq_callback) |
| 1803 | MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(chihiro_state, irq_callback) |
| 5228 | 1804 | |
| 5229 | 1805 | MCFG_QUANTUM_TIME(attotime::from_hz(6000)) |
| 5230 | 1806 | |
| r242208 | r242209 | |
| 5241 | 1817 | MCFG_PCI_BUS_LEGACY_ADD("agpbus", 1) |
| 5242 | 1818 | MCFG_PCI_BUS_LEGACY_SIBLING("pcibus") |
| 5243 | 1819 | MCFG_PCI_BUS_LEGACY_DEVICE(0, "NV2A GeForce 3MX Integrated GPU/Northbridge", geforce_pci_r, geforce_pci_w) |
| 5244 | | MCFG_PIC8259_ADD( "pic8259_1", WRITELINE(chihiro_state, chihiro_pic8259_1_set_int_line), VCC, READ8(chihiro_state,get_slave_ack) ) |
| 5245 | | MCFG_PIC8259_ADD( "pic8259_2", DEVWRITELINE("pic8259_1", pic8259_device, ir2_w), GND, NULL ) |
| 1820 | MCFG_PIC8259_ADD("pic8259_1", WRITELINE(chihiro_state, chihiro_pic8259_1_set_int_line), VCC, READ8(chihiro_state, get_slave_ack)) |
| 1821 | MCFG_PIC8259_ADD("pic8259_2", DEVWRITELINE("pic8259_1", pic8259_device, ir2_w), GND, NULL) |
| 5246 | 1822 | |
| 5247 | 1823 | MCFG_DEVICE_ADD("pit8254", PIT8254, 0) |
| 5248 | 1824 | MCFG_PIT8253_CLK0(1125000) /* heartbeat IRQ */ |
| r242208 | r242209 | |
| 5251 | 1827 | MCFG_PIT8253_CLK2(1125000) /* (unused) pio port c pin 4, and speaker polling enough */ |
| 5252 | 1828 | MCFG_PIT8253_OUT2_HANDLER(WRITELINE(chihiro_state, chihiro_pit8254_out2_changed)) |
| 5253 | 1829 | |
| 5254 | | MCFG_BUS_MASTER_IDE_CONTROLLER_ADD( "ide", ide_baseboard, NULL, "bb", true) |
| 1830 | MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide", ide_baseboard, NULL, "bb", true) |
| 5255 | 1831 | MCFG_ATA_INTERFACE_IRQ_HANDLER(DEVWRITELINE("pic8259_2", pic8259_device, ir6_w)) |
| 5256 | 1832 | MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE("maincpu", AS_PROGRAM) |
| 5257 | 1833 | |
| r242208 | r242209 | |
| 5261 | 1837 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ |
| 5262 | 1838 | MCFG_SCREEN_SIZE(640, 480) |
| 5263 | 1839 | MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 479) |
| 5264 | | MCFG_SCREEN_UPDATE_DRIVER(chihiro_state,screen_update_callback) |
| 5265 | | MCFG_SCREEN_VBLANK_DRIVER(chihiro_state,vblank_callback) |
| 1840 | MCFG_SCREEN_UPDATE_DRIVER(chihiro_state, screen_update_callback) |
| 1841 | MCFG_SCREEN_VBLANK_DRIVER(chihiro_state, vblank_callback) |
| 5266 | 1842 | |
| 5267 | 1843 | MCFG_PALETTE_ADD("palette", 65536) |
| 5268 | 1844 | MACHINE_CONFIG_END |
| 5269 | 1845 | |
| 5270 | | static MACHINE_CONFIG_DERIVED( chihirogd, chihiro_base ) |
| 1846 | static MACHINE_CONFIG_DERIVED(chihirogd, chihiro_base) |
| 5271 | 1847 | MCFG_NAOMI_GDROM_BOARD_ADD("rom_board", ":gdrom", ":pic", NULL, NOOP) |
| 5272 | 1848 | MACHINE_CONFIG_END |
| 5273 | 1849 | |
trunk/src/mame/drivers/gts1.c
| r242208 | r242209 | |
| 70 | 70 | #include "cpu/pps4/pps4.h" |
| 71 | 71 | //#include "gts1.lh" |
| 72 | 72 | |
| 73 | | #define VERBOSE 1 |
| 74 | | |
| 75 | | #if VERBOSE |
| 76 | | #define LOG(x) logerror x |
| 77 | | #else |
| 78 | | #define LOG(x) |
| 79 | | #endif |
| 80 | | |
| 81 | 73 | class gts1_state : public genpin_class |
| 82 | 74 | { |
| 83 | 75 | public: |
| 84 | | gts1_state(const machine_config &mconfig, device_type type, const char *tag) |
| 85 | | : genpin_class(mconfig, type, tag) |
| 86 | | , m_maincpu(*this, "maincpu") |
| 87 | | { } |
| 76 | gts1_state(const machine_config &mconfig, device_type type, const char *tag) |
| 77 | : genpin_class(mconfig, type, tag) |
| 78 | , m_maincpu(*this, "maincpu") |
| 79 | { } |
| 88 | 80 | |
| 89 | | DECLARE_DRIVER_INIT(gts1); |
| 90 | | DECLARE_READ8_MEMBER (gts1_pa_r); |
| 91 | | DECLARE_WRITE8_MEMBER(gts1_pa_w); |
| 92 | | DECLARE_WRITE8_MEMBER(gts1_pb_w); |
| 81 | DECLARE_DRIVER_INIT(gts1); |
| 93 | 82 | private: |
| 94 | | virtual void machine_reset(); |
| 95 | | required_device<cpu_device> m_maincpu; |
| 96 | | UINT8 m_6351_addr; |
| 83 | virtual void machine_reset(); |
| 84 | required_device<cpu_device> m_maincpu; |
| 97 | 85 | }; |
| 98 | 86 | |
| 87 | |
| 99 | 88 | static ADDRESS_MAP_START( gts1_map, AS_PROGRAM, 8, gts1_state ) |
| 100 | | AM_RANGE(0x0000, 0x0fff) AM_ROM |
| 89 | AM_RANGE(0x0000, 0x0fff) AM_ROM |
| 101 | 90 | ADDRESS_MAP_END |
| 102 | 91 | |
| 103 | 92 | static ADDRESS_MAP_START( gts1_data, AS_DATA, 8, gts1_state ) |
| 104 | | AM_RANGE(0x0000, 0x0fff) AM_RAM // not correct |
| 93 | AM_RANGE(0x0000, 0x0fff) AM_RAM // not correct |
| 105 | 94 | ADDRESS_MAP_END |
| 106 | 95 | |
| 107 | 96 | static ADDRESS_MAP_START( gts1_io, AS_IO, 8, gts1_state ) |
| 108 | | AM_RANGE(0x0000, 0x00ff) AM_RAM // connects to all the other chips |
| 109 | | AM_RANGE(0x0100, 0x0100) AM_READ (gts1_pa_r) AM_WRITE(gts1_pa_w) |
| 110 | | AM_RANGE(0x0101, 0x0101) AM_WRITE(gts1_pb_w) |
| 97 | AM_RANGE(0x0000, 0x00ff) AM_RAM // connects to all the other chips |
| 111 | 98 | ADDRESS_MAP_END |
| 112 | 99 | |
| 113 | 100 | static INPUT_PORTS_START( gts1 ) |
| 114 | | PORT_START("DSW0") |
| 115 | | PORT_DIPNAME( 0x01, 0x00, "S01") |
| 116 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 117 | | PORT_DIPSETTING( 0x01, DEF_STR( On )) |
| 118 | | PORT_DIPNAME( 0x02, 0x00, "S02") |
| 119 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 120 | | PORT_DIPSETTING( 0x02, DEF_STR( On )) |
| 121 | | PORT_DIPNAME( 0x04, 0x00, "S03") |
| 122 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 123 | | PORT_DIPSETTING( 0x04, DEF_STR( On )) |
| 124 | | PORT_DIPNAME( 0x08, 0x00, "S04") |
| 125 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 126 | | PORT_DIPSETTING( 0x08, DEF_STR( On )) |
| 127 | | PORT_DIPNAME( 0x10, 0x00, "S05") |
| 128 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 129 | | PORT_DIPSETTING( 0x10, DEF_STR( On )) |
| 130 | | PORT_DIPNAME( 0x20, 0x20, "S06") |
| 131 | | PORT_DIPSETTING( 0x00, DEF_STR( No )) |
| 132 | | PORT_DIPSETTING( 0x20, DEF_STR( Yes )) |
| 133 | | PORT_DIPNAME( 0x40, 0x40, "S07") |
| 134 | | PORT_DIPSETTING( 0x00, DEF_STR( No )) |
| 135 | | PORT_DIPSETTING( 0x40, DEF_STR( Yes )) |
| 136 | | PORT_DIPNAME( 0x80, 0x80, "S08") |
| 137 | | PORT_DIPSETTING( 0x00, DEF_STR( No )) |
| 138 | | PORT_DIPSETTING( 0x80, DEF_STR( Yes )) |
| 101 | PORT_START("DSW0") |
| 102 | PORT_DIPNAME( 0x01, 0x00, "S01") |
| 103 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 104 | PORT_DIPSETTING( 0x01, DEF_STR( On )) |
| 105 | PORT_DIPNAME( 0x02, 0x00, "S02") |
| 106 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 107 | PORT_DIPSETTING( 0x02, DEF_STR( On )) |
| 108 | PORT_DIPNAME( 0x04, 0x00, "S03") |
| 109 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 110 | PORT_DIPSETTING( 0x04, DEF_STR( On )) |
| 111 | PORT_DIPNAME( 0x08, 0x00, "S04") |
| 112 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 113 | PORT_DIPSETTING( 0x08, DEF_STR( On )) |
| 114 | PORT_DIPNAME( 0x10, 0x00, "S05") |
| 115 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 116 | PORT_DIPSETTING( 0x10, DEF_STR( On )) |
| 117 | PORT_DIPNAME( 0x20, 0x20, "S06") |
| 118 | PORT_DIPSETTING( 0x00, DEF_STR( No )) |
| 119 | PORT_DIPSETTING( 0x20, DEF_STR( Yes )) |
| 120 | PORT_DIPNAME( 0x40, 0x40, "S07") |
| 121 | PORT_DIPSETTING( 0x00, DEF_STR( No )) |
| 122 | PORT_DIPSETTING( 0x40, DEF_STR( Yes )) |
| 123 | PORT_DIPNAME( 0x80, 0x80, "S08") |
| 124 | PORT_DIPSETTING( 0x00, DEF_STR( No )) |
| 125 | PORT_DIPSETTING( 0x80, DEF_STR( Yes )) |
| 139 | 126 | |
| 140 | | PORT_START("DSW1") |
| 141 | | PORT_DIPNAME( 0x01, 0x00, "S09") |
| 142 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 143 | | PORT_DIPSETTING( 0x01, DEF_STR( On )) |
| 144 | | PORT_DIPNAME( 0x02, 0x00, "S10") |
| 145 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 146 | | PORT_DIPSETTING( 0x02, DEF_STR( On )) |
| 147 | | PORT_DIPNAME( 0x04, 0x00, "S11") |
| 148 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 149 | | PORT_DIPSETTING( 0x04, DEF_STR( On )) |
| 150 | | PORT_DIPNAME( 0x08, 0x00, "S12") |
| 151 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 152 | | PORT_DIPSETTING( 0x08, DEF_STR( On )) |
| 153 | | PORT_DIPNAME( 0x10, 0x00, "S13") |
| 154 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 155 | | PORT_DIPSETTING( 0x10, DEF_STR( On )) |
| 156 | | PORT_DIPNAME( 0x20, 0x00, "S14") |
| 157 | | PORT_DIPSETTING( 0x00, DEF_STR( Yes )) |
| 158 | | PORT_DIPSETTING( 0x20, DEF_STR( No )) |
| 159 | | PORT_DIPNAME( 0x40, 0x40, "S15") |
| 160 | | PORT_DIPSETTING( 0x00, DEF_STR( No )) |
| 161 | | PORT_DIPSETTING( 0x40, DEF_STR( Yes )) |
| 162 | | PORT_DIPNAME( 0x80, 0x00, "S16") |
| 163 | | PORT_DIPSETTING( 0x00, DEF_STR( No )) |
| 164 | | PORT_DIPSETTING( 0x80, DEF_STR( Yes )) |
| 127 | PORT_START("DSW1") |
| 128 | PORT_DIPNAME( 0x01, 0x00, "S09") |
| 129 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 130 | PORT_DIPSETTING( 0x01, DEF_STR( On )) |
| 131 | PORT_DIPNAME( 0x02, 0x00, "S10") |
| 132 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 133 | PORT_DIPSETTING( 0x02, DEF_STR( On )) |
| 134 | PORT_DIPNAME( 0x04, 0x00, "S11") |
| 135 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 136 | PORT_DIPSETTING( 0x04, DEF_STR( On )) |
| 137 | PORT_DIPNAME( 0x08, 0x00, "S12") |
| 138 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 139 | PORT_DIPSETTING( 0x08, DEF_STR( On )) |
| 140 | PORT_DIPNAME( 0x10, 0x00, "S13") |
| 141 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 142 | PORT_DIPSETTING( 0x10, DEF_STR( On )) |
| 143 | PORT_DIPNAME( 0x20, 0x00, "S14") |
| 144 | PORT_DIPSETTING( 0x00, DEF_STR( Yes )) |
| 145 | PORT_DIPSETTING( 0x20, DEF_STR( No )) |
| 146 | PORT_DIPNAME( 0x40, 0x40, "S15") |
| 147 | PORT_DIPSETTING( 0x00, DEF_STR( No )) |
| 148 | PORT_DIPSETTING( 0x40, DEF_STR( Yes )) |
| 149 | PORT_DIPNAME( 0x80, 0x00, "S16") |
| 150 | PORT_DIPSETTING( 0x00, DEF_STR( No )) |
| 151 | PORT_DIPSETTING( 0x80, DEF_STR( Yes )) |
| 165 | 152 | |
| 166 | | PORT_START("DSW2") |
| 167 | | PORT_DIPNAME( 0x01, 0x00, "S17") |
| 168 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 169 | | PORT_DIPSETTING( 0x01, DEF_STR( On )) |
| 170 | | PORT_DIPNAME( 0x02, 0x00, "S18") |
| 171 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 172 | | PORT_DIPSETTING( 0x02, DEF_STR( On )) |
| 173 | | PORT_DIPNAME( 0x04, 0x00, "S19") |
| 174 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 175 | | PORT_DIPSETTING( 0x04, DEF_STR( On )) |
| 176 | | PORT_DIPNAME( 0x08, 0x00, "S20") |
| 177 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 178 | | PORT_DIPSETTING( 0x08, DEF_STR( On )) |
| 179 | | PORT_DIPNAME( 0x10, 0x00, "S21") |
| 180 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 181 | | PORT_DIPSETTING( 0x10, DEF_STR( On )) |
| 182 | | PORT_DIPNAME( 0x20, 0x00, "S22") |
| 183 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 184 | | PORT_DIPSETTING( 0x20, DEF_STR( On )) |
| 185 | | PORT_DIPNAME( 0x40, 0x00, "S23") |
| 186 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 187 | | PORT_DIPSETTING( 0x40, DEF_STR( On )) |
| 188 | | PORT_DIPNAME( 0x80, 0x00, "S24") |
| 189 | | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 190 | | PORT_DIPSETTING( 0x80, DEF_STR( On )) |
| 153 | PORT_START("DSW2") |
| 154 | PORT_DIPNAME( 0x01, 0x00, "S17") |
| 155 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 156 | PORT_DIPSETTING( 0x01, DEF_STR( On )) |
| 157 | PORT_DIPNAME( 0x02, 0x00, "S18") |
| 158 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 159 | PORT_DIPSETTING( 0x02, DEF_STR( On )) |
| 160 | PORT_DIPNAME( 0x04, 0x00, "S19") |
| 161 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 162 | PORT_DIPSETTING( 0x04, DEF_STR( On )) |
| 163 | PORT_DIPNAME( 0x08, 0x00, "S20") |
| 164 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 165 | PORT_DIPSETTING( 0x08, DEF_STR( On )) |
| 166 | PORT_DIPNAME( 0x10, 0x00, "S21") |
| 167 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 168 | PORT_DIPSETTING( 0x10, DEF_STR( On )) |
| 169 | PORT_DIPNAME( 0x20, 0x00, "S22") |
| 170 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 171 | PORT_DIPSETTING( 0x20, DEF_STR( On )) |
| 172 | PORT_DIPNAME( 0x40, 0x00, "S23") |
| 173 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 174 | PORT_DIPSETTING( 0x40, DEF_STR( On )) |
| 175 | PORT_DIPNAME( 0x80, 0x00, "S24") |
| 176 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 177 | PORT_DIPSETTING( 0x80, DEF_STR( On )) |
| 191 | 178 | INPUT_PORTS_END |
| 192 | 179 | |
| 193 | 180 | void gts1_state::machine_reset() |
| 194 | 181 | { |
| 195 | | m_6351_addr = 0; |
| 196 | 182 | } |
| 197 | 183 | |
| 198 | 184 | DRIVER_INIT_MEMBER(gts1_state,gts1) |
| 199 | 185 | { |
| 200 | 186 | } |
| 201 | 187 | |
| 202 | | READ8_MEMBER (gts1_state::gts1_pa_r) |
| 203 | | { |
| 204 | | // return ROM nibble |
| 205 | | UINT8 *ROM = memregion("maincpu")->base(); |
| 206 | | UINT8 data = ROM[0x2000 + m_6351_addr] & 0x0f; |
| 207 | | LOG(("%s: ROM[%03x]:%02x\n", __FUNCTION__, m_6351_addr, data)); |
| 208 | | return data; |
| 209 | | } |
| 210 | | |
| 211 | | WRITE8_MEMBER(gts1_state::gts1_pa_w) |
| 212 | | { |
| 213 | | // write address lines 7-4 |
| 214 | | m_6351_addr = (m_6351_addr & 0x0f) | ((data & 0x0f) << 4); |
| 215 | | LOG(("%s: ROM hi:%x addr:%02x\n", __FUNCTION__, data & 0x0f, m_6351_addr)); |
| 216 | | } |
| 217 | | |
| 218 | | WRITE8_MEMBER(gts1_state::gts1_pb_w) |
| 219 | | { |
| 220 | | // write address lines 3-0 |
| 221 | | m_6351_addr = (m_6351_addr & 0xf0) | (data & 0x0f); |
| 222 | | LOG(("%s: ROM lo:%x addr:%02x\n", __FUNCTION__, data & 0x0f, m_6351_addr)); |
| 223 | | } |
| 224 | | |
| 225 | | |
| 226 | 188 | static MACHINE_CONFIG_START( gts1, gts1_state ) |
| 227 | | /* basic machine hardware */ |
| 228 | | MCFG_CPU_ADD("maincpu", PPS4, XTAL_3_579545MHz / 18) // divided in the CPU |
| 229 | | MCFG_CPU_PROGRAM_MAP(gts1_map) |
| 230 | | MCFG_CPU_DATA_MAP(gts1_data) |
| 231 | | MCFG_CPU_IO_MAP(gts1_io) |
| 189 | /* basic machine hardware */ |
| 190 | MCFG_CPU_ADD("maincpu", PPS4, XTAL_3_579545MHz / 18) // divided in the CPU |
| 191 | MCFG_CPU_PROGRAM_MAP(gts1_map) |
| 192 | MCFG_CPU_DATA_MAP(gts1_data) |
| 193 | MCFG_CPU_IO_MAP(gts1_io) |
| 232 | 194 | |
| 233 | | //MCFG_NVRAM_ADD_0FILL("nvram") |
| 195 | //MCFG_NVRAM_ADD_0FILL("nvram") |
| 234 | 196 | |
| 235 | | /* Video */ |
| 236 | | //MCFG_DEFAULT_LAYOUT(layout_gts1) |
| 197 | /* Video */ |
| 198 | //MCFG_DEFAULT_LAYOUT(layout_gts1) |
| 237 | 199 | |
| 238 | | /* Sound */ |
| 239 | | MCFG_FRAGMENT_ADD( genpin_audio ) |
| 200 | /* Sound */ |
| 201 | MCFG_FRAGMENT_ADD( genpin_audio ) |
| 240 | 202 | MACHINE_CONFIG_END |
| 241 | 203 | |
| 242 | 204 | |
| 243 | 205 | ROM_START( gts1 ) |
| 244 | | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 245 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 246 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 206 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 207 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 208 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 247 | 209 | ROM_END |
| 248 | 210 | |
| 249 | 211 | ROM_START( gts1s ) |
| 250 | | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 251 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 252 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 212 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 213 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 214 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 253 | 215 | ROM_END |
| 254 | 216 | |
| 255 | 217 | /*------------------------------------------------------------------- |
| 256 | 218 | / Asteroid Annie and the Aliens (12/1980) #442 |
| 257 | 219 | /-------------------------------------------------------------------*/ |
| 258 | 220 | ROM_START(astannie) |
| 259 | | ROM_REGION(0x10000, "maincpu", 0) |
| 260 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 261 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 262 | | ROM_LOAD("442.cpu", 0x2000, 0x0400, CRC(579521e0) SHA1(b1b19473e1ca3373955ee96104b87f586c4c311c)) |
| 263 | | ROM_REGION(0x10000, "cpu2", 0) |
| 264 | | ROM_LOAD("442.snd", 0x0400, 0x0400, CRC(c70195b4) SHA1(ff06197f07111d6a4b8942dcfe8d2279bda6f281)) |
| 265 | | ROM_RELOAD( 0x0800, 0x0400) |
| 266 | | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 267 | | ROM_RELOAD( 0xfc00, 0x0400) |
| 221 | ROM_REGION(0x10000, "maincpu", 0) |
| 222 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 223 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 224 | ROM_LOAD("442.cpu", 0x2000, 0x0400, CRC(579521e0) SHA1(b1b19473e1ca3373955ee96104b87f586c4c311c)) |
| 225 | ROM_REGION(0x10000, "cpu2", 0) |
| 226 | ROM_LOAD("442.snd", 0x0400, 0x0400, CRC(c70195b4) SHA1(ff06197f07111d6a4b8942dcfe8d2279bda6f281)) |
| 227 | ROM_RELOAD( 0x0800, 0x0400) |
| 228 | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 229 | ROM_RELOAD( 0xfc00, 0x0400) |
| 268 | 230 | ROM_END |
| 269 | 231 | |
| 270 | 232 | /*------------------------------------------------------------------- |
| 271 | 233 | / Buck Rogers (01/1980) #437 |
| 272 | 234 | /-------------------------------------------------------------------*/ |
| 273 | 235 | ROM_START(buckrgrs) |
| 274 | | ROM_REGION(0x10000, "maincpu", 0) |
| 275 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 276 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 277 | | ROM_LOAD("437.cpu", 0x2000, 0x0400, CRC(e57d9278) SHA1(dfc4ebff1e14b9a074468671a8e5ac7948d5b352)) |
| 278 | | ROM_REGION(0x10000, "cpu2", 0) |
| 279 | | ROM_LOAD("437.snd", 0x0400, 0x0400, CRC(732b5a27) SHA1(7860ea54e75152246c3ac3205122d750b243b40c)) |
| 280 | | ROM_RELOAD( 0x0800, 0x0400) |
| 281 | | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 282 | | ROM_RELOAD( 0xfc00, 0x0400) |
| 236 | ROM_REGION(0x10000, "maincpu", 0) |
| 237 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 238 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 239 | ROM_LOAD("437.cpu", 0x2000, 0x0400, CRC(e57d9278) SHA1(dfc4ebff1e14b9a074468671a8e5ac7948d5b352)) |
| 240 | ROM_REGION(0x10000, "cpu2", 0) |
| 241 | ROM_LOAD("437.snd", 0x0400, 0x0400, CRC(732b5a27) SHA1(7860ea54e75152246c3ac3205122d750b243b40c)) |
| 242 | ROM_RELOAD( 0x0800, 0x0400) |
| 243 | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 244 | ROM_RELOAD( 0xfc00, 0x0400) |
| 283 | 245 | ROM_END |
| 284 | 246 | |
| 285 | 247 | /*------------------------------------------------------------------- |
| 286 | 248 | / Charlie's Angels (11/1978) #425 |
| 287 | 249 | /-------------------------------------------------------------------*/ |
| 288 | 250 | ROM_START(charlies) |
| 289 | | ROM_REGION(0x10000, "maincpu", 0) |
| 290 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 291 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 292 | | ROM_LOAD("425.cpu", 0x2000, 0x0400, CRC(928b4279) SHA1(51096d45e880d6a8263eaeaa0cdab0f61ad2f58d)) |
| 251 | ROM_REGION(0x10000, "maincpu", 0) |
| 252 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 253 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 254 | ROM_LOAD("425.cpu", 0x2000, 0x0400, CRC(928b4279) SHA1(51096d45e880d6a8263eaeaa0cdab0f61ad2f58d)) |
| 293 | 255 | ROM_END |
| 294 | 256 | /*------------------------------------------------------------------- |
| 295 | 257 | / Cleopatra (11/1977) #409 |
| 296 | 258 | /-------------------------------------------------------------------*/ |
| 297 | 259 | ROM_START(cleoptra) |
| 298 | | ROM_REGION(0x10000, "maincpu", 0) |
| 299 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 300 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 301 | | ROM_LOAD("409.cpu", 0x2000, 0x0400, CRC(8063ff71) SHA1(205f09f067bf79544d2ce2a48d23259901f935dd)) |
| 260 | ROM_REGION(0x10000, "maincpu", 0) |
| 261 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 262 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 263 | ROM_LOAD("409.cpu", 0x2000, 0x0400, CRC(8063ff71) SHA1(205f09f067bf79544d2ce2a48d23259901f935dd)) |
| 302 | 264 | ROM_END |
| 303 | 265 | |
| 304 | 266 | /*------------------------------------------------------------------- |
| 305 | 267 | / Close Encounters of the Third Kind (10/1978) #424 |
| 306 | 268 | /-------------------------------------------------------------------*/ |
| 307 | 269 | ROM_START(closeenc) |
| 308 | | ROM_REGION(0x10000, "maincpu", 0) |
| 309 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 310 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 311 | | ROM_LOAD("424.cpu", 0x2000, 0x0400, CRC(a7a5dd13) SHA1(223c67b9484baa719c91de52b363ff22813db160)) |
| 270 | ROM_REGION(0x10000, "maincpu", 0) |
| 271 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 272 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 273 | ROM_LOAD("424.cpu", 0x2000, 0x0400, CRC(a7a5dd13) SHA1(223c67b9484baa719c91de52b363ff22813db160)) |
| 312 | 274 | ROM_END |
| 313 | 275 | |
| 314 | 276 | /*------------------------------------------------------------------- |
| 315 | 277 | / Count-Down (05/1979) #422 |
| 316 | 278 | /-------------------------------------------------------------------*/ |
| 317 | 279 | ROM_START(countdwn) |
| 318 | | ROM_REGION(0x10000, "maincpu", 0) |
| 319 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 320 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 321 | | ROM_LOAD("422.cpu", 0x2000, 0x0400, CRC(51bc2df0) SHA1(d4b555d106c6b4e420b0fcd1df8871f869476c22)) |
| 280 | ROM_REGION(0x10000, "maincpu", 0) |
| 281 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 282 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 283 | ROM_LOAD("422.cpu", 0x2000, 0x0400, CRC(51bc2df0) SHA1(d4b555d106c6b4e420b0fcd1df8871f869476c22)) |
| 322 | 284 | ROM_END |
| 323 | 285 | |
| 324 | 286 | /*------------------------------------------------------------------- |
| 325 | 287 | / Dragon (10/1978) #419 |
| 326 | 288 | /-------------------------------------------------------------------*/ |
| 327 | 289 | ROM_START(dragon) |
| 328 | | ROM_REGION(0x10000, "maincpu", 0) |
| 329 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 330 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 331 | | ROM_LOAD("419.cpu", 0x2000, 0x0400, CRC(018d9b3a) SHA1(da37ef5017c71bc41bdb1f30d3fd7ac3b7e1ee7e)) |
| 290 | ROM_REGION(0x10000, "maincpu", 0) |
| 291 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 292 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 293 | ROM_LOAD("419.cpu", 0x2000, 0x0400, CRC(018d9b3a) SHA1(da37ef5017c71bc41bdb1f30d3fd7ac3b7e1ee7e)) |
| 332 | 294 | ROM_END |
| 333 | 295 | |
| 334 | 296 | /*------------------------------------------------------------------- |
| 335 | 297 | / Genie (11/1979) #435 |
| 336 | 298 | /-------------------------------------------------------------------*/ |
| 337 | 299 | ROM_START(geniep) |
| 338 | | ROM_REGION(0x10000, "maincpu", 0) |
| 339 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 340 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 341 | | ROM_LOAD("435.cpu", 0x2000, 0x0400, CRC(7749fd92) SHA1(9cd3e799842392e3939877bf295759c27f199e58)) |
| 342 | | ROM_REGION(0x10000, "cpu2", 0) |
| 343 | | ROM_LOAD("435.snd", 0x0400, 0x0400, CRC(4a98ceed) SHA1(f1d7548e03107033c39953ee04b043b5301dbb47)) |
| 344 | | ROM_RELOAD( 0x0800, 0x0400) |
| 345 | | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 346 | | ROM_RELOAD( 0xfc00, 0x0400) |
| 300 | ROM_REGION(0x10000, "maincpu", 0) |
| 301 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 302 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 303 | ROM_LOAD("435.cpu", 0x2000, 0x0400, CRC(7749fd92) SHA1(9cd3e799842392e3939877bf295759c27f199e58)) |
| 304 | ROM_REGION(0x10000, "cpu2", 0) |
| 305 | ROM_LOAD("435.snd", 0x0400, 0x0400, CRC(4a98ceed) SHA1(f1d7548e03107033c39953ee04b043b5301dbb47)) |
| 306 | ROM_RELOAD( 0x0800, 0x0400) |
| 307 | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 308 | ROM_RELOAD( 0xfc00, 0x0400) |
| 347 | 309 | ROM_END |
| 348 | 310 | |
| 349 | 311 | /*------------------------------------------------------------------- |
| 350 | 312 | / Joker Poker (08/1978) #417 |
| 351 | 313 | /-------------------------------------------------------------------*/ |
| 352 | 314 | ROM_START(jokrpokr) |
| 353 | | ROM_REGION(0x10000, "maincpu", 0) |
| 354 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 355 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 356 | | ROM_LOAD("417.cpu", 0x2000, 0x0400, CRC(33dade08) SHA1(23b8dbd7b6c84b806fc0d2da95478235cbf9f80a)) |
| 315 | ROM_REGION(0x10000, "maincpu", 0) |
| 316 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 317 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 318 | ROM_LOAD("417.cpu", 0x2000, 0x0400, CRC(33dade08) SHA1(23b8dbd7b6c84b806fc0d2da95478235cbf9f80a)) |
| 357 | 319 | ROM_END |
| 358 | 320 | |
| 359 | 321 | /*------------------------------------------------------------------- |
| r242208 | r242209 | |
| 363 | 325 | / L'Hexagone (04/1986) |
| 364 | 326 | /-------------------------------------------------------------------*/ |
| 365 | 327 | ROM_START(hexagone) |
| 366 | | ROM_REGION(0x10000, "maincpu", 0) |
| 367 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 368 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 369 | | ROM_LOAD("435.cpu", 0x2000, 0x0400, CRC(7749fd92) SHA1(9cd3e799842392e3939877bf295759c27f199e58)) |
| 370 | | ROM_REGION(0x10000, "cpu2", 0) |
| 371 | | ROM_LOAD("hexagone.bin", 0, 0x4000, CRC(002b5464) SHA1(e2d971c4e85b4fb6580c2d3945c9946ea0cebc2e)) |
| 328 | ROM_REGION(0x10000, "maincpu", 0) |
| 329 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 330 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 331 | ROM_LOAD("435.cpu", 0x2000, 0x0400, CRC(7749fd92) SHA1(9cd3e799842392e3939877bf295759c27f199e58)) |
| 332 | ROM_REGION(0x10000, "cpu2", 0) |
| 333 | ROM_LOAD("hexagone.bin", 0, 0x4000, CRC(002b5464) SHA1(e2d971c4e85b4fb6580c2d3945c9946ea0cebc2e)) |
| 372 | 334 | ROM_END |
| 373 | 335 | /*------------------------------------------------------------------- |
| 374 | 336 | / Movie |
| r242208 | r242209 | |
| 378 | 340 | / Pinball Pool (08/1979) #427 |
| 379 | 341 | /-------------------------------------------------------------------*/ |
| 380 | 342 | ROM_START(pinpool) |
| 381 | | ROM_REGION(0x10000, "maincpu", 0) |
| 382 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 383 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 384 | | ROM_LOAD("427.cpu", 0x2000, 0x0400, CRC(c496393d) SHA1(e91d9596aacdb4277fa200a3f8f9da099c278f32)) |
| 343 | ROM_REGION(0x10000, "maincpu", 0) |
| 344 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 345 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 346 | ROM_LOAD("427.cpu", 0x2000, 0x0400, CRC(c496393d) SHA1(e91d9596aacdb4277fa200a3f8f9da099c278f32)) |
| 385 | 347 | ROM_END |
| 386 | 348 | |
| 387 | 349 | /*------------------------------------------------------------------- |
| 388 | 350 | / Roller Disco (02/1980) #440 |
| 389 | 351 | /-------------------------------------------------------------------*/ |
| 390 | 352 | ROM_START(roldisco) |
| 391 | | ROM_REGION(0x10000, "maincpu", 0) |
| 392 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 393 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 394 | | ROM_LOAD("440.cpu", 0x2000, 0x0400, CRC(bc50631f) SHA1(6aa3124d09fc4e369d087a5ad6dd1737ace55e41)) |
| 395 | | ROM_REGION(0x10000, "cpu2", 0) |
| 396 | | ROM_LOAD("440.snd", 0x0400, 0x0400, CRC(4a0a05ae) SHA1(88f21b5638494d8e78dc0b6b7d69873b76b5f75d)) |
| 397 | | ROM_RELOAD( 0x0800, 0x0400) |
| 398 | | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 399 | | ROM_RELOAD( 0xfc00, 0x0400) |
| 353 | ROM_REGION(0x10000, "maincpu", 0) |
| 354 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 355 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 356 | ROM_LOAD("440.cpu", 0x2000, 0x0400, CRC(bc50631f) SHA1(6aa3124d09fc4e369d087a5ad6dd1737ace55e41)) |
| 357 | ROM_REGION(0x10000, "cpu2", 0) |
| 358 | ROM_LOAD("440.snd", 0x0400, 0x0400, CRC(4a0a05ae) SHA1(88f21b5638494d8e78dc0b6b7d69873b76b5f75d)) |
| 359 | ROM_RELOAD( 0x0800, 0x0400) |
| 360 | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 361 | ROM_RELOAD( 0xfc00, 0x0400) |
| 400 | 362 | ROM_END |
| 401 | 363 | |
| 402 | 364 | /*------------------------------------------------------------------- |
| r242208 | r242209 | |
| 407 | 369 | / Sinbad (05/1978) #412 |
| 408 | 370 | /-------------------------------------------------------------------*/ |
| 409 | 371 | ROM_START(sinbad) |
| 410 | | ROM_REGION(0x10000, "maincpu", 0) |
| 411 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 412 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 413 | | ROM_LOAD("412.cpu", 0x2000, 0x0400, CRC(84a86b83) SHA1(f331f2ffd7d1b279b4ffbb939aa8649e723f5fac)) |
| 372 | ROM_REGION(0x10000, "maincpu", 0) |
| 373 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 374 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 375 | ROM_LOAD("412.cpu", 0x2000, 0x0400, CRC(84a86b83) SHA1(f331f2ffd7d1b279b4ffbb939aa8649e723f5fac)) |
| 414 | 376 | ROM_END |
| 415 | 377 | |
| 416 | 378 | ROM_START(sinbadn) |
| 417 | | ROM_REGION(0x10000, "maincpu", 0) |
| 418 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 419 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 420 | | ROM_LOAD("412no1.cpu", 0x2000, 0x0400, CRC(f5373f5f) SHA1(027840501416ff01b2adf07188c7d667adf3ad5f)) |
| 379 | ROM_REGION(0x10000, "maincpu", 0) |
| 380 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 381 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 382 | ROM_LOAD("412no1.cpu", 0x2000, 0x0400, CRC(f5373f5f) SHA1(027840501416ff01b2adf07188c7d667adf3ad5f)) |
| 421 | 383 | ROM_END |
| 422 | 384 | |
| 423 | 385 | /*------------------------------------------------------------------- |
| r242208 | r242209 | |
| 428 | 390 | / Solar Ride (02/1979) #421 |
| 429 | 391 | /-------------------------------------------------------------------*/ |
| 430 | 392 | ROM_START(solaride) |
| 431 | | ROM_REGION(0x10000, "maincpu", 0) |
| 432 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 433 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 434 | | ROM_LOAD("421.cpu", 0x2000, 0x0400, CRC(6b5c5da6) SHA1(a09b7009473be53586f53f48b7bfed9a0c5ecd55)) |
| 393 | ROM_REGION(0x10000, "maincpu", 0) |
| 394 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 395 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 396 | ROM_LOAD("421.cpu", 0x2000, 0x0400, CRC(6b5c5da6) SHA1(a09b7009473be53586f53f48b7bfed9a0c5ecd55)) |
| 435 | 397 | ROM_END |
| 436 | 398 | |
| 437 | 399 | /*------------------------------------------------------------------- |
| 438 | 400 | / The Incredible Hulk (10/1979) #433 |
| 439 | 401 | /-------------------------------------------------------------------*/ |
| 440 | 402 | ROM_START(hulk) |
| 441 | | ROM_REGION(0x10000, "maincpu", 0) |
| 442 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 443 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 444 | | ROM_LOAD("433.cpu", 0x2000, 0x0400, CRC(c05d2b52) SHA1(393fe063b029246317c90ee384db95a84d61dbb7)) |
| 445 | | ROM_REGION(0x10000, "cpu2", 0) |
| 446 | | ROM_LOAD("433.snd", 0x0400, 0x0400, CRC(20cd1dff) SHA1(93e7c47ff7051c3c0dc9f8f95aa33ba094e7cf25)) |
| 447 | | ROM_RELOAD( 0x0800, 0x0400) |
| 448 | | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 449 | | ROM_RELOAD( 0xfc00, 0x0400) |
| 403 | ROM_REGION(0x10000, "maincpu", 0) |
| 404 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 405 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 406 | ROM_LOAD("433.cpu", 0x2000, 0x0400, CRC(c05d2b52) SHA1(393fe063b029246317c90ee384db95a84d61dbb7)) |
| 407 | ROM_REGION(0x10000, "cpu2", 0) |
| 408 | ROM_LOAD("433.snd", 0x0400, 0x0400, CRC(20cd1dff) SHA1(93e7c47ff7051c3c0dc9f8f95aa33ba094e7cf25)) |
| 409 | ROM_RELOAD( 0x0800, 0x0400) |
| 410 | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 411 | ROM_RELOAD( 0xfc00, 0x0400) |
| 450 | 412 | ROM_END |
| 451 | 413 | |
| 452 | 414 | /*------------------------------------------------------------------- |
| 453 | 415 | / Torch (02/1980) #438 |
| 454 | 416 | /-------------------------------------------------------------------*/ |
| 455 | 417 | ROM_START(torch) |
| 456 | | ROM_REGION(0x10000, "maincpu", 0) |
| 457 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 458 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 459 | | ROM_LOAD("438.cpu", 0x2000, 0x0400, CRC(2d396a64) SHA1(38a1862771500faa471071db08dfbadc6e8759e8)) |
| 460 | | ROM_REGION(0x10000, "cpu2", 0) |
| 461 | | ROM_LOAD("438.snd", 0x0400, 0x0400, CRC(a9619b48) SHA1(1906bc1b059bf31082e3b4546f5a30159479ad3c)) |
| 462 | | ROM_RELOAD( 0x0800, 0x0400) |
| 463 | | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 464 | | ROM_RELOAD( 0xfc00, 0x0400) |
| 418 | ROM_REGION(0x10000, "maincpu", 0) |
| 419 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 420 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 421 | ROM_LOAD("438.cpu", 0x2000, 0x0400, CRC(2d396a64) SHA1(38a1862771500faa471071db08dfbadc6e8759e8)) |
| 422 | ROM_REGION(0x10000, "cpu2", 0) |
| 423 | ROM_LOAD("438.snd", 0x0400, 0x0400, CRC(a9619b48) SHA1(1906bc1b059bf31082e3b4546f5a30159479ad3c)) |
| 424 | ROM_RELOAD( 0x0800, 0x0400) |
| 425 | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 426 | ROM_RELOAD( 0xfc00, 0x0400) |
| 465 | 427 | ROM_END |
| 466 | 428 | |
| 467 | 429 | /*------------------------------------------------------------------- |
| 468 | 430 | / Totem (10/1979) #429 |
| 469 | 431 | /-------------------------------------------------------------------*/ |
| 470 | 432 | ROM_START(totem) |
| 471 | | ROM_REGION(0x10000, "maincpu", 0) |
| 472 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 473 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 474 | | ROM_LOAD("429.cpu", 0x2000, 0x0400, CRC(7885a384) SHA1(1770662af7d48ad8297097a9877c5c497119978d)) |
| 475 | | ROM_REGION(0x10000, "cpu2", 0) |
| 476 | | ROM_LOAD("429.snd", 0x0400, 0x0400, CRC(5d1b7ed4) SHA1(4a584f880e907fb21da78f3b3a0617f20599688f)) |
| 477 | | ROM_RELOAD( 0x0800, 0x0400) |
| 478 | | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 479 | | ROM_RELOAD( 0xfc00, 0x0400) |
| 433 | ROM_REGION(0x10000, "maincpu", 0) |
| 434 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 435 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 436 | ROM_LOAD("429.cpu", 0x2000, 0x0400, CRC(7885a384) SHA1(1770662af7d48ad8297097a9877c5c497119978d)) |
| 437 | ROM_REGION(0x10000, "cpu2", 0) |
| 438 | ROM_LOAD("429.snd", 0x0400, 0x0400, CRC(5d1b7ed4) SHA1(4a584f880e907fb21da78f3b3a0617f20599688f)) |
| 439 | ROM_RELOAD( 0x0800, 0x0400) |
| 440 | ROM_LOAD("6530sys1.bin", 0x0c00, 0x0400, CRC(b7831321) SHA1(c94f4bee97854d0373653a6867016e27d3fc1340)) |
| 441 | ROM_RELOAD( 0xfc00, 0x0400) |
| 480 | 442 | ROM_END |
| 481 | 443 | |
| 482 | 444 | /*------------------------------------------------------------------- |
| 483 | 445 | / System 1 Test prom |
| 484 | 446 | /-------------------------------------------------------------------*/ |
| 485 | 447 | ROM_START(sys1test) |
| 486 | | ROM_REGION(0x10000, "maincpu", 0) |
| 487 | | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 488 | | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 489 | | ROM_LOAD("test.cpu", 0x2000, 0x0400, CRC(8b0704bb) SHA1(5f0eb8d5af867b815b6012c9d078927398efe6d8)) |
| 448 | ROM_REGION(0x10000, "maincpu", 0) |
| 449 | ROM_LOAD("u5_cf.bin", 0x0000, 0x0800, CRC(e0d4b405) SHA1(17aadd79c0dcbb336aadd5d203bc6ca866492345)) |
| 450 | ROM_LOAD("u4_ce.bin", 0x0800, 0x0800, CRC(4cd312dd) SHA1(31245daa9972ef8652caee69986585bb8239e86e)) |
| 451 | ROM_LOAD("test.cpu", 0x2000, 0x0400, CRC(8b0704bb) SHA1(5f0eb8d5af867b815b6012c9d078927398efe6d8)) |
| 490 | 452 | ROM_END |
| 491 | 453 | |
| 492 | 454 | |
trunk/src/mame/video/chihiro.c
| r0 | r242209 | |
| 1 | #include "emu.h" |
| 2 | #include "video/poly.h" |
| 3 | #include "bitmap.h" |
| 4 | #include "includes/chihiro.h" |
| 5 | |
| 6 | //#define LOG_NV2A |
| 7 | |
| 8 | const char *vertex_program_disassembler::srctypes[] = { "??", "Rn", "Vn", "Cn" }; |
| 9 | const char *vertex_program_disassembler::scaops[] = { "NOP", "IMV", "RCP", "RCC", "RSQ", "EXP", "LOG", "LIT", "???", "???", "???", "???", "???", "???", "???", "???", "???" }; |
| 10 | const int vertex_program_disassembler::scapar2[] = { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 11 | const char *vertex_program_disassembler::vecops[] = { "NOP", "MOV", "MUL", "ADD", "MAD", "DP3", "DPH", "DP4", "DST", "MIN", "MAX", "SLT", "SGE", "ARL", "???", "???", "???" }; |
| 12 | const int vertex_program_disassembler::vecpar2[] = { 0, 4, 6, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 4, 0, 0, 0 }; |
| 13 | const char *vertex_program_disassembler::vecouts[] = { "oPos", "???", "???", "oD0", "oD1", "oFog", "oPts", "oB0", "oB1", "oT0", "oT1", "oT2", "oT3" }; |
| 14 | const char vertex_program_disassembler::compchar[] = { 'x', 'y', 'z', 'w' }; |
| 15 | |
| 16 | /* |
| 17 | Each vertex program instruction is a 128 bit word made of the fields: |
| 18 | d f |
| 19 | w b i |
| 20 | o i e |
| 21 | r t l |
| 22 | d s d |
| 23 | +-+-----+------- |
| 24 | |0|31-0 |not used |
| 25 | +-+-----+------- |
| 26 | | |31-29|not used |
| 27 | | +-----+------- |
| 28 | | |28-25|scalar operation |
| 29 | | +-----+------- |
| 30 | | |24-21|vectorial operation |
| 31 | | +-----+------- |
| 32 | | |20-13|index for source constant C[] |
| 33 | | +-----+------- |
| 34 | | |12-9 |input vector index |
| 35 | | +-----+------- |
| 36 | |1| 8 |parameter A:sign |
| 37 | | +-----+------- |
| 38 | | | 7-6 |parameter A:swizzle x |
| 39 | | +-----+------- |
| 40 | | | 5-4 |parameter A:swizzle y |
| 41 | | +-----+------- |
| 42 | | | 3-2 |parameter A:swizzle z |
| 43 | | +-----+------- |
| 44 | | | 1-0 |parameter A:swizzle w |
| 45 | |-+-----+------- |
| 46 | | |31-28|parameter A:parameter Rn index |
| 47 | | +-----+------- |
| 48 | | |27-26|parameter A:input type 1:Rn 2:Vn 3:C[n] |
| 49 | | +-----+------- |
| 50 | | | 25 |parameter B:sign |
| 51 | | +-----+------- |
| 52 | | |24-23|parameter B:swizzle x |
| 53 | | +-----+------- |
| 54 | | |22-21|parameter B:swizzle y |
| 55 | | +-----+------- |
| 56 | | |20-19|parameter B:swizzle z |
| 57 | | +-----+------- |
| 58 | |2|18-17|parameter B:swizzle w |
| 59 | | +-----+------- |
| 60 | | |16-13|parameter B:parameter Rn index |
| 61 | | +-----+------- |
| 62 | | |12-11|parameter B:input type 1:Rn 2:Vn 3:C[n] |
| 63 | | +-----+------- |
| 64 | | | 10 |parameter C:sign |
| 65 | | +-----+------- |
| 66 | | | 9-8 |parameter C:swizzle x |
| 67 | | +-----+------- |
| 68 | | | 7-6 |parameter C:swizzle y |
| 69 | | +-----+------- |
| 70 | | | 5-4 |parameter C:swizzle z |
| 71 | | +-----+------- |
| 72 | | | 3-2 |parameter C:swizzle w |
| 73 | | +-----+------- |
| 74 | | | 1-0 | |
| 75 | |-+ |parameter C:parameter Rn index |
| 76 | | |31-30| |
| 77 | | +-----+------- |
| 78 | | |29-28|parameter C:input type 1:Rn 2:Vn 3:C[n] |
| 79 | | +-----+------- |
| 80 | | |27-24|output Rn mask from vectorial operation |
| 81 | | +-----+------- |
| 82 | | |23-20|output Rn index from vectorial operation |
| 83 | | +-----+------- |
| 84 | | |19-16|output Rn mask from scalar operation |
| 85 | | +-----+------- |
| 86 | |3|15-12|output vector write mask |
| 87 | | +-----+------- |
| 88 | | | 11 |1:output is output vector 0:output is constant C[] |
| 89 | | +-----+------- |
| 90 | | |10-3 |output vector/constant index |
| 91 | | +-----+------- |
| 92 | | | 2 |0:output Rn from vectorial operation 1:output Rn from scalar operation |
| 93 | | +-----+------- |
| 94 | | | 1 |1:add a0x to index for source constant C[] |
| 95 | | +-----+------- |
| 96 | | | 0 |1:end of program |
| 97 | +-+-----+------- |
| 98 | Each vertex program instruction can generate up to three destination values using up to three source values. |
| 99 | The first possible destination is to Rn from a vectorial operation. |
| 100 | The second possible destination is to a vertex shader output or C[n] from a vectorial or scalar operation. |
| 101 | The third possible destination is to Rn from a scalar operation. |
| 102 | */ |
| 103 | void vertex_program_disassembler::decodefields(unsigned int *dwords, int offset, fields &decoded) |
| 104 | { |
| 105 | unsigned int srcbits[3]; |
| 106 | int a; |
| 107 | |
| 108 | srcbits[0] = ((dwords[1 + offset] & 0x1ff) << 6) | (dwords[2 + offset] >> 26); |
| 109 | srcbits[1] = (dwords[2 + offset] >> 11) & 0x7fff; |
| 110 | srcbits[2] = ((dwords[2 + offset] & 0x7ff) << 4) | (dwords[3 + offset] >> 28); |
| 111 | decoded.ScaOperation = (int)(dwords[1 + offset] >> 25) & 0xf; |
| 112 | decoded.VecOperation = (int)(dwords[1 + offset] >> 21) & 0xf; |
| 113 | decoded.SourceConstantIndex = (int)(dwords[1 + offset] >> 13) & 0xff; |
| 114 | decoded.InputIndex = (int)(dwords[1 + offset] >> 9) & 0xf; |
| 115 | for (a = 0; a < 3; a++) |
| 116 | { |
| 117 | decoded.src[a].Sign = (int)(srcbits[a] >> 14) & 1; |
| 118 | decoded.src[a].SwizzleX = (int)(srcbits[a] >> 12) & 3; |
| 119 | decoded.src[a].SwizzleY = (int)(srcbits[a] >> 10) & 3; |
| 120 | decoded.src[a].SwizzleZ = (int)(srcbits[a] >> 8) & 3; |
| 121 | decoded.src[a].SwizzleW = (int)(srcbits[a] >> 6) & 3; |
| 122 | decoded.src[a].TempIndex = (int)(srcbits[a] >> 2) & 0xf; |
| 123 | decoded.src[a].ParameterType = (int)(srcbits[a] >> 0) & 3; |
| 124 | } |
| 125 | |
| 126 | decoded.VecTempWriteMask = (int)(dwords[3 + offset] >> 24) & 0xf; |
| 127 | decoded.VecTempIndex = (int)(dwords[3 + offset] >> 20) & 0xf; |
| 128 | decoded.ScaTempWriteMask = (int)(dwords[3 + offset] >> 16) & 0xf; |
| 129 | decoded.OutputWriteMask = (int)(dwords[3 + offset] >> 12) & 0xf; |
| 130 | decoded.OutputSelect = (int)(dwords[3 + offset] >> 11) & 0x1; |
| 131 | decoded.OutputIndex = (int)(dwords[3 + offset] >> 3) & 0xff; |
| 132 | decoded.MultiplexerControl = (int)(dwords[3 + offset] >> 2) & 0x1; |
| 133 | decoded.Usea0x = (int)(dwords[3 + offset] >> 1) & 0x1; |
| 134 | decoded.EndOfProgram = (int)(dwords[3 + offset] >> 0) & 0x1; |
| 135 | } |
| 136 | |
| 137 | int vertex_program_disassembler::disassemble_mask(int mask, char *s) |
| 138 | { |
| 139 | int l; |
| 140 | |
| 141 | *s = 0; |
| 142 | if (mask == 15) |
| 143 | return 0; |
| 144 | s[0] = '.'; |
| 145 | l = 1; |
| 146 | if ((mask & 8) != 0) { |
| 147 | s[l] = 'x'; |
| 148 | l++; |
| 149 | } |
| 150 | if ((mask & 4) != 0){ |
| 151 | s[l] = 'y'; |
| 152 | l++; |
| 153 | } |
| 154 | if ((mask & 2) != 0){ |
| 155 | s[l] = 'z'; |
| 156 | l++; |
| 157 | } |
| 158 | if ((mask & 1) != 0){ |
| 159 | s[l] = 'w'; |
| 160 | l++; |
| 161 | } |
| 162 | s[l] = 0; |
| 163 | return l; |
| 164 | } |
| 165 | |
| 166 | int vertex_program_disassembler::disassemble_swizzle(sourcefields f, char *s) |
| 167 | { |
| 168 | int t, l; |
| 169 | |
| 170 | t = 4; |
| 171 | if (f.SwizzleW == 3) |
| 172 | { |
| 173 | t = t - 1; |
| 174 | if (f.SwizzleZ == 2) |
| 175 | { |
| 176 | t = t - 1; |
| 177 | if (f.SwizzleY == 1) |
| 178 | { |
| 179 | t = t - 1; |
| 180 | if (f.SwizzleX == 0) |
| 181 | { |
| 182 | t = t - 1; |
| 183 | } |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | *s = 0; |
| 188 | if (t == 0) |
| 189 | return 0; |
| 190 | s[0] = '.'; |
| 191 | l = 1; |
| 192 | if (t > 0) |
| 193 | { |
| 194 | s[l] = compchar[f.SwizzleX]; |
| 195 | l++; |
| 196 | } |
| 197 | if (t > 1) |
| 198 | { |
| 199 | s[l] = compchar[f.SwizzleY]; |
| 200 | l++; |
| 201 | } |
| 202 | if (t > 2) |
| 203 | { |
| 204 | s[l] = compchar[f.SwizzleZ]; |
| 205 | l++; |
| 206 | } |
| 207 | if (t > 3) |
| 208 | { |
| 209 | s[l] = compchar[f.SwizzleW]; |
| 210 | l++; |
| 211 | } |
| 212 | s[l] = 0; |
| 213 | return l; |
| 214 | } |
| 215 | |
| 216 | int vertex_program_disassembler::disassemble_source(sourcefields f, fields fi, char *s) |
| 217 | { |
| 218 | int l; |
| 219 | |
| 220 | if (f.ParameterType == 0) { |
| 221 | strcpy(s, ",???"); |
| 222 | return 4; |
| 223 | } |
| 224 | l = 0; |
| 225 | if (f.Sign != 0) { |
| 226 | s[l] = '-'; |
| 227 | l++; |
| 228 | } |
| 229 | if (f.ParameterType == 1) { |
| 230 | s[l] = 'r'; |
| 231 | l = l + 1 + sprintf(s + l + 1, "%d", f.TempIndex); |
| 232 | } |
| 233 | else if (f.ParameterType == 2){ |
| 234 | s[l] = 'v'; |
| 235 | l = l + 1 + sprintf(s + l + 1, "%d", fi.InputIndex); |
| 236 | } |
| 237 | else |
| 238 | { |
| 239 | if (fi.Usea0x != 0) |
| 240 | { |
| 241 | if (fi.SourceConstantIndex >= 96) { |
| 242 | strcpy(s + l, "c["); |
| 243 | l = l + 2; |
| 244 | l = l + sprintf(s + l, "%d", fi.SourceConstantIndex - 96); |
| 245 | strcpy(s + l, "+a0.x]"); |
| 246 | l = l + 6; |
| 247 | } |
| 248 | else { |
| 249 | strcpy(s + l, "c[a0.x"); |
| 250 | l = l + 6; |
| 251 | l = l + sprintf(s + l, "%d", fi.SourceConstantIndex - 96); |
| 252 | s[l] = ']'; |
| 253 | l++; |
| 254 | } |
| 255 | } |
| 256 | else { |
| 257 | strcpy(s + l, "c["); |
| 258 | l = l + 2; |
| 259 | l = l + sprintf(s + l, "%d", fi.SourceConstantIndex - 96); |
| 260 | s[l] = ']'; |
| 261 | l++; |
| 262 | } |
| 263 | } |
| 264 | l = l + disassemble_swizzle(f, s + l); |
| 265 | s[l] = 0; |
| 266 | return l; |
| 267 | } |
| 268 | |
| 269 | int vertex_program_disassembler::disassemble_output(fields f, char *s) |
| 270 | { |
| 271 | int l; |
| 272 | |
| 273 | if (f.OutputSelect == 1) { |
| 274 | strcpy(s, vecouts[f.OutputIndex]); |
| 275 | return strlen(s); |
| 276 | } |
| 277 | else { |
| 278 | strcpy(s, "c["); |
| 279 | l = 2; |
| 280 | l = l + sprintf(s + l, "%d", f.OutputIndex - 96); |
| 281 | s[l] = ']'; |
| 282 | l++; |
| 283 | } |
| 284 | s[l] = 0; |
| 285 | return l; |
| 286 | } |
| 287 | |
| 288 | int vertex_program_disassembler::output_types(fields f, int *o) |
| 289 | { |
| 290 | o[0] = o[1] = o[2] = o[3] = o[4] = o[5] = 0; |
| 291 | if ((f.VecOperation > 0) && (f.VecTempWriteMask != 0)) |
| 292 | o[0] = 1; |
| 293 | if ((f.VecOperation > 0) && (f.OutputWriteMask != 0) && (f.MultiplexerControl == 0)) |
| 294 | o[1] = 1; |
| 295 | if ((f.ScaOperation > 0) && (f.OutputWriteMask != 0) && (f.MultiplexerControl == 1)) |
| 296 | o[2] = 1; |
| 297 | if ((f.ScaOperation > 0) && (f.ScaTempWriteMask != 0)) |
| 298 | o[3] = 1; |
| 299 | if (f.VecOperation == 13) |
| 300 | o[4] = 1; |
| 301 | if (f.EndOfProgram == 1) |
| 302 | o[5] = 1; |
| 303 | return o[0] + o[1] + o[2] + o[3] + o[4] + o[5]; |
| 304 | } |
| 305 | |
| 306 | int vertex_program_disassembler::disassemble(unsigned int *instruction, char *line) |
| 307 | { |
| 308 | int b, p; |
| 309 | char *c; |
| 310 | |
| 311 | if (state == 0) { |
| 312 | decodefields(instruction, 0, f); |
| 313 | output_types(f, o); |
| 314 | state = 1; |
| 315 | } |
| 316 | if (o[0] != 0) |
| 317 | { |
| 318 | o[0] = 0; |
| 319 | c = line; |
| 320 | strcpy(c, vecops[f.VecOperation]); |
| 321 | c = c + strlen(c); |
| 322 | strcpy(c, " r"); |
| 323 | c = c + 2; |
| 324 | c = c + sprintf(c, "%d", f.VecTempIndex); |
| 325 | c = c + disassemble_mask(f.VecTempWriteMask, c); |
| 326 | b = 0; |
| 327 | for (p = 4; p != 0; p = p >> 1) |
| 328 | { |
| 329 | if ((vecpar2[f.VecOperation] & p) != 0) { |
| 330 | c[0] = ','; |
| 331 | c++; |
| 332 | c = c + disassemble_source(f.src[b], f, c); |
| 333 | } |
| 334 | b++; |
| 335 | } |
| 336 | *c = 0; |
| 337 | return 1; |
| 338 | } |
| 339 | if (o[1] != 0) |
| 340 | { |
| 341 | o[1] = 0; |
| 342 | c = line; |
| 343 | strcpy(c, vecops[f.VecOperation]); |
| 344 | c = c + strlen(c); |
| 345 | *c = ' '; |
| 346 | c++; |
| 347 | c = c + disassemble_output(f, c); |
| 348 | c = c + disassemble_mask(f.OutputWriteMask, c); |
| 349 | b = 0; |
| 350 | for (p = 4; p != 0; p = p >> 1) |
| 351 | { |
| 352 | if ((vecpar2[f.VecOperation] & p) != 0) { |
| 353 | *c = ','; |
| 354 | c++; |
| 355 | c = c + disassemble_source(f.src[b], f, c); |
| 356 | } |
| 357 | b++; |
| 358 | } |
| 359 | *c = 0; |
| 360 | return 1; |
| 361 | } |
| 362 | if (o[2] != 0) |
| 363 | { |
| 364 | o[2] = 0; |
| 365 | c = line; |
| 366 | strcpy(c, scaops[f.ScaOperation]); |
| 367 | c = c + strlen(c); |
| 368 | *c = ' '; |
| 369 | c++; |
| 370 | c = c + disassemble_output(f, c); |
| 371 | c = c + disassemble_mask(f.OutputWriteMask, c); |
| 372 | b = 0; |
| 373 | for (p = 4; p != 0; p = p >> 1) |
| 374 | { |
| 375 | if ((scapar2[f.ScaOperation] & p) != 0) { |
| 376 | *c = ','; |
| 377 | c++; |
| 378 | c = c + disassemble_source(f.src[b], f, c); |
| 379 | } |
| 380 | b++; |
| 381 | } |
| 382 | *c = 0; |
| 383 | return 1; |
| 384 | } |
| 385 | if (o[3] != 0) |
| 386 | { |
| 387 | if (f.VecOperation > 0) |
| 388 | b = 1; |
| 389 | else |
| 390 | b = f.VecTempIndex; |
| 391 | o[3] = 0; |
| 392 | c = line; |
| 393 | strcpy(c, scaops[f.ScaOperation]); |
| 394 | c = c + strlen(c); |
| 395 | strcpy(c, " r"); |
| 396 | c = c + 2; |
| 397 | c = c + sprintf(c, "%d", b); |
| 398 | c = c + disassemble_mask(f.ScaTempWriteMask, c); |
| 399 | b = 0; |
| 400 | for (p = 4; p != 0; p = p >> 1) |
| 401 | { |
| 402 | if ((scapar2[f.ScaOperation] & p) != 0) { |
| 403 | *c = ','; |
| 404 | c++; |
| 405 | c = c + disassemble_source(f.src[b], f, c); |
| 406 | } |
| 407 | b++; |
| 408 | } |
| 409 | *c = 0; |
| 410 | return 1; |
| 411 | } |
| 412 | if (o[4] != 0) |
| 413 | { |
| 414 | o[4] = 0; |
| 415 | c = line; |
| 416 | c = c + sprintf(c, "MOV a0.x,"); |
| 417 | c = c + disassemble_source(f.src[0], f, c); |
| 418 | *c = 0; |
| 419 | return 1; |
| 420 | } |
| 421 | if (o[5] != 0) |
| 422 | { |
| 423 | o[5] = 0; |
| 424 | strcpy(line, "END"); |
| 425 | return 1; |
| 426 | } |
| 427 | state = 0; |
| 428 | return 0; |
| 429 | } |
| 430 | |
| 431 | vertex_program_simulator::vertex_program_simulator() |
| 432 | { |
| 433 | for (int i = 0; i < 256; i++) |
| 434 | op[i].modified = 0; |
| 435 | initialize_constants(); |
| 436 | } |
| 437 | |
| 438 | void vertex_program_simulator::set_data(vertex_nv *in, vertex_nv *out) |
| 439 | { |
| 440 | input = in; |
| 441 | output = out; |
| 442 | } |
| 443 | |
| 444 | void vertex_program_simulator::reset() |
| 445 | { |
| 446 | ip = 0; |
| 447 | a0x = 0; |
| 448 | initialize_outputs(); |
| 449 | initialize_temps(); |
| 450 | } |
| 451 | |
| 452 | void vertex_program_simulator::decode_instruction(int address) |
| 453 | { |
| 454 | instruction *i; |
| 455 | |
| 456 | i = &op[address]; |
| 457 | i->d.SignA = i->i[1] & (1 << 8); |
| 458 | i->d.ParameterTypeA = (i->i[2] >> 26) & 3; |
| 459 | i->d.TempIndexA = (i->i[2] >> 28) & 15; |
| 460 | i->d.SwizzleA[0] = (i->i[1] >> 6) & 3; |
| 461 | i->d.SwizzleA[1] = (i->i[1] >> 4) & 3; |
| 462 | i->d.SwizzleA[2] = (i->i[1] >> 2) & 3; |
| 463 | i->d.SwizzleA[3] = (i->i[1] >> 0) & 3; |
| 464 | i->d.SignB = i->i[2] & (1 << 25); |
| 465 | i->d.ParameterTypeB = (i->i[2] >> 11) & 3; |
| 466 | i->d.TempIndexB = (i->i[2] >> 13) & 15; |
| 467 | i->d.SwizzleB[0] = (i->i[2] >> 23) & 3; |
| 468 | i->d.SwizzleB[1] = (i->i[2] >> 21) & 3; |
| 469 | i->d.SwizzleB[2] = (i->i[2] >> 19) & 3; |
| 470 | i->d.SwizzleB[3] = (i->i[2] >> 17) & 3; |
| 471 | i->d.SignC = i->i[2] & (1 << 10); |
| 472 | i->d.ParameterTypeC = (i->i[3] >> 28) & 3; |
| 473 | i->d.TempIndexC = ((i->i[2] & 3) << 2) + (i->i[3] >> 30); |
| 474 | i->d.SwizzleC[0] = (i->i[2] >> 8) & 3; |
| 475 | i->d.SwizzleC[1] = (i->i[2] >> 6) & 3; |
| 476 | i->d.SwizzleC[2] = (i->i[2] >> 4) & 3; |
| 477 | i->d.SwizzleC[3] = (i->i[2] >> 2) & 3; |
| 478 | i->d.VecOperation = (i->i[1] >> 21) & 15; |
| 479 | i->d.ScaOperation = (i->i[1] >> 25) & 15; |
| 480 | i->d.OutputWriteMask = ((i->i[3] >> 12) & 15); |
| 481 | i->d.MultiplexerControl = i->i[3] & 4; // 0 : output Rn from vectorial operation 4 : output Rn from scalar operation |
| 482 | i->d.VecTempIndex = (i->i[3] >> 20) & 15; |
| 483 | i->d.OutputIndex = (i->i[3] >> 3) & 255; |
| 484 | i->d.OutputSelect = i->i[3] & 0x800; |
| 485 | i->d.VecTempWriteMask = (i->i[3] >> 24) & 15; |
| 486 | i->d.ScaTempWriteMask = (i->i[3] >> 16) & 15; |
| 487 | i->d.InputIndex = (i->i[1] >> 9) & 15; |
| 488 | i->d.SourceConstantIndex = (i->i[1] >> 13) & 255; |
| 489 | i->d.Usea0x = i->i[3] & 2; |
| 490 | i->d.EndOfProgram = i->i[3] & 1; |
| 491 | } |
| 492 | |
| 493 | int vertex_program_simulator::step() |
| 494 | { |
| 495 | int p1, p2; |
| 496 | float tmp[3 * 4]; |
| 497 | float tmpv[4]; |
| 498 | float tmps[4]; |
| 499 | instruction::decoded *d; |
| 500 | |
| 501 | #if 0 // useful while debugging to see what instrucion is being executed |
| 502 | static int debugvpi = 0; |
| 503 | char disbuffer[256]; |
| 504 | if (debugvpi) { |
| 505 | char *pp; |
| 506 | vertex_program_disassembler vdis; |
| 507 | |
| 508 | pp = disbuffer; |
| 509 | while (vdis.disassemble(op[ip].i, pp) != 0) { |
| 510 | pp = pp + strlen(pp); |
| 511 | *pp = '\n'; |
| 512 | pp++; |
| 513 | *pp = 0; |
| 514 | } |
| 515 | } |
| 516 | #endif |
| 517 | |
| 518 | if (op[ip].modified) |
| 519 | decode_instruction(ip); |
| 520 | d = &(op[ip].d); |
| 521 | // prepare inputs |
| 522 | // input A |
| 523 | generate_input(&tmp[0], d->SignA, d->ParameterTypeA, d->TempIndexA, d->SwizzleA); |
| 524 | // input B |
| 525 | generate_input(&tmp[4], d->SignB, d->ParameterTypeB, d->TempIndexB, d->SwizzleB); |
| 526 | // input C |
| 527 | generate_input(&tmp[8], d->SignC, d->ParameterTypeC, d->TempIndexC, d->SwizzleC); |
| 528 | // compute 2 instructions |
| 529 | // vectorial |
| 530 | compute_vectorial_operation(tmpv, d->VecOperation, tmp); |
| 531 | // scalar |
| 532 | compute_scalar_operation(tmps, d->ScaOperation, tmp); |
| 533 | // assign destinations |
| 534 | if (d->VecOperation > 0) { |
| 535 | if (d->VecOperation == 13) |
| 536 | //o[4] = 1; |
| 537 | a0x = (int)tmpv[0]; |
| 538 | else { |
| 539 | if (d->VecTempWriteMask != 0) { // assign to Rn |
| 540 | //o[0] = 1; |
| 541 | int wm = d->VecTempWriteMask; |
| 542 | for (p1 = 0; p1 < 4; p1++) { |
| 543 | if (wm & 8) |
| 544 | r_temp[d->VecTempIndex].fv[p1] = tmpv[p1]; |
| 545 | wm = wm << 1; |
| 546 | } |
| 547 | } |
| 548 | if ((d->OutputWriteMask != 0) && (d->MultiplexerControl == 0)) { |
| 549 | //o[1] = 1; |
| 550 | if (d->OutputSelect) { // assign to output |
| 551 | int wm = d->OutputWriteMask; |
| 552 | for (p1 = 0; p1 < 4; p1++) { |
| 553 | if (wm & 8) |
| 554 | output->attribute[d->OutputIndex].fv[p1] = tmpv[p1]; |
| 555 | wm = wm << 1; |
| 556 | } |
| 557 | // remeber, output position == r12 |
| 558 | if (d->OutputIndex == 0) |
| 559 | for (p1 = 0; p1 < 4; p1++) { |
| 560 | r_temp[12].fv[p1] = output->attribute[d->OutputIndex].fv[p1]; |
| 561 | } |
| 562 | } |
| 563 | else { // assign to constant |
| 564 | int wm = d->OutputWriteMask; |
| 565 | for (p1 = 0; p1 < 4; p1++) { |
| 566 | if (wm & 8) |
| 567 | c_constant[d->OutputIndex].fv[p1] = tmpv[p1]; |
| 568 | wm = wm << 1; |
| 569 | } |
| 570 | } |
| 571 | } |
| 572 | } |
| 573 | } |
| 574 | if (d->ScaOperation > 0) { |
| 575 | if (d->ScaTempWriteMask != 0) { // assign to Rn |
| 576 | //o[3] = 1; |
| 577 | if (d->VecOperation > 0) |
| 578 | p2 = 1; |
| 579 | else |
| 580 | p2 = d->VecTempIndex; |
| 581 | int wm = d->ScaTempWriteMask; |
| 582 | for (p1 = 0; p1 < 4; p1++) { |
| 583 | if (wm & 8) |
| 584 | r_temp[p2].fv[p1] = tmps[p1]; |
| 585 | wm = wm << 1; |
| 586 | } |
| 587 | } |
| 588 | if ((d->OutputWriteMask != 0) && (d->MultiplexerControl != 0)) { // assign to output |
| 589 | //o[2] = 1; |
| 590 | int wm = d->OutputWriteMask; |
| 591 | for (p1 = 0; p1 < 4; p1++) { |
| 592 | if (wm & 8) |
| 593 | output->attribute[d->OutputIndex].fv[p1] = tmps[p1]; |
| 594 | wm = wm << 1; |
| 595 | } |
| 596 | // remeber, output position == r12 |
| 597 | if (d->OutputIndex == 0) { |
| 598 | for (p1 = 0; p1 < 4; p1++) { |
| 599 | r_temp[12].fv[p1] = output->attribute[d->OutputIndex].fv[p1]; |
| 600 | } |
| 601 | } |
| 602 | } |
| 603 | } |
| 604 | return d->EndOfProgram; |
| 605 | } |
| 606 | |
| 607 | void vertex_program_simulator::execute() |
| 608 | { |
| 609 | int c; |
| 610 | |
| 611 | c = 0; |
| 612 | do { |
| 613 | c = step(); |
| 614 | ip++; |
| 615 | } while (c == 0); |
| 616 | } |
| 617 | |
| 618 | void vertex_program_simulator::jump(int address) |
| 619 | { |
| 620 | ip = address; |
| 621 | } |
| 622 | |
| 623 | void vertex_program_simulator::process(int address, vertex_nv *in, vertex_nv *out, int count) |
| 624 | { |
| 625 | #if 0 // useful while debugging to see what is being executed |
| 626 | static int debugvps = 0; |
| 627 | if (debugvps) { |
| 628 | char *pp; |
| 629 | vertex_program_disassembler vdis; |
| 630 | char disbuffer[128]; |
| 631 | |
| 632 | jump(address); |
| 633 | debugvps--; |
| 634 | for (int t = 0; t < 128; t++) { |
| 635 | pp = disbuffer; |
| 636 | while (vdis.disassemble(op[ip + t].i, pp) != 0) { |
| 637 | pp = pp + strlen(pp); |
| 638 | *pp = '\n'; |
| 639 | pp++; |
| 640 | *pp = 0; |
| 641 | } |
| 642 | printf("%08X %08X %08X %s", op[ip + t].i[1], op[ip + t].i[2], op[ip + t].i[3], disbuffer); |
| 643 | if (op[ip + t].i[3] & 1) |
| 644 | break; |
| 645 | } |
| 646 | } |
| 647 | #endif |
| 648 | set_data(in, out); |
| 649 | while (count > 0) { |
| 650 | reset(); |
| 651 | jump(address); |
| 652 | execute(); |
| 653 | input++; |
| 654 | output++; |
| 655 | count--; |
| 656 | } |
| 657 | } |
| 658 | |
| 659 | int vertex_program_simulator::status() |
| 660 | { |
| 661 | return ip; |
| 662 | } |
| 663 | |
| 664 | void vertex_program_simulator::initialize_outputs() |
| 665 | { |
| 666 | for (int n = 0; n < 16; n++) { |
| 667 | output->attribute[n].fv[0] = output->attribute[n].fv[1] = output->attribute[n].fv[2] = 0; |
| 668 | output->attribute[n].fv[3] = 1; |
| 669 | } |
| 670 | } |
| 671 | |
| 672 | void vertex_program_simulator::initialize_temps() |
| 673 | { |
| 674 | for (int n = 0; n < 32; n++) { |
| 675 | for (int m = 0; m < 4; m++) |
| 676 | r_temp[n].fv[m] = 0; |
| 677 | } |
| 678 | } |
| 679 | |
| 680 | void vertex_program_simulator::initialize_constants() |
| 681 | { |
| 682 | for (int n = 0; n < 192; n++) { |
| 683 | for (int m = 0; m < 4;m++) |
| 684 | c_constant[n].fv[m] = 0; |
| 685 | } |
| 686 | } |
| 687 | |
| 688 | void vertex_program_simulator::generate_input(float t[4], int sign, int type, int temp, int swizzle[4]) |
| 689 | { |
| 690 | float sgn = 1; |
| 691 | |
| 692 | if (sign) |
| 693 | sgn = -1; |
| 694 | if (type == 1) { |
| 695 | t[0] = sgn*r_temp[temp].fv[swizzle[0]]; |
| 696 | t[1] = sgn*r_temp[temp].fv[swizzle[1]]; |
| 697 | t[2] = sgn*r_temp[temp].fv[swizzle[2]]; |
| 698 | t[3] = sgn*r_temp[temp].fv[swizzle[3]]; |
| 699 | } |
| 700 | else if (type == 2) { |
| 701 | int InputIndex = op[ip].d.InputIndex; |
| 702 | t[0] = sgn*input->attribute[InputIndex].fv[swizzle[0]]; |
| 703 | t[1] = sgn*input->attribute[InputIndex].fv[swizzle[1]]; |
| 704 | t[2] = sgn*input->attribute[InputIndex].fv[swizzle[2]]; |
| 705 | t[3] = sgn*input->attribute[InputIndex].fv[swizzle[3]]; |
| 706 | } |
| 707 | else if (type == 3) { |
| 708 | int SourceConstantIndex = op[ip].d.SourceConstantIndex; |
| 709 | if (op[ip].d.Usea0x) |
| 710 | SourceConstantIndex = SourceConstantIndex + a0x; |
| 711 | t[0] = sgn*c_constant[SourceConstantIndex].fv[swizzle[0]]; |
| 712 | t[1] = sgn*c_constant[SourceConstantIndex].fv[swizzle[1]]; |
| 713 | t[2] = sgn*c_constant[SourceConstantIndex].fv[swizzle[2]]; |
| 714 | t[3] = sgn*c_constant[SourceConstantIndex].fv[swizzle[3]]; |
| 715 | } |
| 716 | } |
| 717 | |
| 718 | void vertex_program_simulator::compute_vectorial_operation(float t_out[4], int instruction, float par_in[3 * 4]) |
| 719 | { |
| 720 | const int p1_A = 0; |
| 721 | const int p2_B = 4; |
| 722 | const int p3_C = 8; |
| 723 | |
| 724 | // t_out <= instruction(par_in) |
| 725 | switch (instruction) { |
| 726 | case 0: // "NOP" |
| 727 | break; |
| 728 | case 1: // "MOV" |
| 729 | t_out[0] = par_in[p1_A + 0]; |
| 730 | t_out[1] = par_in[p1_A + 1]; |
| 731 | t_out[2] = par_in[p1_A + 2]; |
| 732 | t_out[3] = par_in[p1_A + 3]; |
| 733 | break; |
| 734 | case 2: // "MUL" |
| 735 | t_out[0] = par_in[p1_A + 0] * par_in[p2_B + 0]; |
| 736 | t_out[1] = par_in[p1_A + 1] * par_in[p2_B + 1]; |
| 737 | t_out[2] = par_in[p1_A + 2] * par_in[p2_B + 2]; |
| 738 | t_out[3] = par_in[p1_A + 3] * par_in[p2_B + 3]; |
| 739 | break; |
| 740 | case 3: // "ADD" |
| 741 | t_out[0] = par_in[p1_A + 0] + par_in[p3_C + 0]; |
| 742 | t_out[1] = par_in[p1_A + 1] + par_in[p3_C + 1]; |
| 743 | t_out[2] = par_in[p1_A + 2] + par_in[p3_C + 2]; |
| 744 | t_out[3] = par_in[p1_A + 3] + par_in[p3_C + 3]; |
| 745 | break; |
| 746 | case 4: // "MAD" |
| 747 | t_out[0] = par_in[p1_A + 0] * par_in[p2_B + 0] + par_in[p3_C + 0]; |
| 748 | t_out[1] = par_in[p1_A + 1] * par_in[p2_B + 1] + par_in[p3_C + 1]; |
| 749 | t_out[2] = par_in[p1_A + 2] * par_in[p2_B + 2] + par_in[p3_C + 2]; |
| 750 | t_out[3] = par_in[p1_A + 3] * par_in[p2_B + 3] + par_in[p3_C + 3]; |
| 751 | break; |
| 752 | case 5: // "DP3" |
| 753 | t_out[0] = par_in[p1_A + 0] * par_in[p2_B + 0] + par_in[p1_A + 1] * par_in[p2_B + 1] + par_in[p1_A + 2] * par_in[p2_B + 2]; |
| 754 | t_out[1] = t_out[2] = t_out[3] = t_out[0]; |
| 755 | break; |
| 756 | case 6: // "DPH" |
| 757 | t_out[0] = par_in[p1_A + 0] * par_in[p2_B + 0] + par_in[p1_A + 1] * par_in[p2_B + 1] + par_in[p1_A + 2] * par_in[p2_B + 2] + par_in[p2_B + 3]; |
| 758 | t_out[1] = t_out[2] = t_out[3] = t_out[0]; |
| 759 | break; |
| 760 | case 7: // "DP4" |
| 761 | t_out[0] = par_in[p1_A + 0] * par_in[p2_B + 0] + par_in[p1_A + 1] * par_in[p2_B + 1] + par_in[p1_A + 2] * par_in[p2_B + 2] + par_in[p1_A + 3] * par_in[p2_B + 3]; |
| 762 | t_out[1] = t_out[2] = t_out[3] = t_out[0]; |
| 763 | break; |
| 764 | case 8: // "DST" |
| 765 | t_out[0] = 1.0; |
| 766 | t_out[1] = par_in[p1_A + 1] * par_in[p2_B + 1]; |
| 767 | t_out[2] = par_in[p1_A + 2]; |
| 768 | t_out[3] = par_in[p2_B + 3]; |
| 769 | break; |
| 770 | case 9: // "MIN" |
| 771 | t_out[0] = fmin(par_in[p1_A + 0], par_in[p2_B + 0]); |
| 772 | t_out[1] = fmin(par_in[p1_A + 1], par_in[p2_B + 1]); |
| 773 | t_out[2] = fmin(par_in[p1_A + 2], par_in[p2_B + 2]); |
| 774 | t_out[3] = fmin(par_in[p1_A + 3], par_in[p2_B + 3]); |
| 775 | break; |
| 776 | case 10: // "MAX" |
| 777 | t_out[0] = fmax(par_in[p1_A + 0], par_in[p2_B + 0]); |
| 778 | t_out[1] = fmax(par_in[p1_A + 1], par_in[p2_B + 1]); |
| 779 | t_out[2] = fmax(par_in[p1_A + 2], par_in[p2_B + 2]); |
| 780 | t_out[3] = fmax(par_in[p1_A + 3], par_in[p2_B + 3]); |
| 781 | break; |
| 782 | case 11: // "SLT" |
| 783 | t_out[0] = (par_in[p1_A + 0] < par_in[p2_B + 0]) ? 1.0 : 0; |
| 784 | t_out[1] = (par_in[p1_A + 1] < par_in[p2_B + 1]) ? 1.0 : 0; |
| 785 | t_out[2] = (par_in[p1_A + 2] < par_in[p2_B + 2]) ? 1.0 : 0; |
| 786 | t_out[3] = (par_in[p1_A + 3] < par_in[p2_B + 3]) ? 1.0 : 0; |
| 787 | break; |
| 788 | case 12: // "SGE" |
| 789 | t_out[0] = (par_in[p1_A + 0] >= par_in[p2_B + 0]) ? 1.0 : 0; |
| 790 | t_out[1] = (par_in[p1_A + 1] >= par_in[p2_B + 1]) ? 1.0 : 0; |
| 791 | t_out[2] = (par_in[p1_A + 2] >= par_in[p2_B + 2]) ? 1.0 : 0; |
| 792 | t_out[3] = (par_in[p1_A + 3] >= par_in[p2_B + 3]) ? 1.0 : 0; |
| 793 | break; |
| 794 | case 13: // "ARL" |
| 795 | t_out[0] = par_in[p1_A + 0]; |
| 796 | } |
| 797 | } |
| 798 | |
| 799 | void vertex_program_simulator::compute_scalar_operation(float t_out[4], int instruction, float par_in[3 * 4]) |
| 800 | { |
| 801 | //const int p1_A = 0; |
| 802 | //const int p2_B = 4; |
| 803 | const int p3_C = 8; |
| 804 | union { |
| 805 | float f; |
| 806 | unsigned int i; |
| 807 | } t; |
| 808 | int e; |
| 809 | |
| 810 | // t_out <= instruction(par_in) |
| 811 | switch (instruction) { |
| 812 | case 0: // "NOP" |
| 813 | break; |
| 814 | case 1: // "IMV" |
| 815 | t_out[0] = par_in[p3_C + 0]; |
| 816 | t_out[1] = par_in[p3_C + 1]; |
| 817 | t_out[2] = par_in[p3_C + 2]; |
| 818 | t_out[3] = par_in[p3_C + 3]; |
| 819 | break; |
| 820 | case 2: // "RCP" |
| 821 | t_out[0] = t_out[1] = t_out[2] = t_out[3] = 1.0 / par_in[p3_C + 0]; |
| 822 | break; |
| 823 | case 3: // "RCC" |
| 824 | t_out[0] = t_out[1] = t_out[2] = t_out[3] = 1.0 / par_in[p3_C + 0]; // ? |
| 825 | break; |
| 826 | case 4: // "RSQ" |
| 827 | t_out[0] = t_out[1] = t_out[2] = t_out[3] = 1.0 / sqrt(abs(par_in[p3_C + 0])); |
| 828 | break; |
| 829 | case 5: // "EXP" |
| 830 | t_out[0] = pow(2, floor(par_in[p3_C + 0])); |
| 831 | t_out[1] = par_in[p3_C + 0] - floor(par_in[p3_C + 0]); |
| 832 | t.f = pow(2, par_in[p3_C + 0]); |
| 833 | t.i = t.i & 0xffffff00; |
| 834 | t_out[2] = t.f; |
| 835 | t_out[3] = 1.0; |
| 836 | break; |
| 837 | case 6: // "LOG" |
| 838 | t_out[1] = frexp(par_in[p3_C + 0], &e)*2.0; // frexp gives mantissa as 0.5....1 |
| 839 | t_out[0] = e - 1; |
| 840 | t.f = log2(abs(par_in[p3_C + 0])); |
| 841 | t.i = t.i & 0xffffff00; |
| 842 | t_out[2] = t.f; |
| 843 | t_out[3] = 1.0; |
| 844 | break; |
| 845 | case 7: // "LIT" |
| 846 | t_out[0] = 1.0; |
| 847 | t_out[1] = fmax(0, fmin(par_in[p3_C + 0], 1.0f)); |
| 848 | t_out[2] = par_in[p3_C + 0] > 0 ? pow(fmax(par_in[p3_C + 1], 0), par_in[p3_C + 3]) : 0; |
| 849 | t_out[3] = 1.0; |
| 850 | break; |
| 851 | } |
| 852 | } |
| 853 | |
| 854 | /* |
| 855 | * Graphics |
| 856 | */ |
| 857 | |
| 858 | UINT32 nv2a_renderer::dilate0(UINT32 value, int bits) // dilate first "bits" bits in "value" |
| 859 | { |
| 860 | UINT32 x, m1, m2, m3; |
| 861 | int a; |
| 862 | |
| 863 | x = value; |
| 864 | for (a = 0; a < bits; a++) |
| 865 | { |
| 866 | m2 = 1 << (a << 1); |
| 867 | m1 = m2 - 1; |
| 868 | m3 = (~m1) << 1; |
| 869 | x = (x & m1) + (x & m2) + ((x & m3) << 1); |
| 870 | } |
| 871 | return x; |
| 872 | } |
| 873 | |
| 874 | UINT32 nv2a_renderer::dilate1(UINT32 value, int bits) // dilate first "bits" bits in "value" |
| 875 | { |
| 876 | UINT32 x, m1, m2, m3; |
| 877 | int a; |
| 878 | |
| 879 | x = value; |
| 880 | for (a = 0; a < bits; a++) |
| 881 | { |
| 882 | m2 = 1 << (a << 1); |
| 883 | m1 = m2 - 1; |
| 884 | m3 = (~m1) << 1; |
| 885 | x = (x & m1) + ((x & m2) << 1) + ((x & m3) << 1); |
| 886 | } |
| 887 | return x; |
| 888 | } |
| 889 | |
| 890 | void nv2a_renderer::computedilated(void) |
| 891 | { |
| 892 | int a, b; |
| 893 | |
| 894 | for (b = 0; b < 16; b++) |
| 895 | for (a = 0; a < 2048; a++) { |
| 896 | dilated0[b][a] = dilate0(a, b); |
| 897 | dilated1[b][a] = dilate1(a, b); |
| 898 | } |
| 899 | for (b = 0; b < 16; b++) |
| 900 | for (a = 0; a < 16; a++) |
| 901 | dilatechose[(b << 4) + a] = (a < b ? a : b); |
| 902 | } |
| 903 | |
| 904 | int nv2a_renderer::geforce_commandkind(UINT32 word) |
| 905 | { |
| 906 | if ((word & 0x00000003) == 0x00000002) |
| 907 | return 7; // call |
| 908 | if ((word & 0x00000003) == 0x00000001) |
| 909 | return 6; // jump |
| 910 | if ((word & 0xE0030003) == 0x40000000) |
| 911 | return 5; // non increasing |
| 912 | if ((word & 0xE0000003) == 0x20000000) |
| 913 | return 4; // old jump |
| 914 | if ((word & 0xFFFF0003) == 0x00030000) |
| 915 | return 3; // long non icreasing |
| 916 | if ((word & 0xFFFFFFFF) == 0x00020000) |
| 917 | return 2; // return |
| 918 | if ((word & 0xFFFF0003) == 0x00010000) |
| 919 | return 1; // sli conditional |
| 920 | if ((word & 0xE0030003) == 0x00000000) |
| 921 | return 0; // increasing |
| 922 | return -1; |
| 923 | } |
| 924 | |
| 925 | UINT32 nv2a_renderer::geforce_object_offset(UINT32 handle) |
| 926 | { |
| 927 | UINT32 h = ((((handle >> 11) ^ handle) >> 11) ^ handle) & 0x7ff; |
| 928 | UINT32 o = (pfifo[0x210 / 4] & 0x1f) << 8; // or 12 ? |
| 929 | UINT32 e = o + h * 8; // at 0xfd000000+0x00700000 |
| 930 | UINT32 w; |
| 931 | |
| 932 | if (ramin[e / 4] != handle) |
| 933 | e = 0; |
| 934 | w = ramin[e / 4 + 1]; |
| 935 | return (w & 0xffff) * 0x10; |
| 936 | } |
| 937 | |
| 938 | void nv2a_renderer::geforce_read_dma_object(UINT32 handle, UINT32 &offset, UINT32 &size) |
| 939 | { |
| 940 | //UINT32 objclass,pt_present,pt_linear,access,target,rorw; |
| 941 | UINT32 dma_adjust, dma_frame; |
| 942 | UINT32 o = geforce_object_offset(handle); |
| 943 | |
| 944 | o = o / 4; |
| 945 | //objclass=ramin[o] & 0xfff; |
| 946 | //pt_present=(ramin[o] >> 12) & 1; |
| 947 | //pt_linear=(ramin[o] >> 13) & 1; |
| 948 | //access=(ramin[o] >> 14) & 3; |
| 949 | //target=(ramin[o] >> 16) & 3; |
| 950 | dma_adjust = (ramin[o] >> 20) & 0xfff; |
| 951 | size = ramin[o + 1]; |
| 952 | //rorw=ramin[o+2] & 1; |
| 953 | dma_frame = ramin[o + 2] & 0xfffff000; |
| 954 | offset = dma_frame + dma_adjust; |
| 955 | } |
| 956 | |
| 957 | /*void myline(bitmap_rgb32 &bmp,float x1,float y1,float x2,float y2) |
| 958 | { |
| 959 | int xx1,yy1,xx2,yy2; |
| 960 | |
| 961 | xx1=x1; |
| 962 | xx2=x2; |
| 963 | yy1=y1; |
| 964 | yy2=y2; |
| 965 | if (xx1 == xx2) { |
| 966 | if (yy1 > yy2) { |
| 967 | int t=yy1; |
| 968 | yy1=yy2; |
| 969 | yy2=t; |
| 970 | } |
| 971 | for (int y=yy1;y <= yy2;y++) |
| 972 | *((UINT32 *)bmp.raw_pixptr(y,xx1))= -1; |
| 973 | } else if (yy1 == yy2) { |
| 974 | if (xx1 > xx2) { |
| 975 | int t=xx1; |
| 976 | xx1=xx2; |
| 977 | xx2=t; |
| 978 | } |
| 979 | for (int x=xx1;x <= xx2;x++) |
| 980 | *((UINT32 *)bmp.raw_pixptr(yy1,x))= -1; |
| 981 | } |
| 982 | }*/ |
| 983 | |
| 984 | inline UINT32 convert_a4r4g4b4_a8r8g8b8(UINT32 a4r4g4b4) |
| 985 | { |
| 986 | UINT32 a8r8g8b8; |
| 987 | int ca, cr, cg, cb; |
| 988 | |
| 989 | cb = pal4bit(a4r4g4b4 & 0x000f); |
| 990 | cg = pal4bit((a4r4g4b4 & 0x00f0) >> 4); |
| 991 | cr = pal4bit((a4r4g4b4 & 0x0f00) >> 8); |
| 992 | ca = pal4bit((a4r4g4b4 & 0xf000) >> 12); |
| 993 | a8r8g8b8 = (ca << 24) | (cr << 16) | (cg << 8) | (cb); // color converted to 8 bits per component |
| 994 | return a8r8g8b8; |
| 995 | } |
| 996 | |
| 997 | inline UINT32 convert_a1r5g5b5_a8r8g8b8(UINT32 a1r5g5b5) |
| 998 | { |
| 999 | UINT32 a8r8g8b8; |
| 1000 | int ca, cr, cg, cb; |
| 1001 | |
| 1002 | cb = pal5bit(a1r5g5b5 & 0x001f); |
| 1003 | cg = pal5bit((a1r5g5b5 & 0x03e0) >> 5); |
| 1004 | cr = pal5bit((a1r5g5b5 & 0x7c00) >> 10); |
| 1005 | ca = a1r5g5b5 & 0x8000 ? 0xff : 0; |
| 1006 | a8r8g8b8 = (ca << 24) | (cr << 16) | (cg << 8) | (cb); // color converted to 8 bits per component |
| 1007 | return a8r8g8b8; |
| 1008 | } |
| 1009 | |
| 1010 | inline UINT32 convert_r5g6b5_r8g8b8(UINT32 r5g6b5) |
| 1011 | { |
| 1012 | UINT32 r8g8b8; |
| 1013 | int cr, cg, cb; |
| 1014 | |
| 1015 | cb = pal5bit(r5g6b5 & 0x001f); |
| 1016 | cg = pal6bit((r5g6b5 & 0x07e0) >> 5); |
| 1017 | cr = pal5bit((r5g6b5 & 0xf800) >> 11); |
| 1018 | r8g8b8 = (cr << 16) | (cg << 8) | (cb); // color converted to 8 bits per component |
| 1019 | return r8g8b8; |
| 1020 | } |
| 1021 | |
| 1022 | UINT32 nv2a_renderer::texture_get_texel(int number, int x, int y) |
| 1023 | { |
| 1024 | UINT32 to, s, c, sa, ca; |
| 1025 | UINT32 a4r4g4b4, a1r5g5b5, r5g6b5; |
| 1026 | int bx, by; |
| 1027 | int color0, color1, color0m2, color1m2, alpha0, alpha1; |
| 1028 | UINT32 codes; |
| 1029 | UINT64 alphas; |
| 1030 | int cr, cg, cb; |
| 1031 | |
| 1032 | // force to [0,size-1] |
| 1033 | x = (unsigned int)x & (texture[number].sizeu - 1); |
| 1034 | y = (unsigned int)y & (texture[number].sizev - 1); |
| 1035 | switch (texture[number].format) { |
| 1036 | case A8R8G8B8: |
| 1037 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1038 | return *(((UINT32 *)texture[number].buffer) + to); // get texel color |
| 1039 | case DXT1: |
| 1040 | bx = x >> 2; |
| 1041 | by = y >> 2; |
| 1042 | x = x & 3; |
| 1043 | y = y & 3; |
| 1044 | to = bx + by*(texture[number].sizeu >> 2); |
| 1045 | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 0); |
| 1046 | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 1); |
| 1047 | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 1); |
| 1048 | s = (y << 3) + (x << 1); |
| 1049 | c = (codes >> s) & 3; |
| 1050 | c = c + (color0 > color1 ? 0 : 4); |
| 1051 | color0m2 = color0 << 1; |
| 1052 | color1m2 = color1 << 1; |
| 1053 | switch (c) { |
| 1054 | case 0: |
| 1055 | return 0xff000000 + convert_r5g6b5_r8g8b8(color0); |
| 1056 | case 1: |
| 1057 | return 0xff000000 + convert_r5g6b5_r8g8b8(color1); |
| 1058 | case 2: |
| 1059 | cb = pal5bit(((color0m2 & 0x003e) + (color1 & 0x001f)) / 3); |
| 1060 | cg = pal6bit(((color0m2 & 0x0fc0) + (color1 & 0x07e0)) / 3 >> 5); |
| 1061 | cr = pal5bit(((color0m2 & 0x1f000) + color1) / 3 >> 11); |
| 1062 | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); |
| 1063 | case 3: |
| 1064 | cb = pal5bit(((color1m2 & 0x003e) + (color0 & 0x001f)) / 3); |
| 1065 | cg = pal6bit(((color1m2 & 0x0fc0) + (color0 & 0x07e0)) / 3 >> 5); |
| 1066 | cr = pal5bit(((color1m2 & 0x1f000) + color0) / 3 >> 11); |
| 1067 | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); |
| 1068 | case 4: |
| 1069 | return 0xff000000 + convert_r5g6b5_r8g8b8(color0); |
| 1070 | case 5: |
| 1071 | return 0xff000000 + convert_r5g6b5_r8g8b8(color1); |
| 1072 | case 6: |
| 1073 | cb = pal5bit(((color0 & 0x001f) + (color1 & 0x001f)) / 2); |
| 1074 | cg = pal6bit(((color0 & 0x07e0) + (color1 & 0x07e0)) / 2 >> 5); |
| 1075 | cr = pal5bit(((color0 & 0xf800) + (color1 & 0xf800)) / 2 >> 11); |
| 1076 | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); |
| 1077 | default: |
| 1078 | return 0xff000000; |
| 1079 | } |
| 1080 | case DXT3: |
| 1081 | bx = x >> 2; |
| 1082 | by = y >> 2; |
| 1083 | x = x & 3; |
| 1084 | y = y & 3; |
| 1085 | to = (bx + by*(texture[number].sizeu >> 2)) << 1; |
| 1086 | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 4); |
| 1087 | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 5); |
| 1088 | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 3); |
| 1089 | alphas = *(((UINT64 *)texture[number].buffer) + to); |
| 1090 | s = (y << 3) + (x << 1); |
| 1091 | sa = ((y << 2) + x) << 2; |
| 1092 | c = (codes >> s) & 3; |
| 1093 | ca = (alphas >> sa) & 15; |
| 1094 | switch (c) { |
| 1095 | case 0: |
| 1096 | return ((ca + (ca << 4)) << 24) + convert_r5g6b5_r8g8b8(color0); |
| 1097 | case 1: |
| 1098 | return ((ca + (ca << 4)) << 24) + convert_r5g6b5_r8g8b8(color1); |
| 1099 | case 2: |
| 1100 | cb = pal5bit((2 * (color0 & 0x001f) + (color1 & 0x001f)) / 3); |
| 1101 | cg = pal6bit((2 * (color0 & 0x07e0) + (color1 & 0x07e0)) / 3 >> 5); |
| 1102 | cr = pal5bit((2 * (color0 & 0xf800) + (color1 & 0xf800)) / 3 >> 11); |
| 1103 | return ((ca + (ca << 4)) << 24) | (cr << 16) | (cg << 8) | (cb); |
| 1104 | default: |
| 1105 | cb = pal5bit(((color0 & 0x001f) + 2 * (color1 & 0x001f)) / 3); |
| 1106 | cg = pal6bit(((color0 & 0x07e0) + 2 * (color1 & 0x07e0)) / 3 >> 5); |
| 1107 | cr = pal5bit(((color0 & 0xf800) + 2 * (color1 & 0xf800)) / 3 >> 11); |
| 1108 | return ((ca + (ca << 4)) << 24) | (cr << 16) | (cg << 8) | (cb); |
| 1109 | } |
| 1110 | case A4R4G4B4: |
| 1111 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1112 | a4r4g4b4 = *(((UINT16 *)texture[number].buffer) + to); // get texel color |
| 1113 | return convert_a4r4g4b4_a8r8g8b8(a4r4g4b4); |
| 1114 | case A1R5G5B5: |
| 1115 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1116 | a1r5g5b5 = *(((UINT16 *)texture[number].buffer) + to); // get texel color |
| 1117 | return convert_a1r5g5b5_a8r8g8b8(a1r5g5b5); |
| 1118 | case R5G6B5: |
| 1119 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1120 | r5g6b5 = *(((UINT16 *)texture[number].buffer) + to); // get texel color |
| 1121 | return 0xff000000 + convert_r5g6b5_r8g8b8(r5g6b5); |
| 1122 | case R8G8B8_RECT: |
| 1123 | to = texture[number].rectangle_pitch*y + (x << 2); |
| 1124 | return *((UINT32 *)(((UINT8 *)texture[number].buffer) + to)); |
| 1125 | case A8R8G8B8_RECT: |
| 1126 | to = texture[number].rectangle_pitch*y + (x << 2); |
| 1127 | return *((UINT32 *)(((UINT8 *)texture[number].buffer) + to)); |
| 1128 | case DXT5: |
| 1129 | bx = x >> 2; |
| 1130 | by = y >> 2; |
| 1131 | x = x & 3; |
| 1132 | y = y & 3; |
| 1133 | to = (bx + by*(texture[number].sizeu >> 2)) << 1; |
| 1134 | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 4); |
| 1135 | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 5); |
| 1136 | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 3); |
| 1137 | alpha0 = *((UINT8 *)(((UINT64 *)texture[number].buffer) + to) + 0); |
| 1138 | alpha1 = *((UINT8 *)(((UINT64 *)texture[number].buffer) + to) + 1); |
| 1139 | alphas = *(((UINT64 *)texture[number].buffer) + to); |
| 1140 | s = (y << 3) + (x << 1); |
| 1141 | sa = ((y << 2) + x) * 3; |
| 1142 | c = (codes >> s) & 3; |
| 1143 | ca = (alphas >> sa) & 7; |
| 1144 | ca = ca + (alpha0 > alpha1 ? 0 : 8); |
| 1145 | switch (ca) { |
| 1146 | case 0: |
| 1147 | ca = alpha0; |
| 1148 | break; |
| 1149 | case 1: |
| 1150 | ca = alpha1; |
| 1151 | break; |
| 1152 | case 2: |
| 1153 | ca = (6 * alpha0 + 1 * alpha1) / 7; |
| 1154 | break; |
| 1155 | case 3: |
| 1156 | ca = (5 * alpha0 + 2 * alpha1) / 7; |
| 1157 | break; |
| 1158 | case 4: |
| 1159 | ca = (4 * alpha0 + 3 * alpha1) / 7; |
| 1160 | break; |
| 1161 | case 5: |
| 1162 | ca = (3 * alpha0 + 4 * alpha1) / 7; |
| 1163 | break; |
| 1164 | case 6: |
| 1165 | ca = (2 * alpha0 + 5 * alpha1) / 7; |
| 1166 | break; |
| 1167 | case 7: |
| 1168 | ca = (1 * alpha0 + 6 * alpha1) / 7; |
| 1169 | break; |
| 1170 | case 8: |
| 1171 | ca = alpha0; |
| 1172 | break; |
| 1173 | case 9: |
| 1174 | ca = alpha1; |
| 1175 | break; |
| 1176 | case 10: |
| 1177 | ca = (4 * alpha0 + 1 * alpha1) / 5; |
| 1178 | break; |
| 1179 | case 11: |
| 1180 | ca = (3 * alpha0 + 2 * alpha1) / 5; |
| 1181 | break; |
| 1182 | case 12: |
| 1183 | ca = (2 * alpha0 + 3 * alpha1) / 5; |
| 1184 | break; |
| 1185 | case 13: |
| 1186 | ca = (1 * alpha0 + 4 * alpha1) / 5; |
| 1187 | break; |
| 1188 | case 14: |
| 1189 | ca = 0; |
| 1190 | break; |
| 1191 | case 15: |
| 1192 | ca = 255; |
| 1193 | break; |
| 1194 | } |
| 1195 | switch (c) { |
| 1196 | case 0: |
| 1197 | return (ca << 24) + convert_r5g6b5_r8g8b8(color0); |
| 1198 | case 1: |
| 1199 | return (ca << 24) + convert_r5g6b5_r8g8b8(color1); |
| 1200 | case 2: |
| 1201 | cb = pal5bit((2 * (color0 & 0x001f) + (color1 & 0x001f)) / 3); |
| 1202 | cg = pal6bit((2 * (color0 & 0x07e0) + (color1 & 0x07e0)) / 3 >> 5); |
| 1203 | cr = pal5bit((2 * (color0 & 0xf800) + (color1 & 0xf800)) / 3 >> 11); |
| 1204 | return (ca << 24) | (cr << 16) | (cg << 8) | (cb); |
| 1205 | default: |
| 1206 | cb = pal5bit(((color0 & 0x001f) + 2 * (color1 & 0x001f)) / 3); |
| 1207 | cg = pal6bit(((color0 & 0x07e0) + 2 * (color1 & 0x07e0)) / 3 >> 5); |
| 1208 | cr = pal5bit(((color0 & 0xf800) + 2 * (color1 & 0xf800)) / 3 >> 11); |
| 1209 | return (ca << 24) | (cr << 16) | (cg << 8) | (cb); |
| 1210 | } |
| 1211 | default: |
| 1212 | return 0xff00ff00; |
| 1213 | } |
| 1214 | } |
| 1215 | |
| 1216 | void nv2a_renderer::write_pixel(int x, int y, UINT32 color) |
| 1217 | { |
| 1218 | void *addr; |
| 1219 | UINT32 fbcolor; |
| 1220 | UINT32 c[4], fb[4], s[4], d[4], cc[4]; |
| 1221 | |
| 1222 | addr = this->fb.raw_pixptr(y, x); |
| 1223 | fbcolor = *((UINT32 *)addr); |
| 1224 | c[3] = color >> 24; |
| 1225 | c[2] = (color >> 16) & 255; |
| 1226 | c[1] = (color >> 8) & 255; |
| 1227 | c[0] = color & 255; |
| 1228 | fb[3] = fbcolor >> 24; |
| 1229 | fb[2] = (fbcolor >> 16) & 255; |
| 1230 | fb[1] = (fbcolor >> 8) & 255; |
| 1231 | fb[0] = fbcolor & 255; |
| 1232 | cc[3] = blend_color >> 24; |
| 1233 | cc[2] = (blend_color >> 16) & 255; |
| 1234 | cc[1] = (blend_color >> 8) & 255; |
| 1235 | cc[0] = blend_color & 255; |
| 1236 | // ownership test and scissor test not done |
| 1237 | // alpha test |
| 1238 | if (alpha_test_enabled) { |
| 1239 | switch (alpha_func) { |
| 1240 | case nv2a_renderer::NEVER: |
| 1241 | return; |
| 1242 | case nv2a_renderer::ALWAYS: |
| 1243 | default: |
| 1244 | break; |
| 1245 | case nv2a_renderer::LESS: |
| 1246 | if (c[3] >= alpha_reference) |
| 1247 | return; |
| 1248 | break; |
| 1249 | case nv2a_renderer::LEQUAL: |
| 1250 | if (c[3] > alpha_reference) |
| 1251 | return; |
| 1252 | break; |
| 1253 | case nv2a_renderer::EQUAL: |
| 1254 | if (c[3] != alpha_reference) |
| 1255 | return; |
| 1256 | break; |
| 1257 | case nv2a_renderer::GEQUAL: |
| 1258 | if (c[3] < alpha_reference) |
| 1259 | return; |
| 1260 | break; |
| 1261 | case nv2a_renderer::GREATER: |
| 1262 | if (c[3] <= alpha_reference) |
| 1263 | return; |
| 1264 | break; |
| 1265 | case nv2a_renderer::NOTEQUAL: |
| 1266 | if (c[3] == alpha_reference) |
| 1267 | return; |
| 1268 | break; |
| 1269 | } |
| 1270 | } |
| 1271 | // stencil test not done |
| 1272 | // depth buffer test not done |
| 1273 | // blending |
| 1274 | if (blending_enabled) { |
| 1275 | switch (blend_function_source) { |
| 1276 | case nv2a_renderer::ZERO: |
| 1277 | s[3] = s[2] = s[1] = s[0] = 0; |
| 1278 | break; |
| 1279 | case nv2a_renderer::ONE: |
| 1280 | default: |
| 1281 | s[3] = s[2] = s[1] = s[0] = 255; |
| 1282 | break; |
| 1283 | case nv2a_renderer::DST_COLOR: |
| 1284 | s[3] = fb[3]; |
| 1285 | s[2] = fb[2]; |
| 1286 | s[1] = fb[1]; |
| 1287 | s[0] = fb[0]; |
| 1288 | break; |
| 1289 | case nv2a_renderer::ONE_MINUS_DST_COLOR: |
| 1290 | s[3] = fb[3] ^ 255; |
| 1291 | s[2] = fb[2] ^ 255; |
| 1292 | s[1] = fb[1] ^ 255; |
| 1293 | s[0] = fb[0] ^ 255; |
| 1294 | break; |
| 1295 | case nv2a_renderer::SRC_ALPHA: |
| 1296 | s[3] = s[2] = s[1] = s[0] = c[3]; |
| 1297 | break; |
| 1298 | case nv2a_renderer::ONE_MINUS_SRC_ALPHA: |
| 1299 | s[3] = s[2] = s[1] = s[0] = c[3] ^ 255; |
| 1300 | break; |
| 1301 | case nv2a_renderer::DST_ALPHA: |
| 1302 | s[3] = s[2] = s[1] = s[0] = fb[3]; |
| 1303 | break; |
| 1304 | case nv2a_renderer::ONE_MINUS_DST_ALPHA: |
| 1305 | s[3] = s[2] = s[1] = s[0] = fb[3] ^ 255; |
| 1306 | break; |
| 1307 | case nv2a_renderer::CONSTANT_COLOR: |
| 1308 | s[3] = cc[3]; |
| 1309 | s[2] = cc[2]; |
| 1310 | s[1] = cc[1]; |
| 1311 | s[0] = cc[0]; |
| 1312 | break; |
| 1313 | case nv2a_renderer::ONE_MINUS_CONSTANT_COLOR: |
| 1314 | s[3] = cc[3] ^ 255; |
| 1315 | s[2] = cc[2] ^ 255; |
| 1316 | s[1] = cc[1] ^ 255; |
| 1317 | s[0] = cc[0] ^ 255; |
| 1318 | break; |
| 1319 | case nv2a_renderer::CONSTANT_ALPHA: |
| 1320 | s[3] = s[2] = s[1] = s[0] = cc[3]; |
| 1321 | break; |
| 1322 | case nv2a_renderer::ONE_MINUS_CONSTANT_ALPHA: |
| 1323 | s[3] = s[2] = s[1] = s[0] = cc[3] ^ 255; |
| 1324 | break; |
| 1325 | case nv2a_renderer::SRC_ALPHA_SATURATE: |
| 1326 | s[3] = 255; |
| 1327 | if (c[3] < (fb[3] ^ 255)) |
| 1328 | s[2] = c[3]; |
| 1329 | else |
| 1330 | s[2] = fb[3]; |
| 1331 | s[1] = s[0] = s[2]; |
| 1332 | break; |
| 1333 | } |
| 1334 | switch (blend_function_destination) { |
| 1335 | case nv2a_renderer::ZERO: |
| 1336 | default: |
| 1337 | d[3] = d[2] = d[1] = d[0] = 0; |
| 1338 | break; |
| 1339 | case nv2a_renderer::ONE: |
| 1340 | d[3] = d[2] = d[1] = d[0] = 255; |
| 1341 | break; |
| 1342 | case nv2a_renderer::SRC_COLOR: |
| 1343 | d[3] = c[3]; |
| 1344 | d[2] = c[2]; |
| 1345 | d[1] = c[1]; |
| 1346 | d[0] = c[0]; |
| 1347 | break; |
| 1348 | case nv2a_renderer::ONE_MINUS_SRC_COLOR: |
| 1349 | d[3] = c[3] ^ 255; |
| 1350 | d[2] = c[2] ^ 255; |
| 1351 | d[1] = c[1] ^ 255; |
| 1352 | d[0] = c[0] ^ 255; |
| 1353 | break; |
| 1354 | case nv2a_renderer::SRC_ALPHA: |
| 1355 | d[3] = d[2] = d[1] = d[0] = c[3]; |
| 1356 | break; |
| 1357 | case nv2a_renderer::ONE_MINUS_SRC_ALPHA: |
| 1358 | d[3] = d[2] = d[1] = d[0] = c[3] ^ 255; |
| 1359 | break; |
| 1360 | case nv2a_renderer::DST_ALPHA: |
| 1361 | d[3] = d[2] = d[1] = d[0] = fb[3]; |
| 1362 | break; |
| 1363 | case nv2a_renderer::ONE_MINUS_DST_ALPHA: |
| 1364 | d[3] = d[2] = d[1] = d[0] = fb[3] ^ 255; |
| 1365 | break; |
| 1366 | case nv2a_renderer::CONSTANT_COLOR: |
| 1367 | d[3] = cc[3]; |
| 1368 | d[2] = cc[2]; |
| 1369 | d[1] = cc[1]; |
| 1370 | d[0] = cc[0]; |
| 1371 | break; |
| 1372 | case nv2a_renderer::ONE_MINUS_CONSTANT_COLOR: |
| 1373 | d[3] = cc[3] ^ 255; |
| 1374 | d[2] = cc[2] ^ 255; |
| 1375 | d[1] = cc[1] ^ 255; |
| 1376 | d[0] = cc[0] ^ 255; |
| 1377 | break; |
| 1378 | case nv2a_renderer::CONSTANT_ALPHA: |
| 1379 | d[3] = d[2] = d[1] = d[0] = cc[3]; |
| 1380 | break; |
| 1381 | case nv2a_renderer::ONE_MINUS_CONSTANT_ALPHA: |
| 1382 | d[3] = d[2] = d[1] = d[0] = cc[3] ^ 255; |
| 1383 | break; |
| 1384 | } |
| 1385 | switch (blend_equation) { |
| 1386 | case nv2a_renderer::FUNC_ADD: |
| 1387 | c[3] = (c[3] * s[3] + fb[3] * d[3]) / 255; |
| 1388 | if (c[3] > 255) |
| 1389 | c[3] = 255; |
| 1390 | c[2] = (c[2] * s[2] + fb[2] * d[2]) / 255; |
| 1391 | if (c[2] > 255) |
| 1392 | c[2] = 255; |
| 1393 | c[1] = (c[1] * s[1] + fb[1] * d[1]) / 255; |
| 1394 | if (c[1] > 255) |
| 1395 | c[1] = 255; |
| 1396 | c[0] = (c[0] * s[0] + fb[0] * d[0]) / 255; |
| 1397 | if (c[0] > 255) |
| 1398 | c[0] = 255; |
| 1399 | break; |
| 1400 | case nv2a_renderer::FUNC_SUBTRACT: |
| 1401 | c[3] = (c[3] * s[3] - fb[3] * d[3]) / 255; |
| 1402 | if (c[3] < 0) |
| 1403 | c[3] = 255; |
| 1404 | c[2] = (c[2] * s[2] - fb[2] * d[2]) / 255; |
| 1405 | if (c[2] < 0) |
| 1406 | c[2] = 255; |
| 1407 | c[1] = (c[1] * s[1] - fb[1] * d[1]) / 255; |
| 1408 | if (c[1] < 0) |
| 1409 | c[1] = 255; |
| 1410 | c[0] = (c[0] * s[0] - fb[0] * d[0]) / 255; |
| 1411 | if (c[0] < 0) |
| 1412 | c[0] = 255; |
| 1413 | break; |
| 1414 | case nv2a_renderer::FUNC_REVERSE_SUBTRACT: |
| 1415 | c[3] = (fb[3] * d[3] - c[3] * s[3]) / 255; |
| 1416 | if (c[3] < 0) |
| 1417 | c[3] = 255; |
| 1418 | c[2] = (fb[2] * d[2] - c[2] * s[2]) / 255; |
| 1419 | if (c[2] < 0) |
| 1420 | c[2] = 255; |
| 1421 | c[1] = (fb[1] * d[1] - c[1] * s[1]) / 255; |
| 1422 | if (c[1] < 0) |
| 1423 | c[1] = 255; |
| 1424 | c[0] = (fb[0] * d[0] - c[0] * s[0]) / 255; |
| 1425 | if (c[0] < 0) |
| 1426 | c[0] = 255; |
| 1427 | break; |
| 1428 | case nv2a_renderer::MIN: |
| 1429 | c[3] = s[3]; |
| 1430 | if (d[3] < c[3]) |
| 1431 | c[3] = d[3]; |
| 1432 | c[2] = s[2]; |
| 1433 | if (d[2] < c[2]) |
| 1434 | c[2] = d[2]; |
| 1435 | c[1] = s[1]; |
| 1436 | if (d[1] < c[1]) |
| 1437 | c[1] = d[1]; |
| 1438 | c[0] = s[0]; |
| 1439 | if (d[0] < c[0]) |
| 1440 | c[0] = d[0]; |
| 1441 | break; |
| 1442 | case nv2a_renderer::MAX: |
| 1443 | c[3] = s[3]; |
| 1444 | if (d[3] > c[3]) |
| 1445 | c[3] = d[3]; |
| 1446 | c[2] = s[2]; |
| 1447 | if (d[2] > c[2]) |
| 1448 | c[2] = d[2]; |
| 1449 | c[1] = s[1]; |
| 1450 | if (d[1] > c[1]) |
| 1451 | c[1] = d[1]; |
| 1452 | c[0] = s[0]; |
| 1453 | if (d[0] > c[0]) |
| 1454 | c[0] = d[0]; |
| 1455 | break; |
| 1456 | } |
| 1457 | } |
| 1458 | // dithering not done |
| 1459 | // logical operation |
| 1460 | if (logical_operation_enabled) { |
| 1461 | switch (logical_operation) { |
| 1462 | case nv2a_renderer::CLEAR: |
| 1463 | c[3] = 0; |
| 1464 | c[2] = 0; |
| 1465 | c[1] = 0; |
| 1466 | c[0] = 0; |
| 1467 | break; |
| 1468 | case nv2a_renderer::AND: |
| 1469 | c[3] = c[3] & fb[3]; |
| 1470 | c[2] = c[2] & fb[2]; |
| 1471 | c[1] = c[1] & fb[1]; |
| 1472 | c[0] = c[0] & fb[0]; |
| 1473 | break; |
| 1474 | case nv2a_renderer::AND_REVERSE: |
| 1475 | c[3] = c[3] & (fb[3] ^ 255); |
| 1476 | c[2] = c[2] & (fb[2] ^ 255); |
| 1477 | c[1] = c[1] & (fb[1] ^ 255); |
| 1478 | c[0] = c[0] & (fb[0] ^ 255); |
| 1479 | break; |
| 1480 | case nv2a_renderer::COPY: |
| 1481 | default: |
| 1482 | break; |
| 1483 | case nv2a_renderer::AND_INVERTED: |
| 1484 | c[3] = (c[3] ^ 255) & fb[3]; |
| 1485 | c[2] = (c[2] ^ 255) & fb[2]; |
| 1486 | c[1] = (c[1] ^ 255) & fb[1]; |
| 1487 | c[0] = (c[0] ^ 255) & fb[0]; |
| 1488 | break; |
| 1489 | case nv2a_renderer::NOOP: |
| 1490 | c[3] = fb[3]; |
| 1491 | c[2] = fb[2]; |
| 1492 | c[1] = fb[1]; |
| 1493 | c[0] = fb[0]; |
| 1494 | break; |
| 1495 | case nv2a_renderer::XOR: |
| 1496 | c[3] = c[3] ^ fb[3]; |
| 1497 | c[2] = c[2] ^ fb[2]; |
| 1498 | c[1] = c[1] ^ fb[1]; |
| 1499 | c[0] = c[0] ^ fb[0]; |
| 1500 | break; |
| 1501 | case nv2a_renderer::OR: |
| 1502 | c[3] = c[3] | fb[3]; |
| 1503 | c[2] = c[2] | fb[2]; |
| 1504 | c[1] = c[1] | fb[1]; |
| 1505 | c[0] = c[0] | fb[0]; |
| 1506 | break; |
| 1507 | case nv2a_renderer::NOR: |
| 1508 | c[3] = (c[3] | fb[3]) ^ 255; |
| 1509 | c[2] = (c[2] | fb[2]) ^ 255; |
| 1510 | c[1] = (c[1] | fb[1]) ^ 255; |
| 1511 | c[0] = (c[0] | fb[0]) ^ 255; |
| 1512 | break; |
| 1513 | case nv2a_renderer::EQUIV: |
| 1514 | c[3] = (c[3] ^ fb[3]) ^ 255; |
| 1515 | c[2] = (c[2] ^ fb[2]) ^ 255; |
| 1516 | c[1] = (c[1] ^ fb[1]) ^ 255; |
| 1517 | c[0] = (c[0] ^ fb[0]) ^ 255; |
| 1518 | break; |
| 1519 | case nv2a_renderer::INVERT: |
| 1520 | c[3] = fb[3] ^ 255; |
| 1521 | c[2] = fb[2] ^ 255; |
| 1522 | c[1] = fb[1] ^ 255; |
| 1523 | c[0] = fb[0] ^ 255; |
| 1524 | break; |
| 1525 | case nv2a_renderer::OR_REVERSE: |
| 1526 | c[3] = c[3] | (fb[3] ^ 255); |
| 1527 | c[2] = c[2] | (fb[2] ^ 255); |
| 1528 | c[1] = c[1] | (fb[1] ^ 255); |
| 1529 | c[0] = c[0] | (fb[0] ^ 255); |
| 1530 | break; |
| 1531 | case nv2a_renderer::COPY_INVERTED: |
| 1532 | c[3] = c[3] ^ 255; |
| 1533 | c[2] = c[2] ^ 255; |
| 1534 | c[1] = c[1] ^ 255; |
| 1535 | c[0] = c[0] ^ 255; |
| 1536 | break; |
| 1537 | case nv2a_renderer::OR_INVERTED: |
| 1538 | c[3] = (c[3] ^ 255) | fb[3]; |
| 1539 | c[2] = (c[2] ^ 255) | fb[2]; |
| 1540 | c[1] = (c[1] ^ 255) | fb[1]; |
| 1541 | c[0] = (c[0] ^ 255) | fb[0]; |
| 1542 | break; |
| 1543 | case nv2a_renderer::NAND: |
| 1544 | c[3] = (c[3] & fb[3]) ^ 255; |
| 1545 | c[2] = (c[2] & fb[2]) ^ 255; |
| 1546 | c[1] = (c[1] & fb[1]) ^ 255; |
| 1547 | c[0] = (c[0] & fb[0]) ^ 255; |
| 1548 | break; |
| 1549 | case nv2a_renderer::SET: |
| 1550 | c[3] = 255; |
| 1551 | c[2] = 255; |
| 1552 | c[1] = 255; |
| 1553 | c[0] = 255; |
| 1554 | break; |
| 1555 | } |
| 1556 | } |
| 1557 | fbcolor = (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0]; |
| 1558 | *((UINT32 *)addr) = fbcolor; |
| 1559 | } |
| 1560 | |
| 1561 | void nv2a_renderer::render_color(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid) |
| 1562 | { |
| 1563 | int x; |
| 1564 | |
| 1565 | if ((extent.startx < 0) || (extent.stopx > 640)) |
| 1566 | return; |
| 1567 | x = extent.stopx - extent.startx - 1; // number of pixels to draw |
| 1568 | while (x >= 0) { |
| 1569 | UINT32 a8r8g8b8; |
| 1570 | int ca, cr, cg, cb; |
| 1571 | int xp = extent.startx + x; // x coordinate of current pixel |
| 1572 | |
| 1573 | cb = ((extent.param[0].start + (float)x*extent.param[0].dpdx))*255.0; |
| 1574 | cg = ((extent.param[1].start + (float)x*extent.param[1].dpdx))*255.0; |
| 1575 | cr = ((extent.param[2].start + (float)x*extent.param[2].dpdx))*255.0; |
| 1576 | ca = ((extent.param[3].start + (float)x*extent.param[3].dpdx))*255.0; |
| 1577 | a8r8g8b8 = (ca << 24) + (cr << 16) + (cg << 8) + cb; // pixel color obtained by interpolating the colors of the vertices |
| 1578 | write_pixel(xp, scanline, a8r8g8b8); |
| 1579 | x--; |
| 1580 | } |
| 1581 | } |
| 1582 | |
| 1583 | void nv2a_renderer::render_texture_simple(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid) |
| 1584 | { |
| 1585 | int x; |
| 1586 | UINT32 a8r8g8b8; |
| 1587 | |
| 1588 | if (!objectdata.data->texture[0].enabled) { |
| 1589 | return; |
| 1590 | } |
| 1591 | if ((extent.startx < 0) || (extent.stopx > 640)) |
| 1592 | return; |
| 1593 | x = extent.stopx - extent.startx - 1; |
| 1594 | while (x >= 0) { |
| 1595 | int up, vp; |
| 1596 | int xp = extent.startx + x; // x coordinate of current pixel |
| 1597 | |
| 1598 | up = (extent.param[4].start + (float)x*extent.param[4].dpdx)*(float)(objectdata.data->texture[0].sizeu - 1); // x coordinate of texel in texture |
| 1599 | vp = extent.param[5].start*(float)(objectdata.data->texture[0].sizev - 1); // y coordinate of texel in texture |
| 1600 | a8r8g8b8 = texture_get_texel(0, up, vp); |
| 1601 | write_pixel(xp, scanline, a8r8g8b8); |
| 1602 | x--; |
| 1603 | } |
| 1604 | } |
| 1605 | |
| 1606 | void nv2a_renderer::render_register_combiners(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid) |
| 1607 | { |
| 1608 | int x, xp; |
| 1609 | int up, vp; |
| 1610 | int ca, cr, cg, cb; |
| 1611 | UINT32 color[6]; |
| 1612 | UINT32 a8r8g8b8; |
| 1613 | int n;//,m,i,j,k; |
| 1614 | |
| 1615 | color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0; |
| 1616 | |
| 1617 | if ((extent.startx < 0) || (extent.stopx > 640)) |
| 1618 | return; |
| 1619 | osd_lock_acquire(combiner.lock); // needed since multithreading is not supported yet |
| 1620 | x = extent.stopx - extent.startx - 1; // number of pixels to draw |
| 1621 | while (x >= 0) { |
| 1622 | xp = extent.startx + x; |
| 1623 | // 1: fetch data |
| 1624 | // 1.1: interpolated color from vertices |
| 1625 | cb = ((extent.param[0].start + (float)x*extent.param[0].dpdx))*255.0; |
| 1626 | cg = ((extent.param[1].start + (float)x*extent.param[1].dpdx))*255.0; |
| 1627 | cr = ((extent.param[2].start + (float)x*extent.param[2].dpdx))*255.0; |
| 1628 | ca = ((extent.param[3].start + (float)x*extent.param[3].dpdx))*255.0; |
| 1629 | color[0] = (ca << 24) + (cr << 16) + (cg << 8) + cb; // pixel color obtained by interpolating the colors of the vertices |
| 1630 | color[1] = 0; // lighting not yet |
| 1631 | // 1.2: color for each of the 4 possible textures |
| 1632 | for (n = 0; n < 4; n++) { |
| 1633 | if (texture[n].enabled) { |
| 1634 | up = (extent.param[4 + n * 2].start + (float)x*extent.param[4 + n * 2].dpdx)*(float)(objectdata.data->texture[n].sizeu - 1); |
| 1635 | vp = extent.param[5 + n * 2].start*(float)(objectdata.data->texture[n].sizev - 1); |
| 1636 | color[n + 2] = texture_get_texel(n, up, vp); |
| 1637 | } |
| 1638 | } |
| 1639 | // 2: compute |
| 1640 | // 2.1: initialize |
| 1641 | combiner_initialize_registers(color); |
| 1642 | // 2.2: general cmbiner stages |
| 1643 | for (n = 0; n < combiner.stages; n++) { |
| 1644 | // 2.2.1 initialize |
| 1645 | combiner_initialize_stage(n); |
| 1646 | // 2.2.2 map inputs |
| 1647 | combiner_map_input(n); |
| 1648 | // 2.2.3 compute possible outputs |
| 1649 | combiner_compute_rgb_outputs(n); |
| 1650 | combiner_compute_a_outputs(n); |
| 1651 | // 2.2.4 map outputs to registers |
| 1652 | combiner_map_output(n); |
| 1653 | } |
| 1654 | // 2.3: final cmbiner stage |
| 1655 | combiner_initialize_final(); |
| 1656 | combiner_map_final_input(); |
| 1657 | combiner_final_output(); |
| 1658 | a8r8g8b8 = combiner_float_argb8(combiner.output); |
| 1659 | // 3: write pixel |
| 1660 | write_pixel(xp, scanline, a8r8g8b8); |
| 1661 | x--; |
| 1662 | } |
| 1663 | osd_lock_release(combiner.lock); |
| 1664 | } |
| 1665 | |
| 1666 | #if 0 |
| 1667 | const char *rc_mapping_str[] = { |
| 1668 | "UNSIGNED_IDENTITY", |
| 1669 | "UNSIGNED_INVERT", |
| 1670 | "EXPAND_NORMAL", |
| 1671 | "EXPAND_NEGATE", |
| 1672 | "HALF_BIAS_NORMAL", |
| 1673 | "HALF_BIAS_NEGATE", |
| 1674 | "SIGNED_IDENTITY", |
| 1675 | "SIGNED_NEGATE" |
| 1676 | }; |
| 1677 | |
| 1678 | const char *rc_usage_rgb_str[] = { |
| 1679 | "RGB", |
| 1680 | "ALPHA" |
| 1681 | }; |
| 1682 | |
| 1683 | const char *rc_usage_alpha_str[] = { |
| 1684 | "BLUE", |
| 1685 | "ALPHA" |
| 1686 | }; |
| 1687 | |
| 1688 | const char *rc_variable_str[] = { |
| 1689 | "ZERO", |
| 1690 | "CONSTANT_COLOR0", |
| 1691 | "CONSTANT_COLOR1", |
| 1692 | "FOG", |
| 1693 | "PRIMARY_COLOR", |
| 1694 | "SECONDARY_COLOR", |
| 1695 | "???", |
| 1696 | "???", |
| 1697 | "TEXTURE0", |
| 1698 | "TEXTURE1", |
| 1699 | "TEXTURE2", |
| 1700 | "TEXTURE3", |
| 1701 | "SPARE0", |
| 1702 | "SPARE1", |
| 1703 | "SPARE0_PLUS_SECONDARY_COLOR", |
| 1704 | "E_TIMES_F" |
| 1705 | }; |
| 1706 | |
| 1707 | const char *rc_bias_str[] = { |
| 1708 | "NONE", |
| 1709 | "BIAS_BY_NEGATIVE_ONE_HALF" |
| 1710 | }; |
| 1711 | |
| 1712 | const char *rc_scale_str[] = { |
| 1713 | "NONE", |
| 1714 | "SCALE_BY_TWO", |
| 1715 | "SCALE_BY_FOUR", |
| 1716 | "SCALE_BY_ONE_HALF" |
| 1717 | }; |
| 1718 | |
| 1719 | /* Dump the current setup of the register combiners */ |
| 1720 | void dumpcombiners(UINT32 *m) |
| 1721 | { |
| 1722 | int a, b, n, v; |
| 1723 | |
| 1724 | n = m[0x1e60 / 4] & 0xf; |
| 1725 | printf("Combiners active: %d\n\r", n); |
| 1726 | for (a = 0; a < n; a++) { |
| 1727 | printf("Combiner %d\n\r", a + 1); |
| 1728 | printf(" RC_IN_ALPHA %08X\n\r", m[0x0260 / 4 + a]); |
| 1729 | for (b = 24; b >= 0; b = b - 8) { |
| 1730 | v = (m[0x0260 / 4 + a] >> b) & 0xf; |
| 1731 | printf(" %c_INPUT %s\n\r", 'A' + 3 - b / 8, rc_variable_str[v]); |
| 1732 | v = (m[0x0260 / 4 + a] >> (b + 4)) & 1; |
| 1733 | printf(" %c_COMPONENT_USAGE %s\n\r", 'A' + 3 - b / 8, rc_usage_alpha_str[v]); |
| 1734 | v = (m[0x0260 / 4 + a] >> (b + 5)) & 7; |
| 1735 | printf(" %c_MAPPING %s\n\r", 'A' + 3 - b / 8, rc_mapping_str[v]); |
| 1736 | } |
| 1737 | printf(" RC_IN_RGB %08X\n\r", m[0x0ac0 / 4 + a]); |
| 1738 | for (b = 24; b >= 0; b = b - 8) { |
| 1739 | v = (m[0x0ac0 / 4 + a] >> b) & 0xf; |
| 1740 | printf(" %c_INPUT %s\n\r", 'A' + 3 - b / 8, rc_variable_str[v]); |
| 1741 | v = (m[0x0ac0 / 4 + a] >> (b + 4)) & 1; |
| 1742 | printf(" %c_COMPONENT_USAGE %s\n\r", 'A' + 3 - b / 8, rc_usage_rgb_str[v]); |
| 1743 | v = (m[0x0ac0 / 4 + a] >> (b + 5)) & 7; |
| 1744 | printf(" %c_MAPPING %s\n\r", 'A' + 3 - b / 8, rc_mapping_str[v]); |
| 1745 | } |
| 1746 | printf(" RC_OUT_ALPHA %08X\n\r", m[0x0aa0 / 4 + a]); |
| 1747 | v = m[0x0aa0 / 4 + a] & 0xf; |
| 1748 | printf(" CD_OUTPUT %s\n\r", rc_variable_str[v]); |
| 1749 | v = (m[0x0aa0 / 4 + a] >> 4) & 0xf; |
| 1750 | printf(" AB_OUTPUT %s\n\r", rc_variable_str[v]); |
| 1751 | v = (m[0x0aa0 / 4 + a] >> 8) & 0xf; |
| 1752 | printf(" SUM_OUTPUT %s\n\r", rc_variable_str[v]); |
| 1753 | v = (m[0x0aa0 / 4 + a] >> 12) & 1; |
| 1754 | printf(" CD_DOT_PRODUCT %d\n\r", v); |
| 1755 | v = (m[0x0aa0 / 4 + a] >> 13) & 1; |
| 1756 | printf(" AB_DOT_PRODUCT %d\n\r", v); |
| 1757 | v = (m[0x0aa0 / 4 + a] >> 14) & 1; |
| 1758 | printf(" MUX_SUM %d\n\r", v); |
| 1759 | v = (m[0x0aa0 / 4 + a] >> 15) & 1; |
| 1760 | printf(" BIAS %s\n\r", rc_bias_str[v]); |
| 1761 | v = (m[0x0aa0 / 4 + a] >> 16) & 3; |
| 1762 | printf(" SCALE %s\n\r", rc_scale_str[v]); |
| 1763 | //v=(m[0x0aa0/4+a] >> 27) & 7; |
| 1764 | printf(" RC_OUT_RGB %08X\n\r", m[0x1e40 / 4 + a]); |
| 1765 | v = m[0x1e40 / 4 + a] & 0xf; |
| 1766 | printf(" CD_OUTPUT %s\n\r", rc_variable_str[v]); |
| 1767 | v = (m[0x1e40 / 4 + a] >> 4) & 0xf; |
| 1768 | printf(" AB_OUTPUT %s\n\r", rc_variable_str[v]); |
| 1769 | v = (m[0x1e40 / 4 + a] >> 8) & 0xf; |
| 1770 | printf(" SUM_OUTPUT %s\n\r", rc_variable_str[v]); |
| 1771 | v = (m[0x1e40 / 4 + a] >> 12) & 1; |
| 1772 | printf(" CD_DOT_PRODUCT %d\n\r", v); |
| 1773 | v = (m[0x1e40 / 4 + a] >> 13) & 1; |
| 1774 | printf(" AB_DOT_PRODUCT %d\n\r", v); |
| 1775 | v = (m[0x1e40 / 4 + a] >> 14) & 1; |
| 1776 | printf(" MUX_SUM %d\n\r", v); |
| 1777 | v = (m[0x1e40 / 4 + a] >> 15) & 1; |
| 1778 | printf(" BIAS %s\n\r", rc_bias_str[v]); |
| 1779 | v = (m[0x1e40 / 4 + a] >> 16) & 3; |
| 1780 | printf(" SCALE %s\n\r", rc_scale_str[v]); |
| 1781 | //v=(m[0x1e40/4+a] >> 27) & 7; |
| 1782 | printf("\n\r"); |
| 1783 | } |
| 1784 | printf("Combiner final %08X %08X\n\r", m[0x0288 / 4], m[0x028c / 4]); |
| 1785 | for (a = 24; a >= 0; a = a - 8) { |
| 1786 | n = (m[0x0288 / 4] >> a) & 0xf; |
| 1787 | printf(" %c_INPUT %s\n\r", 'A' + 3 - a / 8, rc_variable_str[n]); |
| 1788 | n = (m[0x0288 / 4] >> (a + 4)) & 1; |
| 1789 | printf(" %c_COMPONENT_USAGE %s\n\r", 'A' + 3 - a / 8, rc_usage_rgb_str[n]); |
| 1790 | n = (m[0x0288 / 4] >> (a + 5)) & 7; |
| 1791 | printf(" %c_MAPPING %s\n\r", 'A' + 3 - a / 8, rc_mapping_str[n]); |
| 1792 | } |
| 1793 | for (a = 24; a >= 8; a = a - 8) { |
| 1794 | n = (m[0x028c / 4] >> a) & 0xf; |
| 1795 | printf(" %c_INPUT %s\n\r", 'E' + 3 - a / 8, rc_variable_str[n]); |
| 1796 | n = (m[0x028c / 4] >> (a + 4)) & 1; |
| 1797 | printf(" %c_COMPONENT_USAGE %s\n\r", 'E' + 3 - a / 8, rc_usage_rgb_str[n]); |
| 1798 | n = (m[0x028c / 4] >> (a + 5)) & 7; |
| 1799 | printf(" %c_MAPPING %s\n\r", 'E' + 3 - a / 8, rc_mapping_str[n]); |
| 1800 | } |
| 1801 | n = (m[0x028c / 4] >> 7) & 1; |
| 1802 | printf(" color sum clamp: %d\n\r", n); |
| 1803 | } |
| 1804 | #endif |
| 1805 | |
| 1806 | void nv2a_renderer::read_vertex(address_space & space, offs_t address, vertex_nv &vertex, int attrib) |
| 1807 | { |
| 1808 | UINT32 u; |
| 1809 | int c, d, l; |
| 1810 | |
| 1811 | l = vertexbuffer_size[attrib]; |
| 1812 | switch (vertexbuffer_kind[attrib]) { |
| 1813 | case NV2A_VTXBUF_TYPE_FLOAT: |
| 1814 | default: |
| 1815 | vertex.attribute[attrib].fv[0] = 0; |
| 1816 | vertex.attribute[attrib].fv[1] = 0; |
| 1817 | vertex.attribute[attrib].fv[2] = 0; |
| 1818 | vertex.attribute[attrib].fv[3] = 1.0; |
| 1819 | for (c = d = 0; c < l; c++) { |
| 1820 | vertex.attribute[attrib].iv[c] = space.read_dword(address + d); |
| 1821 | d = d + 4; |
| 1822 | } |
| 1823 | break; |
| 1824 | case NV2A_VTXBUF_TYPE_UBYTE: |
| 1825 | break; |
| 1826 | case NV2A_VTXBUF_TYPE_UNKNOWN_0: |
| 1827 | u = space.read_dword(address + 0); |
| 1828 | for (c = 0; c < l; c++) { |
| 1829 | vertex.attribute[attrib].fv[c] = (u & 0xff) / 255.0; |
| 1830 | u = u >> 8; |
| 1831 | } |
| 1832 | break; |
| 1833 | case NV2A_VTXBUF_TYPE_UNKNOWN_6: // ??? |
| 1834 | u = space.read_dword(address + 0); |
| 1835 | vertex.attribute[attrib].fv[0] = (u & 0xff) / 255.0; // b |
| 1836 | vertex.attribute[attrib].fv[1] = ((u & 0xff00) >> 8) / 255.0; // g |
| 1837 | vertex.attribute[attrib].fv[2] = ((u & 0xff0000) >> 16) / 255.0; // r |
| 1838 | vertex.attribute[attrib].fv[3] = ((u & 0xff000000) >> 24) / 255.0; // a |
| 1839 | break; |
| 1840 | } |
| 1841 | } |
| 1842 | |
| 1843 | /* Read vertices data from system memory. Method 0x1810 */ |
| 1844 | int nv2a_renderer::read_vertices_0x1810(address_space & space, vertex_nv *destination, int offset, int limit) |
| 1845 | { |
| 1846 | UINT32 m; |
| 1847 | int a, b; |
| 1848 | |
| 1849 | #ifdef MAME_DEBUG |
| 1850 | memset(destination, 0, sizeof(vertex_nv)*limit); |
| 1851 | #endif |
| 1852 | for (m = 0; m < limit; m++) { |
| 1853 | b = enabled_vertex_attributes; |
| 1854 | for (a = 0; a < 16; a++) { |
| 1855 | if (b & 1) { |
| 1856 | read_vertex(space, vertexbuffer_address[a] + (m + offset)*vertexbuffer_stride[a], destination[m], a); |
| 1857 | } |
| 1858 | b = b >> 1; |
| 1859 | } |
| 1860 | } |
| 1861 | return m; |
| 1862 | } |
| 1863 | |
| 1864 | /* Read vertices data from system memory. Method 0x1800 */ |
| 1865 | int nv2a_renderer::read_vertices_0x1800(address_space & space, vertex_nv *destination, UINT32 address, int limit) |
| 1866 | { |
| 1867 | UINT32 data; |
| 1868 | UINT32 m, i, c; |
| 1869 | int a, b; |
| 1870 | |
| 1871 | #ifdef MAME_DEBUG |
| 1872 | memset(destination, 0, sizeof(vertex_nv)*limit); |
| 1873 | #endif |
| 1874 | c = 0; |
| 1875 | for (m = 0; m < limit; m++) { |
| 1876 | if (indexesleft_count == 0) { |
| 1877 | data = space.read_dword(address); |
| 1878 | i = (indexesleft_first + indexesleft_count) & 7; |
| 1879 | indexesleft[i] = data & 0xffff; |
| 1880 | indexesleft[(i + 1) & 7] = (data >> 16) & 0xffff; |
| 1881 | indexesleft_count = indexesleft_count + 2; |
| 1882 | address += 4; |
| 1883 | c++; |
| 1884 | } |
| 1885 | b = enabled_vertex_attributes; |
| 1886 | for (a = 0; a < 16; a++) { |
| 1887 | if (b & 1) { |
| 1888 | read_vertex(space, vertexbuffer_address[a] + indexesleft[indexesleft_first] * vertexbuffer_stride[a], destination[m], a); |
| 1889 | } |
| 1890 | b = b >> 1; |
| 1891 | } |
| 1892 | indexesleft_first = (indexesleft_first + 1) & 7; |
| 1893 | indexesleft_count--; |
| 1894 | } |
| 1895 | return (int)c; |
| 1896 | } |
| 1897 | |
| 1898 | /* Read vertices data from system memory. Method 0x1818 */ |
| 1899 | int nv2a_renderer::read_vertices_0x1818(address_space & space, vertex_nv *destination, UINT32 address, int limit) |
| 1900 | { |
| 1901 | UINT32 m, vwords; |
| 1902 | int a, b; |
| 1903 | |
| 1904 | #ifdef MAME_DEBUG |
| 1905 | memset(destination, 0, sizeof(vertex_nv)*limit); |
| 1906 | #endif |
| 1907 | vwords = vertex_attribute_words[15] + vertex_attribute_offset[15]; |
| 1908 | for (m = 0; m < limit; m++) { |
| 1909 | b = enabled_vertex_attributes; |
| 1910 | for (a = 0; a < 16; a++) { |
| 1911 | if (b & 1) { |
| 1912 | read_vertex(space, address + vertex_attribute_offset[a] * 4, destination[m], a); |
| 1913 | } |
| 1914 | b = b >> 1; |
| 1915 | } |
| 1916 | address = address + vwords * 4; |
| 1917 | } |
| 1918 | return (int)(m*vwords); |
| 1919 | } |
| 1920 | |
| 1921 | void nv2a_renderer::convert_vertices_poly(vertex_nv *source, vertex_t *destination, int count) |
| 1922 | { |
| 1923 | int m, u; |
| 1924 | |
| 1925 | // take each vertex with its attributes and obtain data for drawing |
| 1926 | // should use either the vertex program or transformation matrices |
| 1927 | if (vertex_pipeline == 4) { |
| 1928 | // transformation matrices |
| 1929 | // it is not implemented, so we pretend its always using screen coordinates |
| 1930 | for (m = 0; m < count; m++) { |
| 1931 | destination[m].x = source[m].attribute[0].fv[0]; |
| 1932 | destination[m].y = source[m].attribute[0].fv[1]; |
| 1933 | for (u = 0; u < 4; u++) // 0=b 1=g 2=r 3=a |
| 1934 | destination[m].p[u] = source[m].attribute[3].fv[u]; |
| 1935 | for (u = 0; u < 4; u++) { |
| 1936 | destination[m].p[4 + u * 2] = source[m].attribute[9 + u].fv[0]; |
| 1937 | destination[m].p[5 + u * 2] = source[m].attribute[9 + u].fv[1]; |
| 1938 | } |
| 1939 | } |
| 1940 | } |
| 1941 | else { |
| 1942 | // vertex program |
| 1943 | vertex_nv vert[4]; |
| 1944 | // run vertex program |
| 1945 | vertexprogram.exec.process(vertexprogram.start_instruction, source, vert, count); |
| 1946 | // copy data for poly.c |
| 1947 | for (m = 0; m < count; m++) { |
| 1948 | destination[m].x = vert[m].attribute[0].fv[0]; |
| 1949 | destination[m].y = vert[m].attribute[0].fv[1]; |
| 1950 | for (u = 0; u < 4; u++) // 0=b 1=g 2=r 3=a |
| 1951 | destination[m].p[u] = vert[m].attribute[3].fv[u]; |
| 1952 | for (u = 0; u < 4; u++) { |
| 1953 | destination[m].p[4 + u * 2] = vert[m].attribute[9 + u].fv[0]; |
| 1954 | destination[m].p[5 + u * 2] = vert[m].attribute[9 + u].fv[1]; |
| 1955 | } |
| 1956 | } |
| 1957 | } |
| 1958 | } |
| 1959 | |
| 1960 | void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UINT32 subchannel, UINT32 method, UINT32 address, int &countlen) |
| 1961 | { |
| 1962 | UINT32 maddress; |
| 1963 | UINT32 data; |
| 1964 | |
| 1965 | maddress = method * 4; |
| 1966 | data = space.read_dword(address); |
| 1967 | channel[chanel][subchannel].object.method[method] = data; |
| 1968 | if (maddress == 0x17fc) { |
| 1969 | indexesleft_count = 0; |
| 1970 | indexesleft_first = 0; |
| 1971 | primitives_count = 0; |
| 1972 | countlen--; |
| 1973 | } |
| 1974 | if (maddress == 0x1810) { |
| 1975 | // draw vertices |
| 1976 | int offset, count, type; |
| 1977 | UINT32 n; |
| 1978 | render_delegate renderspans; |
| 1979 | |
| 1980 | offset = data & 0xffffff; |
| 1981 | count = (data >> 24) & 0xff; |
| 1982 | type = channel[chanel][subchannel].object.method[0x17fc / 4]; |
| 1983 | if (((channel[chanel][subchannel].object.method[0x1e60 / 4] & 7) > 0) && (combiner.used != 0)) { |
| 1984 | renderspans = render_delegate(FUNC(nv2a_renderer::render_register_combiners), this); |
| 1985 | } |
| 1986 | else if (texture[0].enabled) { |
| 1987 | renderspans = render_delegate(FUNC(nv2a_renderer::render_texture_simple), this); |
| 1988 | } |
| 1989 | else |
| 1990 | renderspans = render_delegate(FUNC(nv2a_renderer::render_color), this); |
| 1991 | #ifdef LOG_NV2A |
| 1992 | printf("vertex %d %d %d\n\r", type, offset, count); |
| 1993 | #endif |
| 1994 | if (type == nv2a_renderer::QUADS) { |
| 1995 | for (n = 0; n <= count; n += 4) { |
| 1996 | vertex_nv vert[4]; |
| 1997 | vertex_t xy[4]; |
| 1998 | |
| 1999 | read_vertices_0x1810(space, vert, n + offset, 4); |
| 2000 | convert_vertices_poly(vert, xy, 4); |
| 2001 | render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv |
| 2002 | } |
| 2003 | wait(); |
| 2004 | } |
| 2005 | else if (type == nv2a_renderer::TRIANGLE_STRIP) { |
| 2006 | vertex_nv vert[4]; |
| 2007 | vertex_t xy[4]; |
| 2008 | |
| 2009 | read_vertices_0x1810(space, vert, offset, 2); |
| 2010 | convert_vertices_poly(vert, xy, 2); |
| 2011 | count = count - 2; |
| 2012 | offset = offset + 2; |
| 2013 | for (n = 0; n <= count; n++) { |
| 2014 | read_vertices_0x1810(space, vert + ((n + 2) & 3), offset + n, 1); |
| 2015 | convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1); |
| 2016 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]); |
| 2017 | } |
| 2018 | wait(); |
| 2019 | } |
| 2020 | else { |
| 2021 | logerror("Unsupported primitive %d for method 0x1810\n", type); |
| 2022 | } |
| 2023 | countlen--; |
| 2024 | } |
| 2025 | if (maddress == 0x1800) { |
| 2026 | UINT32 type, n; |
| 2027 | render_delegate renderspans; |
| 2028 | |
| 2029 | if (((channel[chanel][subchannel].object.method[0x1e60 / 4] & 7) > 0) && (combiner.used != 0)) { |
| 2030 | renderspans = render_delegate(FUNC(nv2a_renderer::render_register_combiners), this); |
| 2031 | } |
| 2032 | else if (texture[0].enabled) { |
| 2033 | renderspans = render_delegate(FUNC(nv2a_renderer::render_texture_simple), this); |
| 2034 | } |
| 2035 | else |
| 2036 | renderspans = render_delegate(FUNC(nv2a_renderer::render_color), this); |
| 2037 | // vertices are selected from the vertex buffer using an array of indexes |
| 2038 | // each dword after 1800 contains two 16 bit index values to select the vartices |
| 2039 | type = channel[chanel][subchannel].object.method[0x17fc / 4]; |
| 2040 | #ifdef LOG_NV2A |
| 2041 | printf("vertex %d %d %d\n\r", type, offset, count); |
| 2042 | #endif |
| 2043 | if (type == nv2a_renderer::QUADS) { |
| 2044 | while (1) { |
| 2045 | vertex_nv vert[4]; |
| 2046 | vertex_t xy[4]; |
| 2047 | int c; |
| 2048 | |
| 2049 | if ((countlen * 2 + indexesleft_count) < 4) |
| 2050 | break; |
| 2051 | c = read_vertices_0x1800(space, vert, address, 4); |
| 2052 | address = address + c * 4; |
| 2053 | countlen = countlen - c; |
| 2054 | convert_vertices_poly(vert, xy, 4); |
| 2055 | render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv |
| 2056 | } |
| 2057 | while (countlen > 0) { |
| 2058 | data = space.read_dword(address); |
| 2059 | n = (indexesleft_first + indexesleft_count) & 7; |
| 2060 | indexesleft[n] = data & 0xffff; |
| 2061 | indexesleft[(n + 1) & 7] = (data >> 16) & 0xffff; |
| 2062 | indexesleft_count = indexesleft_count + 2; |
| 2063 | address += 4; |
| 2064 | countlen--; |
| 2065 | } |
| 2066 | wait(); |
| 2067 | } |
| 2068 | else if (type == nv2a_renderer::TRIANGLES) { |
| 2069 | while (1) { |
| 2070 | vertex_nv vert[3]; |
| 2071 | vertex_t xy[3]; |
| 2072 | int c; |
| 2073 | |
| 2074 | if ((countlen * 2 + indexesleft_count) < 3) |
| 2075 | break; |
| 2076 | c = read_vertices_0x1800(space, vert, address, 3); |
| 2077 | address = address + c * 4; |
| 2078 | countlen = countlen - c; |
| 2079 | convert_vertices_poly(vert, xy, 3); |
| 2080 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[0], xy[1], xy[2]); // 4 rgba, 4 texture units 2 uv |
| 2081 | } |
| 2082 | while (countlen > 0) { |
| 2083 | data = space.read_dword(address); |
| 2084 | n = (indexesleft_first + indexesleft_count) & 7; |
| 2085 | indexesleft[n] = data & 0xffff; |
| 2086 | indexesleft[(n + 1) & 7] = (data >> 16) & 0xffff; |
| 2087 | indexesleft_count = indexesleft_count + 2; |
| 2088 | address += 4; |
| 2089 | countlen--; |
| 2090 | } |
| 2091 | wait(); |
| 2092 | } |
| 2093 | else if (type == nv2a_renderer::TRIANGLE_STRIP) { |
| 2094 | if ((countlen * 2 + indexesleft_count) >= 3) { |
| 2095 | vertex_nv vert[4]; |
| 2096 | vertex_t xy[4]; |
| 2097 | int c, count; |
| 2098 | |
| 2099 | c = read_vertices_0x1800(space, vert, address, 2); |
| 2100 | convert_vertices_poly(vert, xy, 2); |
| 2101 | address = address + c * 4; |
| 2102 | countlen = countlen - c; |
| 2103 | count = countlen * 2 + indexesleft_count; |
| 2104 | for (n = 0; n < count; n++) { // <= |
| 2105 | c = read_vertices_0x1800(space, vert + ((n + 2) & 3), address, 1); |
| 2106 | address = address + c * 4; |
| 2107 | countlen = countlen - c; |
| 2108 | convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1); |
| 2109 | if (xy[(n + 2) & 3].y > 293800000.0) |
| 2110 | xy[(n + 2) & 3].y = xy[(n + 2) & 3].y + 1.0; |
| 2111 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]); |
| 2112 | } |
| 2113 | } |
| 2114 | while (countlen > 0) { |
| 2115 | data = space.read_dword(address); |
| 2116 | n = (indexesleft_first + indexesleft_count) & 7; |
| 2117 | indexesleft[n] = data & 0xffff; |
| 2118 | indexesleft[(n + 1) & 7] = (data >> 16) & 0xffff; |
| 2119 | indexesleft_count = indexesleft_count + 2; |
| 2120 | address += 4; |
| 2121 | countlen--; |
| 2122 | } |
| 2123 | wait(); |
| 2124 | } |
| 2125 | else { |
| 2126 | logerror("Unsupported primitive %d for method 0x1800\n", type); |
| 2127 | countlen = 0; |
| 2128 | } |
| 2129 | } |
| 2130 | if (maddress == 0x1818) { |
| 2131 | int n; |
| 2132 | int type; |
| 2133 | render_delegate renderspans; |
| 2134 | |
| 2135 | if (((channel[chanel][subchannel].object.method[0x1e60 / 4] & 7) > 0) && (combiner.used != 0)) { |
| 2136 | renderspans = render_delegate(FUNC(nv2a_renderer::render_register_combiners), this); |
| 2137 | } |
| 2138 | else if (texture[0].enabled) { |
| 2139 | renderspans = render_delegate(FUNC(nv2a_renderer::render_texture_simple), this); |
| 2140 | } |
| 2141 | else |
| 2142 | renderspans = render_delegate(FUNC(nv2a_renderer::render_color), this); |
| 2143 | // vertices are taken from the next words, not from a vertex buffer |
| 2144 | // first send primitive type with 17fc |
| 2145 | // then countlen number of dwords with 1818 |
| 2146 | // end with 17fc primitive type 0 |
| 2147 | // at 1760 16 words specify the vertex format:for each possible vertex attribute the number of components (0=not present) and type of each |
| 2148 | type = channel[chanel][subchannel].object.method[0x17fc / 4]; |
| 2149 | if (type == nv2a_renderer::TRIANGLE_FAN) { |
| 2150 | vertex_nv vert[3]; |
| 2151 | vertex_t xy[3]; |
| 2152 | int c; |
| 2153 | |
| 2154 | c = read_vertices_0x1818(space, vert, address, 2); |
| 2155 | convert_vertices_poly(vert, xy, 2); |
| 2156 | countlen = countlen - c; |
| 2157 | if (countlen < 0) { |
| 2158 | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 2159 | countlen = 0; |
| 2160 | return; |
| 2161 | } |
| 2162 | address = address + c * 4; |
| 2163 | for (n = 1; countlen > 0; n++) { |
| 2164 | c = read_vertices_0x1818(space, vert + ((n & 1) + 1), address, 1); |
| 2165 | countlen = countlen - c; |
| 2166 | if (countlen < 0) { |
| 2167 | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 2168 | countlen = 0; |
| 2169 | break; |
| 2170 | } |
| 2171 | address = address + c * 4; |
| 2172 | convert_vertices_poly(vert + ((n & 1) + 1), xy + ((n & 1) + 1), 1); |
| 2173 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[0], xy[(~n & 1) + 1], xy[(n & 1) + 1]); |
| 2174 | } |
| 2175 | wait(); |
| 2176 | } |
| 2177 | else if (type == nv2a_renderer::TRIANGLE_STRIP) { |
| 2178 | vertex_nv vert[4]; |
| 2179 | vertex_t xy[4]; |
| 2180 | int c; |
| 2181 | |
| 2182 | c = read_vertices_0x1818(space, vert, address, 2); |
| 2183 | convert_vertices_poly(vert, xy, 2); |
| 2184 | countlen = countlen - c; |
| 2185 | if (countlen < 0) { |
| 2186 | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 2187 | countlen = 0; |
| 2188 | return; |
| 2189 | } |
| 2190 | address = address + c * 4; |
| 2191 | for (n = 0; countlen > 0; n++) { |
| 2192 | c = read_vertices_0x1818(space, vert + ((n + 2) & 3), address, 1); |
| 2193 | convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1); |
| 2194 | countlen = countlen - c; |
| 2195 | if (countlen < 0) { |
| 2196 | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 2197 | countlen = 0; |
| 2198 | break; |
| 2199 | } |
| 2200 | address = address + c * 4; |
| 2201 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]); |
| 2202 | } |
| 2203 | wait(); |
| 2204 | } |
| 2205 | else if (type == nv2a_renderer::QUADS) { |
| 2206 | while (countlen > 0) { |
| 2207 | vertex_nv vert[4]; |
| 2208 | vertex_t xy[4]; |
| 2209 | int c; |
| 2210 | |
| 2211 | c = read_vertices_0x1818(space, vert, address, 4); |
| 2212 | convert_vertices_poly(vert, xy, 4); |
| 2213 | countlen = countlen - c; |
| 2214 | if (countlen < 0) { |
| 2215 | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 2216 | countlen = 0; |
| 2217 | break; |
| 2218 | } |
| 2219 | address = address + c * 4; |
| 2220 | render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv |
| 2221 | } |
| 2222 | wait(); |
| 2223 | } |
| 2224 | else if (type == nv2a_renderer::QUAD_STRIP) { |
| 2225 | vertex_nv vert[4]; |
| 2226 | vertex_t xy[4]; |
| 2227 | int c; |
| 2228 | |
| 2229 | c = read_vertices_0x1818(space, vert, address, 2); |
| 2230 | convert_vertices_poly(vert, xy, 2); |
| 2231 | countlen = countlen - c; |
| 2232 | if (countlen < 0) { |
| 2233 | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 2234 | countlen = 0; |
| 2235 | return; |
| 2236 | } |
| 2237 | address = address + c * 4; |
| 2238 | for (n = 0; countlen > 0; n += 2) { |
| 2239 | c = read_vertices_0x1818(space, vert + ((n + 2) & 3), address + ((n + 2) & 3), 2); |
| 2240 | convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 2); |
| 2241 | countlen = countlen - c; |
| 2242 | if (countlen < 0) { |
| 2243 | logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen); |
| 2244 | countlen = 0; |
| 2245 | return; |
| 2246 | } |
| 2247 | address = address + c * 4; |
| 2248 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[n & 3], xy[(n + 1) & 3], xy[(n + 2) & 3]); |
| 2249 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[(n + 2) & 3], xy[(n + 1) & 3], xy[(n + 3) & 3]); |
| 2250 | } |
| 2251 | wait(); |
| 2252 | } |
| 2253 | else { |
| 2254 | logerror("Unsupported primitive %d for method 0x1818\n", type); |
| 2255 | countlen = 0; |
| 2256 | } |
| 2257 | } |
| 2258 | if ((maddress >= 0x1720) && (maddress < 0x1760)) { |
| 2259 | int bit = method - 0x1720 / 4; |
| 2260 | |
| 2261 | if (data & 0x80000000) |
| 2262 | vertexbuffer_address[bit] = (data & 0x0fffffff) + dma_offset[1]; |
| 2263 | else |
| 2264 | vertexbuffer_address[bit] = (data & 0x0fffffff) + dma_offset[0]; |
| 2265 | } |
| 2266 | if ((maddress >= 0x1760) && (maddress < 0x17A0)) { |
| 2267 | int bit = method - 0x1760 / 4; |
| 2268 | |
| 2269 | vertexbuffer_stride[bit] = (data >> 8) & 255; |
| 2270 | vertexbuffer_kind[bit] = data & 15; |
| 2271 | vertexbuffer_size[bit] = (data >> 4) & 15; |
| 2272 | switch (vertexbuffer_kind[bit]) { |
| 2273 | case NV2A_VTXBUF_TYPE_UNKNOWN_0: |
| 2274 | vertex_attribute_words[bit] = (vertexbuffer_size[bit] * 1) >> 2; |
| 2275 | break; |
| 2276 | case NV2A_VTXBUF_TYPE_FLOAT: |
| 2277 | vertex_attribute_words[bit] = (vertexbuffer_size[bit] * 4) >> 2; |
| 2278 | break; |
| 2279 | case NV2A_VTXBUF_TYPE_UBYTE: |
| 2280 | vertex_attribute_words[bit] = (vertexbuffer_size[bit] * 1) >> 2; |
| 2281 | break; |
| 2282 | case NV2A_VTXBUF_TYPE_USHORT: |
| 2283 | vertex_attribute_words[bit] = (vertexbuffer_size[bit] * 2) >> 2; |
| 2284 | break; |
| 2285 | case NV2A_VTXBUF_TYPE_UNKNOWN_6: |
| 2286 | vertex_attribute_words[bit] = (vertexbuffer_size[bit] * 4) >> 2; |
| 2287 | break; |
| 2288 | default: |
| 2289 | vertex_attribute_words[bit] = 0; |
| 2290 | } |
| 2291 | if (vertexbuffer_size[bit] > 0) |
| 2292 | enabled_vertex_attributes |= (1 << bit); |
| 2293 | else |
| 2294 | enabled_vertex_attributes &= ~(1 << bit); |
| 2295 | for (int n = bit + 1; n < 16; n++) { |
| 2296 | if ((enabled_vertex_attributes & (1 << (n - 1))) != 0) |
| 2297 | vertex_attribute_offset[n] = vertex_attribute_offset[n - 1] + vertex_attribute_words[n - 1]; |
| 2298 | else |
| 2299 | vertex_attribute_offset[n] = vertex_attribute_offset[n - 1]; |
| 2300 | } |
| 2301 | countlen--; |
| 2302 | } |
| 2303 | if ((maddress == 0x1d6c) || (maddress == 0x1d70) || (maddress == 0x1a4)) |
| 2304 | countlen--; |
| 2305 | if (maddress == 0x019c) { |
| 2306 | geforce_read_dma_object(data, dma_offset[0], dma_size[0]); |
| 2307 | } |
| 2308 | if (maddress == 0x01a0) { |
| 2309 | geforce_read_dma_object(data, dma_offset[1], dma_size[1]); |
| 2310 | } |
| 2311 | if (maddress == 0x1d70) { |
| 2312 | // with 1d70 write the value at offest [1d6c] inside dma object [1a4] |
| 2313 | UINT32 offset, base; |
| 2314 | UINT32 dmahand, dmaoff, smasiz; |
| 2315 | |
| 2316 | offset = channel[chanel][subchannel].object.method[0x1d6c / 4]; |
| 2317 | dmahand = channel[chanel][subchannel].object.method[0x1a4 / 4]; |
| 2318 | geforce_read_dma_object(dmahand, dmaoff, smasiz); |
| 2319 | base = dmaoff; |
| 2320 | space.write_dword(base + offset, data); |
| 2321 | countlen--; |
| 2322 | } |
| 2323 | if (maddress == 0x1d94) { |
| 2324 | // possible buffers: color, depth, stencil, and accumulation |
| 2325 | // clear framebuffer |
| 2326 | if (data & 0xf0) { |
| 2327 | // clear colors |
| 2328 | UINT32 color = channel[chanel][subchannel].object.method[0x1d90 / 4]; |
| 2329 | fb.fill(color); |
| 2330 | //printf("clearscreen\n\r"); |
| 2331 | } |
| 2332 | if (data & 0x03) { |
| 2333 | // clear stencil+zbuffer |
| 2334 | } |
| 2335 | countlen--; |
| 2336 | } |
| 2337 | if (maddress == 0x0210) { |
| 2338 | // framebuffer offset ? |
| 2339 | countlen--; |
| 2340 | } |
| 2341 | if (maddress == 0x0214) { |
| 2342 | // zbuffer offset ? |
| 2343 | countlen--; |
| 2344 | } |
| 2345 | if (maddress == 0x0300) { |
| 2346 | alpha_test_enabled = data != 0; |
| 2347 | } |
| 2348 | if (maddress == 0x033c) { |
| 2349 | alpha_func = data; |
| 2350 | } |
| 2351 | if (maddress == 0x0340) { |
| 2352 | alpha_reference = data; |
| 2353 | } |
| 2354 | if (maddress == 0x0304) { |
| 2355 | if (logical_operation_enabled) |
| 2356 | blending_enabled = false; |
| 2357 | else |
| 2358 | blending_enabled = data != 0; |
| 2359 | } |
| 2360 | if (maddress == 0x0344) { |
| 2361 | blend_function_source = data; |
| 2362 | } |
| 2363 | if (maddress == 0x0348) { |
| 2364 | blend_function_destination = data; |
| 2365 | } |
| 2366 | if (maddress == 0x034c) { |
| 2367 | blend_color = data; |
| 2368 | } |
| 2369 | if (maddress == 0x0350) { |
| 2370 | blend_equation = data; |
| 2371 | } |
| 2372 | if (maddress == 0x0d40) { |
| 2373 | if (data != 0) |
| 2374 | blending_enabled = false; |
| 2375 | else |
| 2376 | blending_enabled = channel[chanel][subchannel].object.method[0x0304 / 4] != 0; |
| 2377 | logical_operation_enabled = data != 0; |
| 2378 | } |
| 2379 | if (maddress == 0x0d44) { |
| 2380 | logical_operation = data; |
| 2381 | } |
| 2382 | // Texture Units |
| 2383 | if ((maddress >= 0x1b00) && (maddress < 0x1c00)) { |
| 2384 | int unit;//,off; |
| 2385 | |
| 2386 | unit = (maddress >> 6) & 3; |
| 2387 | //off=maddress & 0xc0; |
| 2388 | maddress = maddress & ~0xc0; |
| 2389 | if (maddress == 0x1b00) { |
| 2390 | UINT32 offset;//,base; |
| 2391 | //UINT32 dmahand,dmaoff,dmasiz; |
| 2392 | |
| 2393 | offset = data; |
| 2394 | texture[unit].buffer = space.get_read_ptr(offset); |
| 2395 | /*if (dma0 != 0) { |
| 2396 | dmahand=channel[channel][subchannel].object.method[0x184/4]; |
| 2397 | geforce_read_dma_object(dmahand,dmaoff,smasiz); |
| 2398 | } else if (dma1 != 0) { |
| 2399 | dmahand=channel[channel][subchannel].object.method[0x188/4]; |
| 2400 | geforce_read_dma_object(dmahand,dmaoff,smasiz); |
| 2401 | }*/ |
| 2402 | } |
| 2403 | if (maddress == 0x1b04) { |
| 2404 | //int dma0,dma1,cubic,noborder,dims,mipmap; |
| 2405 | int basesizeu, basesizev, basesizew, format; |
| 2406 | |
| 2407 | //dma0=(data >> 0) & 1; |
| 2408 | //dma1=(data >> 1) & 1; |
| 2409 | //cubic=(data >> 2) & 1; |
| 2410 | //noborder=(data >> 3) & 1; |
| 2411 | //dims=(data >> 4) & 15; |
| 2412 | //mipmap=(data >> 19) & 1; |
| 2413 | format = (data >> 8) & 255; |
| 2414 | basesizeu = (data >> 20) & 15; |
| 2415 | basesizev = (data >> 24) & 15; |
| 2416 | basesizew = (data >> 28) & 15; |
| 2417 | texture[unit].sizeu = 1 << basesizeu; |
| 2418 | texture[unit].sizev = 1 << basesizev; |
| 2419 | texture[unit].sizew = 1 << basesizew; |
| 2420 | texture[unit].dilate = dilatechose[(basesizeu << 4) + basesizev]; |
| 2421 | texture[unit].format = format; |
| 2422 | if (debug_grab_texttype == format) { |
| 2423 | FILE *f; |
| 2424 | int written; |
| 2425 | |
| 2426 | debug_grab_texttype = -1; |
| 2427 | f = fopen(debug_grab_textfile, "wb"); |
| 2428 | if (f) { |
| 2429 | written = (int)fwrite(texture[unit].buffer, texture[unit].sizeu*texture[unit].sizev * 4, 1, f); |
| 2430 | fclose(f); |
| 2431 | logerror("Written %d bytes of texture to specified file\n", written); |
| 2432 | } |
| 2433 | else |
| 2434 | logerror("Unable to save texture to specified file\n"); |
| 2435 | } |
| 2436 | } |
| 2437 | if (maddress == 0x1b0c) { |
| 2438 | // enable texture |
| 2439 | int enable; |
| 2440 | |
| 2441 | enable = (data >> 30) & 1; |
| 2442 | texture[unit].enabled = enable; |
| 2443 | } |
| 2444 | if (maddress == 0x1b10) { |
| 2445 | texture[unit].rectangle_pitch = data >> 16; |
| 2446 | } |
| 2447 | countlen--; |
| 2448 | } |
| 2449 | // modelview matrix |
| 2450 | if ((maddress >= 0x0480) && (maddress < 0x04c0)) { |
| 2451 | maddress = (maddress - 0x0480) / 4; |
| 2452 | *(UINT32 *)(&matrix.modelview[maddress]) = data; |
| 2453 | countlen--; |
| 2454 | } |
| 2455 | // inverse modelview matrix |
| 2456 | if ((maddress >= 0x0580) && (maddress < 0x05c0)) { |
| 2457 | maddress = (maddress - 0x0580) / 4; |
| 2458 | *(UINT32 *)(&matrix.modelview_inverse[maddress]) = data; |
| 2459 | countlen--; |
| 2460 | } |
| 2461 | // projection matrix |
| 2462 | if ((maddress >= 0x0680) && (maddress < 0x06c0)) { |
| 2463 | maddress = (maddress - 0x0680) / 4; |
| 2464 | *(UINT32 *)(&matrix.projection[maddress]) = data; |
| 2465 | countlen--; |
| 2466 | } |
| 2467 | // viewport translate |
| 2468 | if ((maddress >= 0x0a20) && (maddress < 0x0a30)) { |
| 2469 | maddress = (maddress - 0x0a20) / 4; |
| 2470 | *(UINT32 *)(&matrix.translate[maddress]) = data; |
| 2471 | // set corresponding vertex shader constant too |
| 2472 | vertexprogram.exec.c_constant[59].iv[maddress] = data; // constant -37 |
| 2473 | countlen--; |
| 2474 | } |
| 2475 | // viewport scale |
| 2476 | if ((maddress >= 0x0af0) && (maddress < 0x0b00)) { |
| 2477 | maddress = (maddress - 0x0af0) / 4; |
| 2478 | *(UINT32 *)(&matrix.scale[maddress]) = data; |
| 2479 | // set corresponding vertex shader constant too |
| 2480 | vertexprogram.exec.c_constant[58].iv[maddress] = data; // constant -38 |
| 2481 | countlen--; |
| 2482 | } |
| 2483 | // Vertex program (shader) |
| 2484 | if (maddress == 0x1e94) { |
| 2485 | /*if (data == 2) |
| 2486 | logerror("Enabled vertex program\n"); |
| 2487 | else if (data == 4) |
| 2488 | logerror("Enabled fixed function pipeline\n"); |
| 2489 | else if (data == 6) |
| 2490 | logerror("Enabled both fixed function pipeline and vertex program ?\n"); |
| 2491 | else |
| 2492 | logerror("Unknown value %d to method 0x1e94\n",data);*/ |
| 2493 | vertex_pipeline = data & 6; |
| 2494 | countlen--; |
| 2495 | } |
| 2496 | if (maddress == 0x1e9c) { |
| 2497 | //logerror("VP_UPLOAD_FROM_ID %d\n",data); |
| 2498 | vertexprogram.upload_instruction_index = data; |
| 2499 | vertexprogram.upload_instruction_component = 0; |
| 2500 | countlen--; |
| 2501 | } |
| 2502 | if (maddress == 0x1ea0) { |
| 2503 | //logerror("VP_START_FROM_ID %d\n",data); |
| 2504 | vertexprogram.instructions = vertexprogram.upload_instruction_index; |
| 2505 | vertexprogram.start_instruction = data; |
| 2506 | countlen--; |
| 2507 | } |
| 2508 | if (maddress == 0x1ea4) { |
| 2509 | //logerror("VP_UPLOAD_CONST_ID %d\n",data); |
| 2510 | vertexprogram.upload_parameter_index = data; |
| 2511 | vertexprogram.upload_parameter_component = 0; |
| 2512 | countlen--; |
| 2513 | } |
| 2514 | if ((maddress >= 0x0b00) && (maddress < 0x0b80)) { |
| 2515 | //logerror("VP_UPLOAD_INST\n"); |
| 2516 | if (vertexprogram.upload_instruction_index < 192) { |
| 2517 | vertexprogram.exec.op[vertexprogram.upload_instruction_index].i[vertexprogram.upload_instruction_component] = data; |
| 2518 | vertexprogram.exec.op[vertexprogram.upload_instruction_index].modified |= (1 << vertexprogram.upload_instruction_component); |
| 2519 | } |
| 2520 | else |
| 2521 | logerror("Need to increase size of vertexprogram.instruction to %d\n\r", vertexprogram.upload_instruction_index); |
| 2522 | if (vertexprogram.exec.op[vertexprogram.upload_instruction_index].modified == 15) { |
| 2523 | vertexprogram.exec.op[vertexprogram.upload_instruction_index].modified = 0; |
| 2524 | vertexprogram.exec.decode_instruction(vertexprogram.upload_instruction_index); |
| 2525 | } |
| 2526 | vertexprogram.upload_instruction_component++; |
| 2527 | if (vertexprogram.upload_instruction_component >= 4) { |
| 2528 | vertexprogram.upload_instruction_component = 0; |
| 2529 | vertexprogram.upload_instruction_index++; |
| 2530 | } |
| 2531 | } |
| 2532 | if ((maddress >= 0x0b80) && (maddress < 0x0c00)) { |
| 2533 | //logerror("VP_UPLOAD_CONST\n"); |
| 2534 | if (vertexprogram.upload_parameter_index < 256) |
| 2535 | vertexprogram.exec.c_constant[vertexprogram.upload_parameter_index].iv[vertexprogram.upload_parameter_component] = data; |
| 2536 | else |
| 2537 | logerror("Need to increase size of vertexprogram.parameter to %d\n\r", vertexprogram.upload_parameter_index); |
| 2538 | vertexprogram.upload_parameter_component++; |
| 2539 | if (vertexprogram.upload_parameter_component >= 4) { |
| 2540 | vertexprogram.upload_parameter_component = 0; |
| 2541 | vertexprogram.upload_parameter_index++; |
| 2542 | } |
| 2543 | } |
| 2544 | // Register combiners |
| 2545 | if (maddress == 0x1e60) { |
| 2546 | combiner.stages = data & 15; |
| 2547 | countlen--; |
| 2548 | } |
| 2549 | if (maddress == 0x0288) { |
| 2550 | combiner.final.mapin_rgbD_input = data & 15; |
| 2551 | combiner.final.mapin_rgbD_component = (data >> 4) & 1; |
| 2552 | combiner.final.mapin_rgbD_mapping = (data >> 5) & 7; |
| 2553 | combiner.final.mapin_rgbC_input = (data >> 8) & 15; |
| 2554 | combiner.final.mapin_rgbC_component = (data >> 12) & 1; |
| 2555 | combiner.final.mapin_rgbC_mapping = (data >> 13) & 7; |
| 2556 | combiner.final.mapin_rgbB_input = (data >> 16) & 15; |
| 2557 | combiner.final.mapin_rgbB_component = (data >> 20) & 1; |
| 2558 | combiner.final.mapin_rgbB_mapping = (data >> 21) & 7; |
| 2559 | combiner.final.mapin_rgbA_input = (data >> 24) & 15; |
| 2560 | combiner.final.mapin_rgbA_component = (data >> 28) & 1; |
| 2561 | combiner.final.mapin_rgbA_mapping = (data >> 29) & 7; |
| 2562 | countlen--; |
| 2563 | } |
| 2564 | if (maddress == 0x028c) { |
| 2565 | combiner.final.color_sum_clamp = (data >> 7) & 1; |
| 2566 | combiner.final.mapin_aG_input = (data >> 8) & 15; |
| 2567 | combiner.final.mapin_aG_component = (data >> 12) & 1; |
| 2568 | combiner.final.mapin_aG_mapping = (data >> 13) & 7; |
| 2569 | combiner.final.mapin_rgbF_input = (data >> 16) & 15; |
| 2570 | combiner.final.mapin_rgbF_component = (data >> 20) & 1; |
| 2571 | combiner.final.mapin_rgbF_mapping = (data >> 21) & 7; |
| 2572 | combiner.final.mapin_rgbE_input = (data >> 24) & 15; |
| 2573 | combiner.final.mapin_rgbE_component = (data >> 28) & 1; |
| 2574 | combiner.final.mapin_rgbE_mapping = (data >> 29) & 7; |
| 2575 | countlen--; |
| 2576 | } |
| 2577 | if (maddress == 0x1e20) { |
| 2578 | combiner_argb8_float(data, combiner.final.register_constantcolor0); |
| 2579 | countlen--; |
| 2580 | } |
| 2581 | if (maddress == 0x1e24) { |
| 2582 | combiner_argb8_float(data, combiner.final.register_constantcolor1); |
| 2583 | countlen--; |
| 2584 | } |
| 2585 | if ((maddress >= 0x0260) && (maddress < 0x0280)) { |
| 2586 | int n; |
| 2587 | |
| 2588 | n = (maddress - 0x0260) >> 2; |
| 2589 | combiner.stage[n].mapin_aD_input = data & 15; |
| 2590 | combiner.stage[n].mapin_aD_component = (data >> 4) & 1; |
| 2591 | combiner.stage[n].mapin_aD_mapping = (data >> 5) & 7; |
| 2592 | combiner.stage[n].mapin_aC_input = (data >> 8) & 15; |
| 2593 | combiner.stage[n].mapin_aC_component = (data >> 12) & 1; |
| 2594 | combiner.stage[n].mapin_aC_mapping = (data >> 13) & 7; |
| 2595 | combiner.stage[n].mapin_aB_input = (data >> 16) & 15; |
| 2596 | combiner.stage[n].mapin_aB_component = (data >> 20) & 1; |
| 2597 | combiner.stage[n].mapin_aB_mapping = (data >> 21) & 7; |
| 2598 | combiner.stage[n].mapin_aA_input = (data >> 24) & 15; |
| 2599 | combiner.stage[n].mapin_aA_component = (data >> 28) & 1; |
| 2600 | combiner.stage[n].mapin_aA_mapping = (data >> 29) & 7; |
| 2601 | countlen--; |
| 2602 | } |
| 2603 | if ((maddress >= 0x0ac0) && (maddress < 0x0ae0)) { |
| 2604 | int n; |
| 2605 | |
| 2606 | n = (maddress - 0x0ac0) >> 2; |
| 2607 | combiner.stage[n].mapin_rgbD_input = data & 15; |
| 2608 | combiner.stage[n].mapin_rgbD_component = (data >> 4) & 1; |
| 2609 | combiner.stage[n].mapin_rgbD_mapping = (data >> 5) & 7; |
| 2610 | combiner.stage[n].mapin_rgbC_input = (data >> 8) & 15; |
| 2611 | combiner.stage[n].mapin_rgbC_component = (data >> 12) & 1; |
| 2612 | combiner.stage[n].mapin_rgbC_mapping = (data >> 13) & 7; |
| 2613 | combiner.stage[n].mapin_rgbB_input = (data >> 16) & 15; |
| 2614 | combiner.stage[n].mapin_rgbB_component = (data >> 20) & 1; |
| 2615 | combiner.stage[n].mapin_rgbB_mapping = (data >> 21) & 7; |
| 2616 | combiner.stage[n].mapin_rgbA_input = (data >> 24) & 15; |
| 2617 | combiner.stage[n].mapin_rgbA_component = (data >> 28) & 1; |
| 2618 | combiner.stage[n].mapin_rgbA_mapping = (data >> 29) & 7; |
| 2619 | countlen--; |
| 2620 | } |
| 2621 | if ((maddress >= 0x0a60) && (maddress < 0x0a80)) { |
| 2622 | int n; |
| 2623 | |
| 2624 | n = (maddress - 0x0a60) >> 2; |
| 2625 | combiner_argb8_float(data, combiner.stage[n].register_constantcolor0); |
| 2626 | countlen--; |
| 2627 | } |
| 2628 | if ((maddress >= 0x0a80) && (maddress < 0x0aa0)) { |
| 2629 | int n; |
| 2630 | |
| 2631 | n = (maddress - 0x0a80) >> 2; |
| 2632 | combiner_argb8_float(data, combiner.stage[n].register_constantcolor1); |
| 2633 | countlen--; |
| 2634 | } |
| 2635 | if ((maddress >= 0x0aa0) && (maddress < 0x0ac0)) { |
| 2636 | int n; |
| 2637 | |
| 2638 | n = (maddress - 0x0aa0) >> 2; |
| 2639 | combiner.stage[n].mapout_aCD_output = data & 15; |
| 2640 | combiner.stage[n].mapout_aAB_output = (data >> 4) & 15; |
| 2641 | combiner.stage[n].mapout_aSUM_output = (data >> 8) & 15; |
| 2642 | combiner.stage[n].mapout_aCD_dotproduct = (data >> 12) & 1; |
| 2643 | combiner.stage[n].mapout_aAB_dotproduct = (data >> 13) & 1; |
| 2644 | combiner.stage[n].mapout_a_muxsum = (data >> 14) & 1; |
| 2645 | combiner.stage[n].mapout_a_bias = (data >> 15) & 1; |
| 2646 | combiner.stage[n].mapout_a_scale = (data >> 16) & 3; |
| 2647 | //combiner.=(data >> 27) & 7; |
| 2648 | countlen--; |
| 2649 | } |
| 2650 | if ((maddress >= 0x1e40) && (maddress < 0x1e60)) { |
| 2651 | int n; |
| 2652 | |
| 2653 | n = (maddress - 0x1e40) >> 2; |
| 2654 | combiner.stage[n].mapout_rgbCD_output = data & 15; |
| 2655 | combiner.stage[n].mapout_rgbAB_output = (data >> 4) & 15; |
| 2656 | combiner.stage[n].mapout_rgbSUM_output = (data >> 8) & 15; |
| 2657 | combiner.stage[n].mapout_rgbCD_dotproduct = (data >> 12) & 1; |
| 2658 | combiner.stage[n].mapout_rgbAB_dotproduct = (data >> 13) & 1; |
| 2659 | combiner.stage[n].mapout_rgb_muxsum = (data >> 14) & 1; |
| 2660 | combiner.stage[n].mapout_rgb_bias = (data >> 15) & 1; |
| 2661 | combiner.stage[n].mapout_rgb_scale = (data >> 16) & 3; |
| 2662 | //combiner.=(data >> 27) & 7; |
| 2663 | countlen--; |
| 2664 | } |
| 2665 | } |
| 2666 | |
| 2667 | int nv2a_renderer::toggle_register_combiners_usage() |
| 2668 | { |
| 2669 | combiner.used = 1 - combiner.used; |
| 2670 | return combiner.used; |
| 2671 | } |
| 2672 | |
| 2673 | void nv2a_renderer::debug_grab_texture(int type, const char *filename) |
| 2674 | { |
| 2675 | debug_grab_texttype = type; |
| 2676 | if (debug_grab_textfile == NULL) |
| 2677 | debug_grab_textfile = (char *)malloc(128); |
| 2678 | strncpy(debug_grab_textfile, filename, 127); |
| 2679 | } |
| 2680 | |
| 2681 | void nv2a_renderer::debug_grab_vertex_program_slot(int slot, UINT32 *instruction) |
| 2682 | { |
| 2683 | if (slot >= 1024 / 4) |
| 2684 | return; |
| 2685 | instruction[0] = vertexprogram.exec.op[slot].i[0]; |
| 2686 | instruction[1] = vertexprogram.exec.op[slot].i[1]; |
| 2687 | instruction[2] = vertexprogram.exec.op[slot].i[2]; |
| 2688 | instruction[3] = vertexprogram.exec.op[slot].i[3]; |
| 2689 | } |
| 2690 | |
| 2691 | void nv2a_renderer::savestate_items() |
| 2692 | { |
| 2693 | } |
| 2694 | |
| 2695 | void nv2a_renderer::combiner_argb8_float(UINT32 color, float reg[4]) |
| 2696 | { |
| 2697 | reg[0] = (float)(color & 0xff) / 255.0; |
| 2698 | reg[1] = (float)((color >> 8) & 0xff) / 255.0; |
| 2699 | reg[2] = (float)((color >> 16) & 0xff) / 255.0; |
| 2700 | reg[3] = (float)((color >> 24) & 0xff) / 255.0; |
| 2701 | } |
| 2702 | |
| 2703 | UINT32 nv2a_renderer::combiner_float_argb8(float reg[4]) |
| 2704 | { |
| 2705 | UINT32 r, g, b, a; |
| 2706 | |
| 2707 | a = reg[3] * 255.0; |
| 2708 | b = reg[2] * 255.0; |
| 2709 | g = reg[1] * 255.0; |
| 2710 | r = reg[0] * 255.0; |
| 2711 | return (a << 24) | (r << 16) | (g << 8) | b; |
| 2712 | } |
| 2713 | |
| 2714 | float nv2a_renderer::combiner_map_input_select(int code, int index) |
| 2715 | { |
| 2716 | switch (code) { |
| 2717 | case 0: |
| 2718 | default: |
| 2719 | return combiner.register_zero[index]; |
| 2720 | case 1: |
| 2721 | return combiner.register_color0[index]; |
| 2722 | case 2: |
| 2723 | return combiner.register_color1[index]; |
| 2724 | case 3: |
| 2725 | return combiner.register_fogcolor[index]; |
| 2726 | case 4: |
| 2727 | return combiner.register_primarycolor[index]; |
| 2728 | case 5: |
| 2729 | return combiner.register_secondarycolor[index]; |
| 2730 | case 8: |
| 2731 | return combiner.register_texture0color[index]; |
| 2732 | case 9: |
| 2733 | return combiner.register_texture1color[index]; |
| 2734 | case 10: |
| 2735 | return combiner.register_texture2color[index]; |
| 2736 | case 11: |
| 2737 | return combiner.register_texture3color[index]; |
| 2738 | case 12: |
| 2739 | return combiner.register_spare0[index]; |
| 2740 | case 13: |
| 2741 | return combiner.register_spare1[index]; |
| 2742 | case 14: |
| 2743 | return combiner.variable_sumclamp[index]; |
| 2744 | case 15: |
| 2745 | return combiner.variable_EF[index]; |
| 2746 | } |
| 2747 | |
| 2748 | // never executed |
| 2749 | //return 0; |
| 2750 | } |
| 2751 | |
| 2752 | float *nv2a_renderer::combiner_map_input_select3(int code) |
| 2753 | { |
| 2754 | switch (code) { |
| 2755 | case 0: |
| 2756 | default: |
| 2757 | return combiner.register_zero; |
| 2758 | case 1: |
| 2759 | return combiner.register_color0; |
| 2760 | case 2: |
| 2761 | return combiner.register_color1; |
| 2762 | case 3: |
| 2763 | return combiner.register_fogcolor; |
| 2764 | case 4: |
| 2765 | return combiner.register_primarycolor; |
| 2766 | case 5: |
| 2767 | return combiner.register_secondarycolor; |
| 2768 | case 8: |
| 2769 | return combiner.register_texture0color; |
| 2770 | case 9: |
| 2771 | return combiner.register_texture1color; |
| 2772 | case 10: |
| 2773 | return combiner.register_texture2color; |
| 2774 | case 11: |
| 2775 | return combiner.register_texture3color; |
| 2776 | case 12: |
| 2777 | return combiner.register_spare0; |
| 2778 | case 13: |
| 2779 | return combiner.register_spare1; |
| 2780 | case 14: |
| 2781 | return combiner.variable_sumclamp; |
| 2782 | case 15: |
| 2783 | return combiner.variable_EF; |
| 2784 | } |
| 2785 | |
| 2786 | // never executed |
| 2787 | //return 0; |
| 2788 | } |
| 2789 | |
| 2790 | float *nv2a_renderer::combiner_map_output_select3(int code) |
| 2791 | { |
| 2792 | switch (code) { |
| 2793 | case 0: |
| 2794 | return 0; |
| 2795 | case 1: |
| 2796 | return 0; |
| 2797 | case 2: |
| 2798 | return 0; |
| 2799 | case 3: |
| 2800 | return 0; |
| 2801 | case 4: |
| 2802 | return combiner.register_primarycolor; |
| 2803 | case 5: |
| 2804 | return combiner.register_secondarycolor; |
| 2805 | case 8: |
| 2806 | return combiner.register_texture0color; |
| 2807 | case 9: |
| 2808 | return combiner.register_texture1color; |
| 2809 | case 10: |
| 2810 | return combiner.register_texture2color; |
| 2811 | case 11: |
| 2812 | return combiner.register_texture3color; |
| 2813 | case 12: |
| 2814 | return combiner.register_spare0; |
| 2815 | case 13: |
| 2816 | return combiner.register_spare1; |
| 2817 | case 14: |
| 2818 | return 0; |
| 2819 | case 15: |
| 2820 | default: |
| 2821 | return 0; |
| 2822 | } |
| 2823 | } |
| 2824 | |
| 2825 | float nv2a_renderer::combiner_map_input_function(int code, float value) |
| 2826 | { |
| 2827 | float t; |
| 2828 | |
| 2829 | switch (code) { |
| 2830 | case 0: |
| 2831 | return MAX(0.0, value); |
| 2832 | case 1: |
| 2833 | t = MAX(value, 0.0); |
| 2834 | return 1.0 - MIN(t, 1.0); |
| 2835 | case 2: |
| 2836 | return 2.0 * MAX(0.0, value) - 1.0; |
| 2837 | case 3: |
| 2838 | return -2.0 * MAX(0.0, value) + 1.0; |
| 2839 | case 4: |
| 2840 | return MAX(0.0, value) - 0.5; |
| 2841 | case 5: |
| 2842 | return -MAX(0.0, value) + 0.5; |
| 2843 | case 6: |
| 2844 | return value; |
| 2845 | case 7: |
| 2846 | default: |
| 2847 | return -value; |
| 2848 | } |
| 2849 | |
| 2850 | // never executed |
| 2851 | //return 0; |
| 2852 | } |
| 2853 | |
| 2854 | void nv2a_renderer::combiner_map_input_function3(int code, float *data) |
| 2855 | { |
| 2856 | float t; |
| 2857 | |
| 2858 | switch (code) { |
| 2859 | case 0: |
| 2860 | data[0] = MAX(0.0, data[0]); |
| 2861 | data[1] = MAX(0.0, data[1]); |
| 2862 | data[2] = MAX(0.0, data[2]); |
| 2863 | break; |
| 2864 | case 1: |
| 2865 | t = MAX(data[0], 0.0); |
| 2866 | data[0] = 1.0 - MIN(t, 1.0); |
| 2867 | t = MAX(data[1], 0.0); |
| 2868 | data[1] = 1.0 - MIN(t, 1.0); |
| 2869 | t = MAX(data[2], 0.0); |
| 2870 | data[2] = 1.0 - MIN(t, 1.0); |
| 2871 | break; |
| 2872 | case 2: |
| 2873 | data[0] = 2.0 * MAX(0.0, data[0]) - 1.0; |
| 2874 | data[1] = 2.0 * MAX(0.0, data[1]) - 1.0; |
| 2875 | data[2] = 2.0 * MAX(0.0, data[2]) - 1.0; |
| 2876 | break; |
| 2877 | case 3: |
| 2878 | data[0] = -2.0 * MAX(0.0, data[0]) + 1.0; |
| 2879 | data[1] = -2.0 * MAX(0.0, data[1]) + 1.0; |
| 2880 | data[2] = -2.0 * MAX(0.0, data[2]) + 1.0; |
| 2881 | break; |
| 2882 | case 4: |
| 2883 | data[0] = MAX(0.0, data[0]) - 0.5; |
| 2884 | data[1] = MAX(0.0, data[1]) - 0.5; |
| 2885 | data[2] = MAX(0.0, data[2]) - 0.5; |
| 2886 | break; |
| 2887 | case 5: |
| 2888 | data[0] = -MAX(0.0, data[0]) + 0.5; |
| 2889 | data[1] = -MAX(0.0, data[1]) + 0.5; |
| 2890 | data[2] = -MAX(0.0, data[2]) + 0.5; |
| 2891 | break; |
| 2892 | case 6: |
| 2893 | return; |
| 2894 | case 7: |
| 2895 | default: |
| 2896 | data[0] = -data[0]; |
| 2897 | data[1] = -data[1]; |
| 2898 | data[2] = -data[2]; |
| 2899 | break; |
| 2900 | } |
| 2901 | } |
| 2902 | |
| 2903 | void nv2a_renderer::combiner_initialize_registers(UINT32 argb8[6]) |
| 2904 | { |
| 2905 | combiner_argb8_float(argb8[0], combiner.register_primarycolor); |
| 2906 | combiner_argb8_float(argb8[1], combiner.register_secondarycolor); |
| 2907 | combiner_argb8_float(argb8[2], combiner.register_texture0color); |
| 2908 | combiner_argb8_float(argb8[3], combiner.register_texture1color); |
| 2909 | combiner_argb8_float(argb8[4], combiner.register_texture2color); |
| 2910 | combiner_argb8_float(argb8[5], combiner.register_texture3color); |
| 2911 | combiner.register_spare0[3] = combiner.register_texture0color[3]; |
| 2912 | combiner.register_zero[0] = combiner.register_zero[1] = combiner.register_zero[2] = combiner.register_zero[3] = 0; |
| 2913 | } |
| 2914 | |
| 2915 | void nv2a_renderer::combiner_initialize_stage(int stage_number) |
| 2916 | { |
| 2917 | int n = stage_number; |
| 2918 | |
| 2919 | // put register_constantcolor0 in register_color0 |
| 2920 | combiner.register_color0[0] = combiner.stage[n].register_constantcolor0[0]; |
| 2921 | combiner.register_color0[1] = combiner.stage[n].register_constantcolor0[1]; |
| 2922 | combiner.register_color0[2] = combiner.stage[n].register_constantcolor0[2]; |
| 2923 | combiner.register_color0[3] = combiner.stage[n].register_constantcolor0[3]; |
| 2924 | // put register_constantcolor1 in register_color1 |
| 2925 | combiner.register_color1[0] = combiner.stage[n].register_constantcolor1[0]; |
| 2926 | combiner.register_color1[1] = combiner.stage[n].register_constantcolor1[1]; |
| 2927 | combiner.register_color1[2] = combiner.stage[n].register_constantcolor1[2]; |
| 2928 | combiner.register_color1[3] = combiner.stage[n].register_constantcolor1[3]; |
| 2929 | } |
| 2930 | |
| 2931 | void nv2a_renderer::combiner_initialize_final() |
| 2932 | { |
| 2933 | // put register_constantcolor0 in register_color0 |
| 2934 | combiner.register_color0[0] = combiner.final.register_constantcolor0[0]; |
| 2935 | combiner.register_color0[1] = combiner.final.register_constantcolor0[1]; |
| 2936 | combiner.register_color0[2] = combiner.final.register_constantcolor0[2]; |
| 2937 | combiner.register_color0[3] = combiner.final.register_constantcolor0[3]; |
| 2938 | // put register_constantcolor1 in register_color1 |
| 2939 | combiner.register_color1[0] = combiner.final.register_constantcolor1[0]; |
| 2940 | combiner.register_color1[1] = combiner.final.register_constantcolor1[1]; |
| 2941 | combiner.register_color1[2] = combiner.final.register_constantcolor1[2]; |
| 2942 | combiner.register_color1[3] = combiner.final.register_constantcolor1[3]; |
| 2943 | } |
| 2944 | |
| 2945 | void nv2a_renderer::combiner_map_input(int stage_number) |
| 2946 | { |
| 2947 | int n = stage_number; |
| 2948 | int c, d, i; |
| 2949 | float v, *pv; |
| 2950 | |
| 2951 | // A |
| 2952 | v = combiner_map_input_select(combiner.stage[n].mapin_aA_input, 2 + combiner.stage[n].mapin_aA_component); |
| 2953 | combiner.variable_A[3] = combiner_map_input_function(combiner.stage[n].mapin_aA_mapping, v); |
| 2954 | // B |
| 2955 | v = combiner_map_input_select(combiner.stage[n].mapin_aB_input, 2 + combiner.stage[n].mapin_aB_component); |
| 2956 | combiner.variable_B[3] = combiner_map_input_function(combiner.stage[n].mapin_aB_mapping, v); |
| 2957 | // C |
| 2958 | v = combiner_map_input_select(combiner.stage[n].mapin_aC_input, 2 + combiner.stage[n].mapin_aC_component); |
| 2959 | combiner.variable_C[3] = combiner_map_input_function(combiner.stage[n].mapin_aC_mapping, v); |
| 2960 | // D |
| 2961 | v = combiner_map_input_select(combiner.stage[n].mapin_aD_input, 2 + combiner.stage[n].mapin_aD_component); |
| 2962 | combiner.variable_D[3] = combiner_map_input_function(combiner.stage[n].mapin_aD_mapping, v); |
| 2963 | |
| 2964 | // A |
| 2965 | pv = combiner_map_input_select3(combiner.stage[n].mapin_rgbA_input); |
| 2966 | c = combiner.stage[n].mapin_rgbA_component * 3; |
| 2967 | i = ~combiner.stage[n].mapin_rgbA_component & 1; |
| 2968 | for (d = 0; d < 3; d++) { |
| 2969 | combiner.variable_A[d] = pv[c]; |
| 2970 | c = c + i; |
| 2971 | } |
| 2972 | combiner_map_input_function3(combiner.stage[n].mapin_rgbA_mapping, combiner.variable_A); |
| 2973 | // B |
| 2974 | pv = combiner_map_input_select3(combiner.stage[n].mapin_rgbB_input); |
| 2975 | c = combiner.stage[n].mapin_rgbB_component * 3; |
| 2976 | i = ~combiner.stage[n].mapin_rgbB_component & 1; |
| 2977 | for (d = 0; d < 3; d++) { |
| 2978 | combiner.variable_B[d] = pv[c]; |
| 2979 | c = c + i; |
| 2980 | } |
| 2981 | combiner_map_input_function3(combiner.stage[n].mapin_rgbB_mapping, combiner.variable_B); |
| 2982 | // C |
| 2983 | pv = combiner_map_input_select3(combiner.stage[n].mapin_rgbC_input); |
| 2984 | c = combiner.stage[n].mapin_rgbC_component * 3; |
| 2985 | i = ~combiner.stage[n].mapin_rgbC_component & 1; |
| 2986 | for (d = 0; d < 3; d++) { |
| 2987 | combiner.variable_C[d] = pv[c]; |
| 2988 | c = c + i; |
| 2989 | } |
| 2990 | combiner_map_input_function3(combiner.stage[n].mapin_rgbC_mapping, combiner.variable_C); |
| 2991 | // D |
| 2992 | pv = combiner_map_input_select3(combiner.stage[n].mapin_rgbD_input); |
| 2993 | c = combiner.stage[n].mapin_rgbD_component * 3; |
| 2994 | i = ~combiner.stage[n].mapin_rgbD_component & 1; |
| 2995 | for (d = 0; d < 3; d++) { |
| 2996 | combiner.variable_D[d] = pv[c]; |
| 2997 | c = c + i; |
| 2998 | } |
| 2999 | combiner_map_input_function3(combiner.stage[n].mapin_rgbD_mapping, combiner.variable_D); |
| 3000 | } |
| 3001 | |
| 3002 | void nv2a_renderer::combiner_map_output(int stage_number) |
| 3003 | { |
| 3004 | int n = stage_number; |
| 3005 | float *f; |
| 3006 | |
| 3007 | // rgb |
| 3008 | f = combiner_map_output_select3(combiner.stage[n].mapout_rgbAB_output); |
| 3009 | if (f) { |
| 3010 | f[0] = combiner.function_RGBop1[0]; |
| 3011 | f[1] = combiner.function_RGBop1[1]; |
| 3012 | f[2] = combiner.function_RGBop1[2]; |
| 3013 | } |
| 3014 | f = combiner_map_output_select3(combiner.stage[n].mapout_rgbCD_output); |
| 3015 | if (f) { |
| 3016 | f[0] = combiner.function_RGBop2[0]; |
| 3017 | f[1] = combiner.function_RGBop2[1]; |
| 3018 | f[2] = combiner.function_RGBop2[2]; |
| 3019 | } |
| 3020 | if ((combiner.stage[n].mapout_rgbAB_dotproduct | combiner.stage[n].mapout_rgbCD_dotproduct) == 0) { |
| 3021 | f = combiner_map_output_select3(combiner.stage[n].mapout_rgbSUM_output); |
| 3022 | if (f) { |
| 3023 | f[0] = combiner.function_RGBop3[0]; |
| 3024 | f[1] = combiner.function_RGBop3[1]; |
| 3025 | f[2] = combiner.function_RGBop3[2]; |
| 3026 | } |
| 3027 | } |
| 3028 | // a |
| 3029 | f = combiner_map_output_select3(combiner.stage[n].mapout_aAB_output); |
| 3030 | if (f) |
| 3031 | f[3] = combiner.function_Aop1; |
| 3032 | f = combiner_map_output_select3(combiner.stage[n].mapout_aCD_output); |
| 3033 | if (f) |
| 3034 | f[3] = combiner.function_Aop2; |
| 3035 | f = combiner_map_output_select3(combiner.stage[n].mapout_aSUM_output); |
| 3036 | if (f) |
| 3037 | f[3] = combiner.function_Aop3; |
| 3038 | } |
| 3039 | |
| 3040 | void nv2a_renderer::combiner_map_final_input() |
| 3041 | { |
| 3042 | int i, c, d; |
| 3043 | float *pv; |
| 3044 | |
| 3045 | // E |
| 3046 | pv = combiner_map_input_select3(combiner.final.mapin_rgbE_input); |
| 3047 | c = combiner.final.mapin_rgbE_component * 3; |
| 3048 | i = ~combiner.final.mapin_rgbE_component & 1; |
| 3049 | for (d = 0; d < 3; d++) { |
| 3050 | combiner.variable_E[d] = pv[c]; |
| 3051 | c = c + i; |
| 3052 | } |
| 3053 | combiner_map_input_function3(combiner.final.mapin_rgbE_mapping, combiner.variable_E); |
| 3054 | // F |
| 3055 | pv = combiner_map_input_select3(combiner.final.mapin_rgbF_input); |
| 3056 | c = combiner.final.mapin_rgbF_component * 3; |
| 3057 | i = ~combiner.final.mapin_rgbF_component & 1; |
| 3058 | for (d = 0; d < 3; d++) { |
| 3059 | combiner.variable_F[d] = pv[c]; |
| 3060 | c = c + i; |
| 3061 | } |
| 3062 | combiner_map_input_function3(combiner.final.mapin_rgbF_mapping, combiner.variable_F); |
| 3063 | // EF |
| 3064 | combiner.variable_EF[0] = combiner.variable_E[0] * combiner.variable_F[0]; |
| 3065 | combiner.variable_EF[1] = combiner.variable_E[1] * combiner.variable_F[1]; |
| 3066 | combiner.variable_EF[2] = combiner.variable_E[2] * combiner.variable_F[2]; |
| 3067 | // sumclamp |
| 3068 | combiner.variable_sumclamp[0] = MAX(0, combiner.register_spare0[0]) + MAX(0, combiner.register_secondarycolor[0]); |
| 3069 | combiner.variable_sumclamp[1] = MAX(0, combiner.register_spare0[1]) + MAX(0, combiner.register_secondarycolor[1]); |
| 3070 | combiner.variable_sumclamp[2] = MAX(0, combiner.register_spare0[2]) + MAX(0, combiner.register_secondarycolor[2]); |
| 3071 | if (combiner.final.color_sum_clamp != 0) { |
| 3072 | combiner.variable_sumclamp[0] = MIN(combiner.variable_sumclamp[0], 1.0); |
| 3073 | combiner.variable_sumclamp[1] = MIN(combiner.variable_sumclamp[1], 1.0); |
| 3074 | combiner.variable_sumclamp[2] = MIN(combiner.variable_sumclamp[2], 1.0); |
| 3075 | } |
| 3076 | // A |
| 3077 | pv = combiner_map_input_select3(combiner.final.mapin_rgbA_input); |
| 3078 | c = combiner.final.mapin_rgbA_component * 3; |
| 3079 | i = ~combiner.final.mapin_rgbA_component & 1; |
| 3080 | for (d = 0; d < 3; d++) { |
| 3081 | combiner.variable_A[d] = pv[c]; |
| 3082 | c = c + i; |
| 3083 | } |
| 3084 | combiner_map_input_function3(combiner.final.mapin_rgbA_mapping, combiner.variable_A); |
| 3085 | // B |
| 3086 | pv = combiner_map_input_select3(combiner.final.mapin_rgbB_input); |
| 3087 | c = combiner.final.mapin_rgbB_component * 3; |
| 3088 | i = ~combiner.final.mapin_rgbB_component & 1; |
| 3089 | for (d = 0; d < 3; d++) { |
| 3090 | combiner.variable_B[d] = pv[c]; |
| 3091 | c = c + i; |
| 3092 | } |
| 3093 | combiner_map_input_function3(combiner.final.mapin_rgbB_mapping, combiner.variable_B); |
| 3094 | // C |
| 3095 | pv = combiner_map_input_select3(combiner.final.mapin_rgbC_input); |
| 3096 | c = combiner.final.mapin_rgbC_component * 3; |
| 3097 | i = ~combiner.final.mapin_rgbC_component & 1; |
| 3098 | for (d = 0; d < 3; d++) { |
| 3099 | combiner.variable_C[d] = pv[c]; |
| 3100 | c = c + i; |
| 3101 | } |
| 3102 | combiner_map_input_function3(combiner.final.mapin_rgbC_mapping, combiner.variable_C); |
| 3103 | // D |
| 3104 | pv = combiner_map_input_select3(combiner.final.mapin_rgbD_input); |
| 3105 | c = combiner.final.mapin_rgbD_component * 3; |
| 3106 | i = ~combiner.final.mapin_rgbD_component & 1; |
| 3107 | for (d = 0; d < 3; d++) { |
| 3108 | combiner.variable_D[d] = pv[c]; |
| 3109 | c = c + i; |
| 3110 | } |
| 3111 | combiner_map_input_function3(combiner.final.mapin_rgbD_mapping, combiner.variable_D); |
| 3112 | // G |
| 3113 | combiner.variable_G = combiner_map_input_select(combiner.final.mapin_aG_input, 2 + combiner.final.mapin_aG_component); |
| 3114 | } |
| 3115 | |
| 3116 | void nv2a_renderer::combiner_final_output() |
| 3117 | { |
| 3118 | // rgb |
| 3119 | combiner.output[0] = combiner.variable_A[0] * combiner.variable_B[0] + (1.0 - combiner.variable_A[0])*combiner.variable_C[0] + combiner.variable_D[0]; |
| 3120 | combiner.output[1] = combiner.variable_A[1] * combiner.variable_B[1] + (1.0 - combiner.variable_A[1])*combiner.variable_C[1] + combiner.variable_D[1]; |
| 3121 | combiner.output[2] = combiner.variable_A[2] * combiner.variable_B[2] + (1.0 - combiner.variable_A[2])*combiner.variable_C[2] + combiner.variable_D[2]; |
| 3122 | combiner.output[0] = MIN(combiner.output[0], 1.0); |
| 3123 | combiner.output[1] = MIN(combiner.output[1], 1.0); |
| 3124 | combiner.output[2] = MIN(combiner.output[2], 1.0); |
| 3125 | // a |
| 3126 | combiner.output[3] = combiner_map_input_function(combiner.final.mapin_aG_mapping, combiner.variable_G); |
| 3127 | } |
| 3128 | |
| 3129 | void nv2a_renderer::combiner_function_AB(float result[4]) |
| 3130 | { |
| 3131 | result[0] = combiner.variable_A[0] * combiner.variable_B[0]; |
| 3132 | result[1] = combiner.variable_A[1] * combiner.variable_B[1]; |
| 3133 | result[2] = combiner.variable_A[2] * combiner.variable_B[2]; |
| 3134 | } |
| 3135 | |
| 3136 | void nv2a_renderer::combiner_function_AdotB(float result[4]) |
| 3137 | { |
| 3138 | result[0] = combiner.variable_A[0] * combiner.variable_B[0] + combiner.variable_A[1] * combiner.variable_B[1] + combiner.variable_A[2] * combiner.variable_B[2]; |
| 3139 | result[1] = result[0]; |
| 3140 | result[2] = result[0]; |
| 3141 | } |
| 3142 | |
| 3143 | void nv2a_renderer::combiner_function_CD(float result[4]) |
| 3144 | { |
| 3145 | result[0] = combiner.variable_C[0] * combiner.variable_D[0]; |
| 3146 | result[1] = combiner.variable_C[1] * combiner.variable_D[1]; |
| 3147 | result[2] = combiner.variable_C[2] * combiner.variable_D[2]; |
| 3148 | } |
| 3149 | |
| 3150 | void nv2a_renderer::combiner_function_CdotD(float result[4]) |
| 3151 | { |
| 3152 | result[0] = combiner.variable_C[0] * combiner.variable_D[0] + combiner.variable_C[1] * combiner.variable_D[1] + combiner.variable_C[2] * combiner.variable_D[2]; |
| 3153 | result[1] = result[0]; |
| 3154 | result[2] = result[0]; |
| 3155 | } |
| 3156 | |
| 3157 | void nv2a_renderer::combiner_function_ABmuxCD(float result[4]) |
| 3158 | { |
| 3159 | if (combiner.register_spare0[3] >= 0.5) |
| 3160 | combiner_function_AB(result); |
| 3161 | else |
| 3162 | combiner_function_CD(result); |
| 3163 | } |
| 3164 | |
| 3165 | void nv2a_renderer::combiner_function_ABsumCD(float result[4]) |
| 3166 | { |
| 3167 | result[0] = combiner.variable_A[0] * combiner.variable_B[0] + combiner.variable_C[0] * combiner.variable_D[0]; |
| 3168 | result[1] = combiner.variable_A[1] * combiner.variable_B[1] + combiner.variable_C[1] * combiner.variable_D[1]; |
| 3169 | result[2] = combiner.variable_A[2] * combiner.variable_B[2] + combiner.variable_C[2] * combiner.variable_D[2]; |
| 3170 | } |
| 3171 | |
| 3172 | void nv2a_renderer::combiner_compute_rgb_outputs(int stage_number) |
| 3173 | { |
| 3174 | int n = stage_number; |
| 3175 | int m; |
| 3176 | float biasrgb, scalergb; |
| 3177 | |
| 3178 | if (combiner.stage[n].mapout_rgb_bias) |
| 3179 | biasrgb = -0.5; |
| 3180 | else |
| 3181 | biasrgb = 0; |
| 3182 | switch (combiner.stage[n].mapout_rgb_scale) { |
| 3183 | case 0: |
| 3184 | default: |
| 3185 | scalergb = 1.0; |
| 3186 | break; |
| 3187 | case 1: |
| 3188 | scalergb = 2.0; |
| 3189 | break; |
| 3190 | case 2: |
| 3191 | scalergb = 4.0; |
| 3192 | break; |
| 3193 | case 3: |
| 3194 | scalergb = 0.5; |
| 3195 | break; |
| 3196 | } |
| 3197 | if (combiner.stage[n].mapout_rgbAB_dotproduct) { |
| 3198 | m = 1; |
| 3199 | combiner_function_AdotB(combiner.function_RGBop1); |
| 3200 | } |
| 3201 | else { |
| 3202 | m = 0; |
| 3203 | combiner_function_AB(combiner.function_RGBop1); |
| 3204 | } |
| 3205 | combiner.function_RGBop1[0] = MAX(MIN((combiner.function_RGBop1[0] + biasrgb) * scalergb, 1.0), -1.0); |
| 3206 | combiner.function_RGBop1[1] = MAX(MIN((combiner.function_RGBop1[1] + biasrgb) * scalergb, 1.0), -1.0); |
| 3207 | combiner.function_RGBop1[2] = MAX(MIN((combiner.function_RGBop1[2] + biasrgb) * scalergb, 1.0), -1.0); |
| 3208 | if (combiner.stage[n].mapout_rgbCD_dotproduct) { |
| 3209 | m = m | 1; |
| 3210 | combiner_function_CdotD(combiner.function_RGBop2); |
| 3211 | } |
| 3212 | else |
| 3213 | combiner_function_CD(combiner.function_RGBop2); |
| 3214 | combiner.function_RGBop2[0] = MAX(MIN((combiner.function_RGBop2[0] + biasrgb) * scalergb, 1.0), -1.0); |
| 3215 | combiner.function_RGBop2[1] = MAX(MIN((combiner.function_RGBop2[1] + biasrgb) * scalergb, 1.0), -1.0); |
| 3216 | combiner.function_RGBop2[2] = MAX(MIN((combiner.function_RGBop2[2] + biasrgb) * scalergb, 1.0), -1.0); |
| 3217 | if (m == 0) { |
| 3218 | if (combiner.stage[n].mapout_rgb_muxsum) |
| 3219 | combiner_function_ABmuxCD(combiner.function_RGBop3); |
| 3220 | else |
| 3221 | combiner_function_ABsumCD(combiner.function_RGBop3); |
| 3222 | combiner.function_RGBop3[0] = MAX(MIN((combiner.function_RGBop3[0] + biasrgb) * scalergb, 1.0), -1.0); |
| 3223 | combiner.function_RGBop3[1] = MAX(MIN((combiner.function_RGBop3[1] + biasrgb) * scalergb, 1.0), -1.0); |
| 3224 | combiner.function_RGBop3[2] = MAX(MIN((combiner.function_RGBop3[2] + biasrgb) * scalergb, 1.0), -1.0); |
| 3225 | } |
| 3226 | } |
| 3227 | |
| 3228 | void nv2a_renderer::combiner_compute_a_outputs(int stage_number) |
| 3229 | { |
| 3230 | int n = stage_number; |
| 3231 | float biasa, scalea; |
| 3232 | |
| 3233 | if (combiner.stage[n].mapout_a_bias) |
| 3234 | biasa = -0.5; |
| 3235 | else |
| 3236 | biasa = 0; |
| 3237 | switch (combiner.stage[n].mapout_a_scale) { |
| 3238 | case 0: |
| 3239 | default: |
| 3240 | scalea = 1.0; |
| 3241 | break; |
| 3242 | case 1: |
| 3243 | scalea = 2.0; |
| 3244 | break; |
| 3245 | case 2: |
| 3246 | scalea = 4.0; |
| 3247 | break; |
| 3248 | case 3: |
| 3249 | scalea = 0.5; |
| 3250 | break; |
| 3251 | } |
| 3252 | combiner.function_Aop1 = combiner.variable_A[3] * combiner.variable_B[3]; |
| 3253 | combiner.function_Aop1 = MAX(MIN((combiner.function_Aop1 + biasa) * scalea, 1.0), -1.0); |
| 3254 | combiner.function_Aop2 = combiner.variable_C[3] * combiner.variable_D[3]; |
| 3255 | combiner.function_Aop2 = MAX(MIN((combiner.function_Aop2 + biasa) * scalea, 1.0), -1.0); |
| 3256 | if (combiner.stage[n].mapout_a_muxsum) { |
| 3257 | if (combiner.register_spare0[3] >= 0.5) |
| 3258 | combiner.function_Aop3 = combiner.variable_A[3] * combiner.variable_B[3]; |
| 3259 | else |
| 3260 | combiner.function_Aop3 = combiner.variable_C[3] * combiner.variable_D[3]; |
| 3261 | } |
| 3262 | else |
| 3263 | combiner.function_Aop3 = combiner.variable_A[3] * combiner.variable_B[3] + combiner.variable_C[3] * combiner.variable_D[3]; |
| 3264 | combiner.function_Aop3 = MAX(MIN((combiner.function_Aop3 + biasa) * scalea, 1.0), -1.0); |
| 3265 | } |
| 3266 | |
| 3267 | bool nv2a_renderer::vblank_callback(screen_device &screen, bool state) |
| 3268 | { |
| 3269 | //printf("vblank_callback\n\r"); |
| 3270 | if (state == true) |
| 3271 | pcrtc[0x100 / 4] |= 1; |
| 3272 | else |
| 3273 | pcrtc[0x100 / 4] &= ~1; |
| 3274 | if (pcrtc[0x100 / 4] & pcrtc[0x140 / 4]) |
| 3275 | pmc[0x100 / 4] |= 0x1000000; |
| 3276 | else |
| 3277 | pmc[0x100 / 4] &= ~0x1000000; |
| 3278 | if ((pmc[0x100 / 4] != 0) && (pmc[0x140 / 4] != 0)) { |
| 3279 | // send interrupt |
| 3280 | return true; |
| 3281 | } |
| 3282 | else |
| 3283 | return false; |
| 3284 | } |
| 3285 | |
| 3286 | UINT32 nv2a_renderer::screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 3287 | { |
| 3288 | UINT32 *dst = (UINT32 *)bitmap.raw_pixptr(0, 0); |
| 3289 | UINT32 *src = (UINT32 *)fb.raw_pixptr(0, 0); |
| 3290 | |
| 3291 | //printf("updatescreen\n\r"); |
| 3292 | memcpy(dst, src, bitmap.rowbytes()*bitmap.height()); |
| 3293 | return 0; |
| 3294 | } |
| 3295 | |
| 3296 | READ32_MEMBER(nv2a_renderer::geforce_r) |
| 3297 | { |
| 3298 | static int x, ret; |
| 3299 | |
| 3300 | ret = 0; |
| 3301 | if (offset == 0x1804f6) { |
| 3302 | x = x ^ 0x08080808; |
| 3303 | ret = x; |
| 3304 | } |
| 3305 | if ((offset >= 0x00101000 / 4) && (offset < 0x00102000 / 4)) { |
| 3306 | //logerror("NV_2A: read STRAPS[%06X] mask %08X value %08X\n",offset*4-0x00101000,mem_mask,ret); |
| 3307 | } |
| 3308 | else if ((offset >= 0x00002000 / 4) && (offset < 0x00004000 / 4)) { |
| 3309 | ret = pfifo[offset - 0x00002000 / 4]; |
| 3310 | // PFIFO.CACHE1.STATUS or PFIFO.RUNOUT_STATUS |
| 3311 | if ((offset == 0x3214 / 4) || (offset == 0x2400 / 4)) |
| 3312 | ret = 0x10; |
| 3313 | //logerror("NV_2A: read PFIFO[%06X] value %08X\n",offset*4-0x00002000,ret); |
| 3314 | } |
| 3315 | else if ((offset >= 0x00700000 / 4) && (offset < 0x00800000 / 4)) { |
| 3316 | ret = ramin[offset - 0x00700000 / 4]; |
| 3317 | //logerror("NV_2A: read PRAMIN[%06X] value %08X\n",offset*4-0x00700000,ret); |
| 3318 | } |
| 3319 | else if ((offset >= 0x00400000 / 4) && (offset < 0x00402000 / 4)) { |
| 3320 | //logerror("NV_2A: read PGRAPH[%06X] value %08X\n",offset*4-0x00400000,ret); |
| 3321 | } |
| 3322 | else if ((offset >= 0x00600000 / 4) && (offset < 0x00601000 / 4)) { |
| 3323 | ret = pcrtc[offset - 0x00600000 / 4]; |
| 3324 | //logerror("NV_2A: read PCRTC[%06X] value %08X\n",offset*4-0x00600000,ret); |
| 3325 | } |
| 3326 | else if ((offset >= 0x00000000 / 4) && (offset < 0x00001000 / 4)) { |
| 3327 | ret = pmc[offset - 0x00000000 / 4]; |
| 3328 | //logerror("NV_2A: read PMC[%06X] value %08X\n",offset*4-0x00000000,ret); |
| 3329 | } |
| 3330 | else if ((offset >= 0x00800000 / 4) && (offset < 0x00900000 / 4)) { |
| 3331 | // 32 channels size 0x10000 each, 8 subchannels per channel size 0x2000 each |
| 3332 | int chanel, subchannel, suboffset; |
| 3333 | |
| 3334 | suboffset = offset - 0x00800000 / 4; |
| 3335 | chanel = (suboffset >> (16 - 2)) & 31; |
| 3336 | subchannel = (suboffset >> (13 - 2)) & 7; |
| 3337 | suboffset = suboffset & 0x7ff; |
| 3338 | if (suboffset < 0x80 / 4) |
| 3339 | ret = channel[chanel][subchannel].regs[suboffset]; |
| 3340 | //logerror("NV_2A: read channel[%02X,%d,%04X]=%08X\n",chanel,subchannel,suboffset*4,ret); |
| 3341 | return ret; |
| 3342 | } |
| 3343 | else; |
| 3344 | //logerror("NV_2A: read at %08X mask %08X value %08X\n",0xfd000000+offset*4,mem_mask,ret); |
| 3345 | return ret; |
| 3346 | } |
| 3347 | |
| 3348 | WRITE32_MEMBER(nv2a_renderer::geforce_w) |
| 3349 | { |
| 3350 | if ((offset >= 0x00101000 / 4) && (offset < 0x00102000 / 4)) { |
| 3351 | //logerror("NV_2A: write STRAPS[%06X] mask %08X value %08X\n",offset*4-0x00101000,mem_mask,data); |
| 3352 | } |
| 3353 | else if ((offset >= 0x00002000 / 4) && (offset < 0x00004000 / 4)) { |
| 3354 | int e = offset - 0x00002000 / 4; |
| 3355 | if (e >= (sizeof(pfifo) / sizeof(UINT32))) |
| 3356 | return; |
| 3357 | COMBINE_DATA(pfifo + e); |
| 3358 | //logerror("NV_2A: read PFIFO[%06X]=%08X\n",offset*4-0x00002000,data & mem_mask); // 2210 pfifo ramht & 1f0 << 12 |
| 3359 | } |
| 3360 | else if ((offset >= 0x00700000 / 4) && (offset < 0x00800000 / 4)) { |
| 3361 | int e = offset - 0x00700000 / 4; |
| 3362 | if (e >= (sizeof(ramin) / sizeof(UINT32))) |
| 3363 | return; |
| 3364 | COMBINE_DATA(ramin + e); |
| 3365 | //logerror("NV_2A: write PRAMIN[%06X]=%08X\n",offset*4-0x00700000,data & mem_mask); |
| 3366 | } |
| 3367 | else if ((offset >= 0x00400000 / 4) && (offset < 0x00402000 / 4)) { |
| 3368 | //logerror("NV_2A: write PGRAPH[%06X]=%08X\n",offset*4-0x00400000,data & mem_mask); |
| 3369 | } |
| 3370 | else if ((offset >= 0x00600000 / 4) && (offset < 0x00601000 / 4)) { |
| 3371 | int e = offset - 0x00600000 / 4; |
| 3372 | if (e >= (sizeof(pcrtc) / sizeof(UINT32))) |
| 3373 | return; |
| 3374 | COMBINE_DATA(pcrtc + e); |
| 3375 | //logerror("NV_2A: write PCRTC[%06X]=%08X\n",offset*4-0x00600000,data & mem_mask); |
| 3376 | } |
| 3377 | else if ((offset >= 0x00000000 / 4) && (offset < 0x00001000 / 4)) { |
| 3378 | int e = offset - 0x00000000 / 4; |
| 3379 | if (e >= (sizeof(pmc) / sizeof(UINT32))) |
| 3380 | return; |
| 3381 | COMBINE_DATA(pmc + e); |
| 3382 | //logerror("NV_2A: write PMC[%06X]=%08X\n",offset*4-0x00000000,data & mem_mask); |
| 3383 | } |
| 3384 | else if ((offset >= 0x00800000 / 4) && (offset < 0x00900000 / 4)) { |
| 3385 | // 32 channels size 0x10000 each, 8 subchannels per channel size 0x2000 each |
| 3386 | int chanel, subchannel, suboffset; |
| 3387 | int method, count, handle, objclass; |
| 3388 | #ifdef LOG_NV2A |
| 3389 | int subch; |
| 3390 | #endif |
| 3391 | |
| 3392 | suboffset = offset - 0x00800000 / 4; |
| 3393 | chanel = (suboffset >> (16 - 2)) & 31; |
| 3394 | subchannel = (suboffset >> (13 - 2)) & 7; |
| 3395 | suboffset = suboffset & 0x7ff; |
| 3396 | //logerror("NV_2A: write channel[%02X,%d,%04X]=%08X\n",chanel,subchannel,suboffset*4,data & mem_mask); |
| 3397 | if (suboffset >= 0x80 / 4) |
| 3398 | return; |
| 3399 | COMBINE_DATA(&channel[chanel][subchannel].regs[suboffset]); |
| 3400 | if ((suboffset == 0x40 / 4) || (suboffset == 0x44 / 4)) { // DMA_PUT or DMA_GET |
| 3401 | UINT32 *dmaput, *dmaget; |
| 3402 | UINT32 cmd, cmdtype; |
| 3403 | int countlen; |
| 3404 | |
| 3405 | dmaput = &channel[chanel][subchannel].regs[0x40 / 4]; |
| 3406 | dmaget = &channel[chanel][subchannel].regs[0x44 / 4]; |
| 3407 | //printf("dmaget %08X dmaput %08X\n\r",*dmaget,*dmaput); |
| 3408 | if ((*dmaput == 0x048cf000) && (*dmaget == 0x07f4d000)) |
| 3409 | *dmaget = *dmaput; |
| 3410 | while (*dmaget != *dmaput) { |
| 3411 | cmd = space.read_dword(*dmaget); |
| 3412 | *dmaget += 4; |
| 3413 | cmdtype = geforce_commandkind(cmd); |
| 3414 | switch (cmdtype) |
| 3415 | { |
| 3416 | case 6: // jump |
| 3417 | #ifdef LOG_NV2A |
| 3418 | printf("jump dmaget %08X", *dmaget); |
| 3419 | #endif |
| 3420 | *dmaget = cmd & 0xfffffffc; |
| 3421 | #ifdef LOG_NV2A |
| 3422 | printf(" -> %08X\n\r", *dmaget); |
| 3423 | #endif |
| 3424 | break; |
| 3425 | case 0: // increasing method |
| 3426 | method = (cmd >> 2) & 2047; // method*4 is address // if method >= 0x40 send it to assigned object |
| 3427 | #ifdef LOG_NV2A |
| 3428 | subch = (cmd >> 13) & 7; |
| 3429 | #endif |
| 3430 | count = (cmd >> 18) & 2047; |
| 3431 | if ((method == 0) && (count == 1)) { |
| 3432 | handle = space.read_dword(*dmaget); |
| 3433 | handle = geforce_object_offset(handle); |
| 3434 | #ifdef LOG_NV2A |
| 3435 | logerror(" assign to subchannel %d object at %d\n", subch, handle); |
| 3436 | #endif |
| 3437 | channel[chanel][subchannel].object.objhandle = handle; |
| 3438 | handle = ramin[handle / 4]; |
| 3439 | objclass = handle & 0xff; |
| 3440 | channel[chanel][subchannel].object.objclass = objclass; |
| 3441 | *dmaget += 4; |
| 3442 | } |
| 3443 | else { |
| 3444 | #ifdef LOG_NV2A |
| 3445 | logerror(" subch. %d method %04x offset %04x count %d\n", subch, method, method * 4, count); |
| 3446 | #endif |
| 3447 | while (count > 0) { |
| 3448 | countlen = 1; |
| 3449 | geforce_exec_method(space, chanel, subchannel, method, *dmaget, countlen); |
| 3450 | count--; |
| 3451 | method++; |
| 3452 | *dmaget += 4; |
| 3453 | } |
| 3454 | } |
| 3455 | break; |
| 3456 | case 5: // non-increasing method |
| 3457 | method = (cmd >> 2) & 2047; |
| 3458 | #ifdef LOG_NV2A |
| 3459 | subch = (cmd >> 13) & 7; |
| 3460 | #endif |
| 3461 | count = (cmd >> 18) & 2047; |
| 3462 | if ((method == 0) && (count == 1)) { |
| 3463 | #ifdef LOG_NV2A |
| 3464 | logerror(" assign channel %d\n", subch); |
| 3465 | #endif |
| 3466 | handle = space.read_dword(*dmaget); |
| 3467 | handle = geforce_object_offset(handle); |
| 3468 | #ifdef LOG_NV2A |
| 3469 | logerror(" assign to subchannel %d object at %d\n", subch, handle); |
| 3470 | #endif |
| 3471 | channel[chanel][subchannel].object.objhandle = handle; |
| 3472 | handle = ramin[handle / 4]; |
| 3473 | objclass = handle & 0xff; |
| 3474 | channel[chanel][subchannel].object.objclass = objclass; |
| 3475 | *dmaget += 4; |
| 3476 | } |
| 3477 | else { |
| 3478 | #ifdef LOG_NV2A |
| 3479 | logerror(" subch. %d method %04x offset %04x count %d\n", subch, method, method * 4, count); |
| 3480 | #endif |
| 3481 | while (count > 0) { |
| 3482 | countlen = count; |
| 3483 | geforce_exec_method(space, chanel, subchannel, method, *dmaget, countlen); |
| 3484 | *dmaget += 4 * (count - countlen); |
| 3485 | count = countlen; |
| 3486 | } |
| 3487 | } |
| 3488 | break; |
| 3489 | case 3: // long non-increasing method |
| 3490 | method = (cmd >> 2) & 2047; |
| 3491 | #ifdef LOG_NV2A |
| 3492 | subch = (cmd >> 13) & 7; |
| 3493 | #endif |
| 3494 | count = space.read_dword(*dmaget); |
| 3495 | *dmaget += 4; |
| 3496 | if ((method == 0) && (count == 1)) { |
| 3497 | handle = space.read_dword(*dmaget); |
| 3498 | handle = geforce_object_offset(handle); |
| 3499 | #ifdef LOG_NV2A |
| 3500 | logerror(" assign to subchannel %d object at %d\n", subch, handle); |
| 3501 | #endif |
| 3502 | channel[chanel][subchannel].object.objhandle = handle; |
| 3503 | handle = ramin[handle / 4]; |
| 3504 | objclass = handle & 0xff; |
| 3505 | channel[chanel][subchannel].object.objclass = objclass; |
| 3506 | *dmaget += 4; |
| 3507 | } |
| 3508 | else { |
| 3509 | #ifdef LOG_NV2A |
| 3510 | logerror(" subch. %d method %04x offset %04x count %d\n", subch, method, method * 4, count); |
| 3511 | #endif |
| 3512 | while (count > 0) { |
| 3513 | countlen = count; |
| 3514 | geforce_exec_method(space, chanel, subchannel, method, *dmaget, countlen); |
| 3515 | *dmaget += 4 * (count - countlen); |
| 3516 | count = countlen; |
| 3517 | } |
| 3518 | } |
| 3519 | break; |
| 3520 | default: |
| 3521 | logerror(" unimplemented command %08X\n", cmd); |
| 3522 | } |
| 3523 | } |
| 3524 | } |
| 3525 | } |
| 3526 | else; |
| 3527 | // logerror("NV_2A: write at %08X mask %08X value %08X\n",0xfd000000+offset*4,mem_mask,data); |
| 3528 | } |