Previous 199869 Revisions Next

r31237 Wednesday 9th July, 2014 at 01:19:20 UTC by R. Belmont
Chihiro WIP [Samuele Zannoli]
- Add NV2A vertex program disassembler
- Added two new debugger commands, grab_vprog <filename> to save the currently uploaded vertex program, and vprogdis <address, length>[<,type>] to disassemble a vertex program.
- Implemented alpha-test, blending, and logical per-fragment operations.  Improves many 2D displays in outr2.
[src/mame/drivers]chihiro.c

trunk/src/mame/drivers/chihiro.c
r31236r31237
374374#define LOG_PCI
375375//#define LOG_OHCI
376376//#define LOG_NV2A
377#define LOG_BASEBOARD
377//#define LOG_BASEBOARD
378378
379379class nv2a_renderer; // forw. dec.
380380struct nvidia_object_data
r31236r31237
415415   void dword_write_le(UINT8 *addr,UINT32 d);
416416   void word_write_le(UINT8 *addr,UINT16 d);
417417   void debug_generate_irq(int irq,bool active);
418   void debug_grab_texture(int type, char *filename);
419418
420419   void vblank_callback(screen_device &screen, bool state);
421420   UINT32 screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
r31236r31237
480479};
481480
482481/*
482 * geforce 3d (NV2A) vertex program disassembler
483 */
484class 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);
531public:
532   vertex_program_disassembler() { state = 0; }
533   int disassemble(unsigned int *instruction, char *line);
534};
535
536const char *vertex_program_disassembler::srctypes[] = { "??", "Rn", "Vn", "Cn" };
537const char *vertex_program_disassembler::scaops[] = { "NOP", "IMV", "RCP", "RCC", "RSQ", "EXP", "LOG", "LIT", "???", "???", "???", "???", "???", "???", "???", "???", "???" };
538const int vertex_program_disassembler::scapar2[] = { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
539const char *vertex_program_disassembler::vecops[] = { "NOP", "MOV", "MUL", "ADD", "MAD", "DP3", "DPH", "DP4", "DST", "MIN", "MAX", "SLT", "SGE", "ARL", "???", "???", "???" };
540const int vertex_program_disassembler::vecpar2[] = { 0, 4, 6, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 4, 0, 0, 0 };
541const char *vertex_program_disassembler::vecouts[] = { "oPos", "???", "???", "oD0", "oD1", "oFog", "oPts", "oB0", "oB1", "oT0", "oT1", "oT2", "oT3" };
542const char vertex_program_disassembler::compchar[] = { 'x', 'y', 'z', 'w' };
543
544/*
545Each vertex program instruction is a 128 bit word made of the fields:
546d         f
547w   b     i
548o   i     e
549r   t     l
550d   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+-+-----+-------
626Each vertex program instruction can generate up to three destination values using up to three source values.
627The first possible destination is to Rn from a vectorial operation.
628The second possible destination is to a vertex shader output or C[n] from a vectorial or scalar operation.
629The third possible destination is to Rn from a scalar operation.
630*/
631void 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
665int 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
694int 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
744int 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
797int 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
816int 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
834int 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/*
483960 * geforce 3d (NV2A) accellerator
484961 */
485962/* very simplified view
r31236r31237
498975objects have methods used to do drawing
499976most methods set parameters, others actually draw
500977*/
501class nv2a_renderer : public poly_manager<float, nvidia_object_data, 12, 6000>
978class nv2a_renderer : public poly_manager<float, nvidia_object_data, 12, 8192>
502979{
503980public:
504   nv2a_renderer(running_machine &machine) : poly_manager<float, nvidia_object_data, 12, 6000>(machine)
981   nv2a_renderer(running_machine &machine) : poly_manager<float, nvidia_object_data, 12, 8192>(machine)
505982   {
506983      memset(channel,0,sizeof(channel));
507984      memset(pfifo,0,sizeof(pfifo));
r31236r31237
516993      combiner.lock=osd_lock_alloc();
517994      enabled_vertex_attributes=0;
518995      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;
5191007      debug_grab_texttype = -1;
5201008      debug_grab_textfile = NULL;
521      memset(words_vertex_attributes, 0, sizeof(words_vertex_attributes));
1009      memset(vertex_attribute_words, 0, sizeof(vertex_attribute_words));
1010      memset(vertex_attribute_offset, 0, sizeof(vertex_attribute_offset));
5221011   }
5231012   DECLARE_READ32_MEMBER( geforce_r );
5241013   DECLARE_WRITE32_MEMBER( geforce_w );
r31236r31237
5341023   void geforce_read_dma_object(UINT32 handle,UINT32 &offset,UINT32 &size);
5351024   void geforce_exec_method(address_space &space,UINT32 channel,UINT32 subchannel,UINT32 method,UINT32 address,int &countlen);
5361025   UINT32 texture_get_texel(int number,int x,int y);
1026   void write_pixel(int x, int y, UINT32 color);
5371027   void combiner_initialize_registers(UINT32 argb8[6]);
5381028   void combiner_initialize_stage(int stage_number);
5391029   void combiner_initialize_final();
r31236r31237
5621052   void putpixtex(int xp,int yp,int up,int vp);
5631053   int toggle_register_combiners_usage();
5641054   void debug_grab_texture(int type, const char *filename);
1055   void debug_grab_vertex_program_slot(int slot, UINT32 *instruction);
5651056   void savestate_items();
5661057
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
5671069   struct {
5681070      UINT32 regs[0x80/4];
5691071      struct {
r31236r31237
5761078   UINT32 pcrtc[0x1000/4];
5771079   UINT32 pmc[0x1000/4];
5781080   UINT32 ramin[0x100000/4];
1081   UINT32 dma_offset[2];
1082   UINT32 dma_size[2];
1083   UINT32 vertexbuffer_address[16];
1084   int vertexbuffer_stride[16];
5791085   struct {
5801086      int enabled;
5811087      int sizeu;
r31236r31237
5881094   } texture[4];
5891095   int primitives_count;
5901096   int indexesleft_count;
1097   int indexesleft_first;
5911098   UINT32 indexesleft[8];
5921099   struct {
5931100      float variable_A[4]; // 0=R 1=G 2=B 3=A
r31236r31237
6921199      int used;
6931200      osd_lock *lock;
6941201   } 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;
6951212   struct {
6961213      float modelview[16];
6971214      float modelview_inverse[16];
r31236r31237
7031220      UINT32 instruction[1024];
7041221      int instructions;
7051222      int upload_instruction;
706      UINT32 parameter[1024];
1223      int start_instruction;
1224      float parameter[1024];
7071225      int upload_parameter;
7081226   } vertexprogram;
1227   int vertex_pipeline;
7091228   int enabled_vertex_attributes;
710   int words_vertex_attributes[16];
1229   int vertex_attribute_words[16];
1230   int vertex_attribute_offset[16];
7111231   bitmap_rgb32 fb;
7121232   UINT32 dilated0[16][2048];
7131233   UINT32 dilated1[16][2048];
r31236r31237
7801300      HILO8_RECT=0x46,
7811301      SIGNED_HILO8_RECT=0x47
7821302   };
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   };
7831365};
7841366
7851367/* jamtable instructions for Chihiro (different from console)
r31236r31237
11011683   chst->nvidia_nv2a->debug_grab_texture((int)type,param[1]);
11021684}
11031685
1686static void grab_vprog_command(running_machine &machine, int ref, int params, const char **param)
1687{
1688   chihiro_state *chst = machine.driver_data<chihiro_state>();
1689   UINT32 instruction[4];
1690   FILE *fil;
1691
1692   if (params < 1)
1693      return;
1694   if ((param[0][0] == 0) || (strlen(param[0]) > 127))
1695      return;
1696   if ((fil = fopen(param[0], "wb")) == NULL)
1697      return;
1698   for (int n = 0; n < 136; n++) {
1699      chst->nvidia_nv2a->debug_grab_vertex_program_slot(n, instruction);
1700      fwrite(instruction, sizeof(UINT32), 4, fil);
1701   }
1702   fclose(fil);
1703}
1704
1705static void vprogdis_command(running_machine &machine, int ref, int params, const char **param)
1706{
1707   UINT64 address, length, type;
1708   UINT32 instruction[4];
1709   offs_t addr;
1710   vertex_program_disassembler vd;
1711   char line[64];
1712   chihiro_state *chst = machine.driver_data<chihiro_state>();
1713   address_space &space = chst->m_maincpu->space();
1714
1715   if (params < 2)
1716      return;
1717   if (!debug_command_parameter_number(machine, param[0], &address))
1718      return;
1719   if (!debug_command_parameter_number(machine, param[1], &length))
1720      return;
1721   type = 0;
1722   if (params > 2)
1723      if (!debug_command_parameter_number(machine, param[2], &type))
1724         return;
1725   while (length > 0) {
1726      if (type == 1) {
1727         addr = (offs_t)address;
1728         if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &addr))
1729            return;
1730         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
1735         chst->nvidia_nv2a->debug_grab_vertex_program_slot((int)address, instruction);
1736      while (vd.disassemble(instruction, line) != 0)
1737         debug_console_printf(machine, "%s\n", line);
1738      if (type == 1)
1739         address = address + 4 * 4;
1740      else
1741         address++;
1742      length--;
1743   }
1744}
1745
11041746static void help_command(running_machine &machine, int ref, int params, const char **param)
11051747{
11061748   debug_console_printf(machine,"Available Chihiro commands:\n");
r31236r31237
11121754   debug_console_printf(machine,"  chihiro irq,<number> -- Generate interrupt with irq number 0-15\n");
11131755   debug_console_printf(machine,"  chihiro nv2a_combiners -- Toggle use of register combiners\n");
11141756   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");
11151759   debug_console_printf(machine,"  chihiro help -- this list\n");
11161760}
11171761
r31236r31237
11351779      nv2a_combiners_command(machine,ref,params-1,param+1);
11361780   else if (strcmp("grab_texture", param[0]) == 0)
11371781      grab_texture_command(machine, ref, params - 1, param + 1);
1782   else if (strcmp("grab_vprog", param[0]) == 0)
1783      grab_vprog_command(machine, ref, params - 1, param + 1);
1784   else if (strcmp("vprogdis", param[0]) == 0)
1785      vprogdis_command(machine, ref, params - 1, param + 1);
11381786   else
11391787      help_command(machine,ref,params-1,param+1);
11401788}
r31236r31237
12161864   UINT32 o=(pfifo[0x210/4] & 0x1f) << 8; // or 12 ?
12171865   UINT32 e=o+h*8; // at 0xfd000000+0x00700000
12181866   UINT32 w;
1867
12191868   if (ramin[e/4] != handle)
12201869      e=0;
12211870   w=ramin[e/4+1];
r31236r31237
12681917    }
12691918}*/
12701919
1271UINT32 convert_a4r4g4b4_a8r8g8b8(UINT32 a4r4g4b4)
1920inline UINT32 convert_a4r4g4b4_a8r8g8b8(UINT32 a4r4g4b4)
12721921{
12731922   UINT32 a8r8g8b8;
12741923   int ca,cr,cg,cb;
r31236r31237
12811930   return a8r8g8b8;
12821931}
12831932
1284UINT32 convert_a1r5g5b5_a8r8g8b8(UINT32 a1r5g5b5)
1933inline UINT32 convert_a1r5g5b5_a8r8g8b8(UINT32 a1r5g5b5)
12851934{
12861935   UINT32 a8r8g8b8;
12871936   int ca,cr,cg,cb;
r31236r31237
12941943   return a8r8g8b8;
12951944}
12961945
1297UINT32 convert_r5g6b5_r8g8b8(UINT32 r5g6b5)
1946inline UINT32 convert_r5g6b5_r8g8b8(UINT32 r5g6b5)
12981947{
12991948   UINT32 r8g8b8;
13001949   int cr,cg,cb;
r31236r31237
15172166   }
15182167}
15192168
2169void nv2a_renderer::write_pixel(int x, int y, UINT32 color)
2170{
2171   void *addr;
2172   UINT32 fbcolor;
2173   UINT32 c[4], fb[4], s[4], d[4], cc[4];
2174
2175   addr = this->fb.raw_pixptr(y, x);
2176   fbcolor = *((UINT32 *)addr);
2177   c[3] = color >> 24;
2178   c[2] = (color >> 16) & 255;
2179   c[1] = (color >> 8) & 255;
2180   c[0] = color & 255;
2181   fb[3] = fbcolor >> 24;
2182   fb[2] = (fbcolor >> 16) & 255;
2183   fb[1] = (fbcolor >> 8) & 255;
2184   fb[0] = fbcolor & 255;
2185   cc[3] = blend_color >> 24;
2186   cc[2] = (blend_color >> 16) & 255;
2187   cc[1] = (blend_color >> 8) & 255;
2188   cc[0] = blend_color & 255;
2189   // ownership test and scissor test not done
2190   // alpha test
2191   if (alpha_test_enabled) {
2192      switch (alpha_func) {
2193      case nv2a_renderer::NEVER:
2194         return;
2195         break;
2196      case nv2a_renderer::ALWAYS:
2197      default:
2198         break;
2199      case nv2a_renderer::LESS:
2200         if (c[3] >= alpha_reference)
2201            return;
2202         break;
2203      case nv2a_renderer::LEQUAL:
2204         if (c[3] > alpha_reference)
2205            return;
2206         break;
2207      case nv2a_renderer::EQUAL:
2208         if (c[3] != alpha_reference)
2209            return;
2210         break;
2211      case nv2a_renderer::GEQUAL:
2212         if (c[3] < alpha_reference)
2213            return;
2214         break;
2215      case nv2a_renderer::GREATER:
2216         if (c[3] <= alpha_reference)
2217            return;
2218         break;
2219      case nv2a_renderer::NOTEQUAL:
2220         if (c[3] == alpha_reference)
2221            return;
2222         break;
2223      }
2224   }
2225   // stencil test not done
2226   // depth buffer test not done
2227   // blending
2228   if (blending_enabled) {
2229      switch (blend_function_source) {
2230      case nv2a_renderer::ZERO:
2231         s[3] = s[2] = s[1] = s[0] = 0;
2232         break;
2233      case nv2a_renderer::ONE:
2234      default:
2235         s[3] = s[2] = s[1] = s[0] = 255;
2236         break;
2237      case nv2a_renderer::DST_COLOR:
2238         s[3] = fb[3];
2239         s[2] = fb[2];
2240         s[1] = fb[1];
2241         s[0] = fb[0];
2242         break;
2243      case nv2a_renderer::ONE_MINUS_DST_COLOR:
2244         s[3] = fb[3] ^ 255;
2245         s[2] = fb[2] ^ 255;
2246         s[1] = fb[1] ^ 255;
2247         s[0] = fb[0] ^ 255;
2248         break;
2249      case nv2a_renderer::SRC_ALPHA:
2250         s[3] = s[2] = s[1] = s[0] = c[3];
2251         break;
2252      case nv2a_renderer::ONE_MINUS_SRC_ALPHA:
2253         s[3] = s[2] = s[1] = s[0] = c[3] ^ 255;
2254         break;
2255      case nv2a_renderer::DST_ALPHA:
2256         s[3] = s[2] = s[1] = s[0] = fb[3];
2257         break;
2258      case nv2a_renderer::ONE_MINUS_DST_ALPHA:
2259         s[3] = s[2] = s[1] = s[0] = fb[3] ^ 255;
2260         break;
2261      case nv2a_renderer::CONSTANT_COLOR:
2262         s[3] = cc[3];
2263         s[2] = cc[2];
2264         s[1] = cc[1];
2265         s[0] = cc[0];
2266         break;
2267      case nv2a_renderer::ONE_MINUS_CONSTANT_COLOR:
2268         s[3] = cc[3] ^ 255;
2269         s[2] = cc[2] ^ 255;
2270         s[1] = cc[1] ^ 255;
2271         s[0] = cc[0] ^ 255;
2272         break;
2273      case nv2a_renderer::CONSTANT_ALPHA:
2274         s[3] = s[2] = s[1] = s[0] = cc[3];
2275         break;
2276      case nv2a_renderer::ONE_MINUS_CONSTANT_ALPHA:
2277         s[3] = s[2] = s[1] = s[0] = cc[3] ^ 255;
2278         break;
2279      case nv2a_renderer::SRC_ALPHA_SATURATE:
2280         s[3] = 255;
2281         if (c[3] < (fb[3] ^ 255))
2282            s[2] = c[3];
2283         else
2284            s[2] = fb[3];
2285         s[1] = s[0] = s[2];
2286         break;
2287      }
2288      switch (blend_function_destination) {
2289      case nv2a_renderer::ZERO:
2290      default:
2291         d[3] = d[2] = d[1] = d[0] = 0;
2292         break;
2293      case nv2a_renderer::ONE:
2294         d[3] = d[2] = d[1] = d[0] = 255;
2295         break;
2296      case nv2a_renderer::SRC_COLOR:
2297         d[3] = c[3];
2298         d[2] = c[2];
2299         d[1] = c[1];
2300         d[0] = c[0];
2301         break;
2302      case nv2a_renderer::ONE_MINUS_SRC_COLOR:
2303         d[3] = c[3] ^ 255;
2304         d[2] = c[2] ^ 255;
2305         d[1] = c[1] ^ 255;
2306         d[0] = c[0] ^ 255;
2307         break;
2308      case nv2a_renderer::SRC_ALPHA:
2309         d[3] = d[2] = d[1] = d[0] = c[3];
2310         break;
2311      case nv2a_renderer::ONE_MINUS_SRC_ALPHA:
2312         d[3] = d[2] = d[1] = d[0] = c[3] ^ 255;
2313         break;
2314      case nv2a_renderer::DST_ALPHA:
2315         d[3] = d[2] = d[1] = d[0] = fb[3];
2316         break;
2317      case nv2a_renderer::ONE_MINUS_DST_ALPHA:
2318         d[3] = d[2] = d[1] = d[0] = fb[3] ^ 255;
2319         break;
2320      case nv2a_renderer::CONSTANT_COLOR:
2321         d[3] = cc[3];
2322         d[2] = cc[2];
2323         d[1] = cc[1];
2324         d[0] = cc[0];
2325         break;
2326      case nv2a_renderer::ONE_MINUS_CONSTANT_COLOR:
2327         d[3] = cc[3] ^ 255;
2328         d[2] = cc[2] ^ 255;
2329         d[1] = cc[1] ^ 255;
2330         d[0] = cc[0] ^ 255;
2331         break;
2332      case nv2a_renderer::CONSTANT_ALPHA:
2333         d[3] = d[2] = d[1] = d[0] = cc[3];
2334         break;
2335      case nv2a_renderer::ONE_MINUS_CONSTANT_ALPHA:
2336         d[3] = d[2] = d[1] = d[0] = cc[3] ^ 255;
2337         break;
2338      }
2339      switch (blend_equation) {
2340      case nv2a_renderer::FUNC_ADD:
2341         c[3] = (c[3]*s[3] + fb[3]*d[3]) / 255;
2342         if (c[3] > 255)
2343            c[3] = 255;
2344         c[2] = (c[2]*s[2] + fb[2]*d[2]) / 255;
2345         if (c[2] > 255)
2346            c[2] = 255;
2347         c[1] = (c[1]*s[1] + fb[1]*d[1]) / 255;
2348         if (c[1] > 255)
2349            c[1] = 255;
2350         c[0] = (c[0]*s[0] + fb[0]*d[0]) / 255;
2351         if (c[0] > 255)
2352            c[0] = 255;
2353         break;
2354      case nv2a_renderer::FUNC_SUBTRACT:
2355         c[3] = (c[3]*s[3] - fb[3]*d[3]) / 255;
2356         if (c[3] < 0)
2357            c[3] = 255;
2358         c[2] = (c[2]*s[2] - fb[2]*d[2]) / 255;
2359         if (c[2] < 0)
2360            c[2] = 255;
2361         c[1] = (c[1]*s[1] - fb[1]*d[1]) / 255;
2362         if (c[1] < 0)
2363            c[1] = 255;
2364         c[0] = (c[0]*s[0] - fb[0]*d[0]) / 255;
2365         if (c[0] < 0)
2366            c[0] = 255;
2367         break;
2368      case nv2a_renderer::FUNC_REVERSE_SUBTRACT:
2369         c[3] = (fb[3] * d[3] - c[3] * s[3]) / 255;
2370         if (c[3] < 0)
2371            c[3] = 255;
2372         c[2] = (fb[2] * d[2] - c[2] * s[2]) / 255;
2373         if (c[2] < 0)
2374            c[2] = 255;
2375         c[1] = (fb[1] * d[1] - c[1] * s[1]) / 255;
2376         if (c[1] < 0)
2377            c[1] = 255;
2378         c[0] = (fb[0] * d[0] - c[0] * s[0]) / 255;
2379         if (c[0] < 0)
2380            c[0] = 255;
2381         break;
2382      case nv2a_renderer::MIN:
2383         c[3] = s[3];
2384         if (d[3] < c[3])
2385            c[3] = d[3];
2386         c[2] = s[2];
2387         if (d[2] < c[2])
2388            c[2] = d[2];
2389         c[1] = s[1];
2390         if (d[1] < c[1])
2391            c[1] = d[1];
2392         c[0] = s[0];
2393         if (d[0] < c[0])
2394            c[0] = d[0];
2395         break;
2396      case nv2a_renderer::MAX:
2397         c[3] = s[3];
2398         if (d[3] > c[3])
2399            c[3] = d[3];
2400         c[2] = s[2];
2401         if (d[2] > c[2])
2402            c[2] = d[2];
2403         c[1] = s[1];
2404         if (d[1] > c[1])
2405            c[1] = d[1];
2406         c[0] = s[0];
2407         if (d[0] > c[0])
2408            c[0] = d[0];
2409         break;
2410      }
2411   }
2412   // dithering not done
2413   // logical operation
2414   if (logical_operation_enabled) {
2415      switch (logical_operation) {
2416      case  nv2a_renderer::CLEAR:
2417         c[3] = 0;
2418         c[2] = 0;
2419         c[1] = 0;
2420         c[0] = 0;
2421         break;
2422      case  nv2a_renderer::AND:
2423         c[3] = c[3] & fb[3];
2424         c[2] = c[2] & fb[2];
2425         c[1] = c[1] & fb[1];
2426         c[0] = c[0] & fb[0];
2427         break;
2428      case  nv2a_renderer::AND_REVERSE:
2429         c[3] = c[3] & (fb[3] ^ 255);
2430         c[2] = c[2] & (fb[2] ^ 255);
2431         c[1] = c[1] & (fb[1] ^ 255);
2432         c[0] = c[0] & (fb[0] ^ 255);
2433         break;
2434      case  nv2a_renderer::COPY:
2435      default:
2436         break;
2437      case  nv2a_renderer::AND_INVERTED:
2438         c[3] = (c[3] ^ 255) & fb[3];
2439         c[2] = (c[2] ^ 255) & fb[2];
2440         c[1] = (c[1] ^ 255) & fb[1];
2441         c[0] = (c[0] ^ 255) & fb[0];
2442         break;
2443      case  nv2a_renderer::NOOP:
2444         c[3] = fb[3];
2445         c[2] = fb[2];
2446         c[1] = fb[1];
2447         c[0] = fb[0];
2448         break;
2449      case  nv2a_renderer::XOR:
2450         c[3] = c[3] ^ fb[3];
2451         c[2] = c[2] ^ fb[2];
2452         c[1] = c[1] ^ fb[1];
2453         c[0] = c[0] ^ fb[0];
2454         break;
2455      case  nv2a_renderer::OR:
2456         c[3] = c[3] | fb[3];
2457         c[2] = c[2] | fb[2];
2458         c[1] = c[1] | fb[1];
2459         c[0] = c[0] | fb[0];
2460         break;
2461      case  nv2a_renderer::NOR:
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::EQUIV:
2468         c[3] = (c[3] ^ fb[3]) ^ 255;
2469         c[2] = (c[2] ^ fb[2]) ^ 255;
2470         c[1] = (c[1] ^ fb[1]) ^ 255;
2471         c[0] = (c[0] ^ fb[0]) ^ 255;
2472         break;
2473      case  nv2a_renderer::INVERT:
2474         c[3] = fb[3] ^ 255;
2475         c[2] = fb[2] ^ 255;
2476         c[1] = fb[1] ^ 255;
2477         c[0] = fb[0] ^ 255;
2478         break;
2479      case  nv2a_renderer::OR_REVERSE:
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::COPY_INVERTED:
2486         c[3] = c[3] ^ 255;
2487         c[2] = c[2] ^ 255;
2488         c[1] = c[1] ^ 255;
2489         c[0] = c[0] ^ 255;
2490         break;
2491      case  nv2a_renderer::OR_INVERTED:
2492         c[3] = (c[3] ^ 255) | fb[3];
2493         c[2] = (c[2] ^ 255) | fb[2];
2494         c[1] = (c[1] ^ 255) | fb[1];
2495         c[0] = (c[0] ^ 255) | fb[0];
2496         break;
2497      case  nv2a_renderer::NAND:
2498         c[3] = (c[3] & fb[3]) ^ 255;
2499         c[2] = (c[2] & fb[2]) ^ 255;
2500         c[1] = (c[1] & fb[1]) ^ 255;
2501         c[0] = (c[0] & fb[0]) ^ 255;
2502         break;
2503      case  nv2a_renderer::SET:
2504         c[3] = 255;
2505         c[2] = 255;
2506         c[1] = 255;
2507         c[0] = 255;
2508         break;
2509      }
2510   }
2511   fbcolor = (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0];
2512   *((UINT32 *)addr) = fbcolor;
2513}
2514
15202515void nv2a_renderer::render_color(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid)
15212516{
15222517   int x;
r31236r31237
15322527      cr=(extent.param[2].start+(float)x*extent.param[2].dpdx);
15332528      ca=(extent.param[3].start+(float)x*extent.param[3].dpdx);
15342529      a8r8g8b8=(ca << 24)+(cr << 16)+(cg << 8)+cb; // pixel color obtained by interpolating the colors of the vertices
1535      *((UINT32 *)objectdata.data->fb.raw_pixptr(scanline,xp))=a8r8g8b8;
2530      write_pixel(xp, scanline, a8r8g8b8);
15362531      x--;
15372532   }
15382533}
r31236r31237
15402535void nv2a_renderer::render_texture_simple(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid)
15412536{
15422537   int x;
2538   UINT32 a8r8g8b8;
15432539
15442540   if (!objectdata.data->texture[0].enabled) {
15452541      return;
r31236r31237
15512547
15522548      up=(extent.param[4].start+(float)x*extent.param[4].dpdx)*(float)(objectdata.data->texture[0].sizeu-1); // x coordinate of texel in texture
15532549      vp=extent.param[5].start*(float)(objectdata.data->texture[0].sizev-1); // y coordinate of texel in texture
1554      *((UINT32 *)fb.raw_pixptr(scanline,xp))=texture_get_texel(0, up, vp);
2550      a8r8g8b8=texture_get_texel(0, up, vp);
2551      write_pixel(xp, scanline, a8r8g8b8);
15552552      x--;
15562553   }
15572554}
r31236r31237
16082605      combiner_final_output();
16092606      a8r8g8b8=combiner_float_argb8(combiner.output);
16102607      // 3: write pixel
1611      *((UINT32 *)objectdata.data->fb.raw_pixptr(scanline,xp))=a8r8g8b8;
2608      write_pixel(xp, scanline, a8r8g8b8);
16122609      x--;
16132610   }
16142611   osd_lock_release(combiner.lock);
r31236r31237
17542751}
17552752#endif
17562753
2754/* Read vertices data from system memory. Method 0x1810 */
2755int nv2a_renderer::read_vertices_0x1810(address_space & space, vertex *destination, int offset, int limit)
2756{
2757   UINT32 m, u;
2758
2759   for (m = 0; m < limit; m++) {
2760      destination[m].attribute[0].iv[0] = space.read_dword(vertexbuffer_address[0] + (m + offset)*vertexbuffer_stride[0] + 0);
2761      destination[m].attribute[0].iv[1] = space.read_dword(vertexbuffer_address[0] + (m + offset)*vertexbuffer_stride[0] + 4);
2762      destination[m].attribute[0].iv[2] = space.read_dword(vertexbuffer_address[0] + (m + offset)*vertexbuffer_stride[0] + 8);
2763      destination[m].attribute[0].iv[3] = space.read_dword(vertexbuffer_address[0] + (m + offset)*vertexbuffer_stride[0] + 12);
2764      destination[m].attribute[3].iv[0] = space.read_dword(vertexbuffer_address[3] + (m + offset)*vertexbuffer_stride[3] + 0); // color
2765      for (u = 0; u < 4; u++) {
2766         destination[m].attribute[9 + u].iv[0] = space.read_dword(vertexbuffer_address[9 + u] + (m + offset)*vertexbuffer_stride[9 + u] + 0);
2767         destination[m].attribute[9 + u].iv[1] = space.read_dword(vertexbuffer_address[9 + u] + (m + offset)*vertexbuffer_stride[9 + u] + 4);
2768      }
2769   }
2770   return m;
2771}
2772
2773/* Read vertices data from system memory. Method 0x1800 */
2774int nv2a_renderer::read_vertices_0x1800(address_space & space, vertex *destination, UINT32 address, int limit)
2775{
2776   UINT32 data;
2777   UINT32 m, u, i, c;
2778
2779   c = 0;
2780   for (m = 0; m < limit; m++) {
2781      if (indexesleft_count == 0) {
2782         data = space.read_dword(address);
2783         i = (indexesleft_first + indexesleft_count) & 7;
2784         indexesleft[i] = data & 0xffff;
2785         indexesleft[(i + 1) & 7] = (data >> 16) & 0xffff;
2786         indexesleft_count = indexesleft_count + 2;
2787         address += 4;
2788         c++;
2789      }
2790      destination[m].attribute[0].iv[0] = space.read_dword(vertexbuffer_address[0] + indexesleft[indexesleft_first] * vertexbuffer_stride[0] + 0);
2791      destination[m].attribute[0].iv[1] = space.read_dword(vertexbuffer_address[0] + indexesleft[indexesleft_first] * vertexbuffer_stride[0] + 4);
2792      destination[m].attribute[0].iv[2] = space.read_dword(vertexbuffer_address[0] + indexesleft[indexesleft_first] * vertexbuffer_stride[0] + 8);
2793      destination[m].attribute[0].iv[3] = space.read_dword(vertexbuffer_address[0] + indexesleft[indexesleft_first] * vertexbuffer_stride[0] + 12);
2794      destination[m].attribute[3].iv[0] = space.read_dword(vertexbuffer_address[3] + indexesleft[indexesleft_first] * vertexbuffer_stride[3] + 0); // color
2795      for (u = 0; u < 4; u++) {
2796         destination[m].attribute[9 + u].iv[0] = space.read_dword(vertexbuffer_address[9 + u] + indexesleft[indexesleft_first] * vertexbuffer_stride[9 + u] + 0);
2797         destination[m].attribute[9 + u].iv[1] = space.read_dword(vertexbuffer_address[9 + u] + indexesleft[indexesleft_first] * vertexbuffer_stride[9 + u] + 4);
2798      }
2799      indexesleft_first = (indexesleft_first + 1) & 7;
2800      indexesleft_count--;
2801   }
2802   return (int)c;
2803}
2804
2805/* Read vertices data from system memory. Method 0x1818 */
2806int nv2a_renderer::read_vertices_0x1818(address_space & space, vertex *destination, UINT32 address, int limit)
2807{
2808   UINT32 m, u, vwords;
2809
2810   vwords = vertex_attribute_words[15] + vertex_attribute_offset[15];
2811   for (m = 0; m < limit; m++) {
2812      destination[m].attribute[0].iv[0] = space.read_dword(address + vertex_attribute_offset[0] * 4 + 0);
2813      destination[m].attribute[0].iv[1] = space.read_dword(address + vertex_attribute_offset[0] * 4 + 4);
2814      destination[m].attribute[0].iv[2] = space.read_dword(address + vertex_attribute_offset[0] * 4 + 8);
2815      destination[m].attribute[0].iv[3] = space.read_dword(address + vertex_attribute_offset[0] * 4 + 12);
2816      destination[m].attribute[3].iv[0] = space.read_dword(address + vertex_attribute_offset[3] * 4 + 0); // color
2817      for (u = 0; u < 4; u++) {
2818         destination[m].attribute[9 + u].iv[0] = space.read_dword(address + vertex_attribute_offset[9 + u] * 4 + 0);
2819         destination[m].attribute[9 + u].iv[1] = space.read_dword(address + vertex_attribute_offset[9 + u] * 4 + 4);
2820      }
2821      address = address + vwords * 4;
2822   }
2823   return (int)(m*vwords);
2824}
2825
2826void nv2a_renderer::convert_vertices_poly(vertex *source, vertex_t *destination, int count)
2827{
2828   int m, u;
2829
2830   for (m = 0; m < count; m++) {
2831      destination[m].x = source[m].attribute[0].fv[0];
2832      destination[m].y = source[m].attribute[0].fv[1];
2833      u = source[m].attribute[3].iv[0];
2834      destination[m].p[0] = u & 0xff; // b
2835      destination[m].p[1] = (u & 0xff00) >> 8;  // g
2836      destination[m].p[2] = (u & 0xff0000) >> 16;  // r
2837      destination[m].p[3] = (u & 0xff000000) >> 24;  // a
2838      for (u = 0; u < 4; u++) {
2839         destination[m].p[4 + u * 2] = 0;
2840         destination[m].p[5 + u * 2] = 0;
2841         if (texture[u].enabled) {
2842            destination[m].p[4 + u * 2] = source[m].attribute[9 + u].fv[0];
2843            destination[m].p[5 + u * 2] = source[m].attribute[9 + u].fv[1];
2844         }
2845      }
2846   }
2847}
2848
17572849void nv2a_renderer::geforce_exec_method(address_space & space,UINT32 chanel,UINT32 subchannel,UINT32 method,UINT32 address,int &countlen)
17582850{
17592851   UINT32 maddress;
r31236r31237
17642856   channel[chanel][subchannel].object.method[method]=data;
17652857   if (maddress == 0x17fc) {
17662858      indexesleft_count = 0;
2859      indexesleft_first = 0;
17672860      primitives_count = 0;
17682861      countlen--;
17692862   }
17702863   if (maddress == 0x1810) {
17712864      // draw vertices
17722865      int offset,count,type;
1773      //int vtxbuf_kind[16],vtxbuf_size[16];
1774      int vtxbuf_stride[16];
1775      UINT32 vtxbuf_address[16];
1776      UINT32 dmahand[2],dmaoff[2],smasiz[2];
1777      UINT32 tmp,n,m,u;
2866      UINT32 n;
17782867      render_delegate renderspans;
17792868
17802869      offset=data & 0xffffff;
17812870      count=(data >> 24) & 0xff;
17822871      type=channel[chanel][subchannel].object.method[0x17fc/4];
1783      dmahand[0]=channel[chanel][subchannel].object.method[0x019c/4];
1784      dmahand[1]=channel[chanel][subchannel].object.method[0x01a0/4];
1785      geforce_read_dma_object(dmahand[0],dmaoff[0],smasiz[0]);
1786      geforce_read_dma_object(dmahand[1],dmaoff[1],smasiz[1]);
17872872      if (((channel[chanel][subchannel].object.method[0x1e60/4] & 7) > 0) && (combiner.used != 0)) {
17882873         renderspans=render_delegate(FUNC(nv2a_renderer::render_register_combiners),this);
17892874      } else if (texture[0].enabled) {
r31236r31237
17932878#ifdef LOG_NV2A
17942879      printf("vertex %d %d %d\n\r",type,offset,count);
17952880#endif
1796      for (n=0;n < 16;n++) {
1797#ifdef LOG_NV2A
1798         printf(" %08X %08X\n\r",channel[chanel][subchannel].object.method[0x1720/4+n],channel[chanel][subchannel].object.method[0x1760/4+n]);
1799#endif
1800         tmp=channel[chanel][subchannel].object.method[0x1760/4+n]; // VTXBUF_FMT
1801         //vtxbuf_kind[n]=tmp & 15;
1802         //vtxbuf_size[n]=(tmp >> 4) & 15;
1803         vtxbuf_stride[n]=(tmp >> 8) & 255;
1804         tmp=channel[chanel][subchannel].object.method[0x1720/4+n]; // VTXBUF_OFFSET
1805         if (tmp & 0x80000000)
1806            vtxbuf_address[n]=(tmp & 0x0fffffff)+dmaoff[1];
1807         else
1808            vtxbuf_address[n]=(tmp & 0x0fffffff)+dmaoff[0];
1809      }
18102881      if (type == nv2a_renderer::QUADS) {
1811#if 0
1812         n=0;
1813         if (n == 1)
1814            dumpcombiners(channel[chanel][subchannel].object.method);
1815#endif
1816         for (n=0;n <= count;n+=4) {
2882         for (n = 0; n <= count; n += 4) {
2883            vertex vert[4];
18172884            vertex_t xy[4];
1818            float z[4],w[4];
1819            UINT32 c[4];
18202885
1821            //printf("draw quad\n\r");
1822            for (m=0;m < 4;m++) {
1823               *((UINT32 *)(&xy[m].x))=space.read_dword(vtxbuf_address[0]+(n+m+offset)*vtxbuf_stride[0]+0);
1824               *((UINT32 *)(&xy[m].y))=space.read_dword(vtxbuf_address[0]+(n+m+offset)*vtxbuf_stride[0]+4);
1825               *((UINT32 *)(&z[m]))=space.read_dword(vtxbuf_address[0]+(n+m+offset)*vtxbuf_stride[0]+8);
1826               *((UINT32 *)(&w[m]))=space.read_dword(vtxbuf_address[0]+(n+m+offset)*vtxbuf_stride[0]+12);
1827               c[m]=space.read_dword(vtxbuf_address[3]+(n+m+offset)*vtxbuf_stride[3]+0); // color
1828               xy[m].p[0]=c[m] & 0xff; // b
1829               xy[m].p[1]=(c[m] & 0xff00) >> 8; // g
1830               xy[m].p[2]=(c[m] & 0xff0000) >> 16; // r
1831               xy[m].p[3]=(c[m] & 0xff000000) >> 24; // a
1832               for (u=0;u < 4;u++) {
1833                  xy[m].p[4+u*2]=0;
1834                  xy[m].p[5+u*2]=0;
1835                  if (texture[u].enabled) {
1836                     *((UINT32 *)(&xy[m].p[4+u*2]))=space.read_dword(vtxbuf_address[9+u]+(n+m+offset)*vtxbuf_stride[9+u]+0);
1837                     *((UINT32 *)(&xy[m].p[5+u*2]))=space.read_dword(vtxbuf_address[9+u]+(n+m+offset)*vtxbuf_stride[9+u]+4);
1838                  }
1839               }
1840            }
1841
1842            render_polygon<4>(fb.cliprect(),renderspans,4+4*2,xy); // 4 rgba, 4 texture units 2 uv
1843            /*myline(fb,xy[0].x,xy[0].y,xy[1].x,xy[1].y);
1844            myline(fb,xy[1].x,xy[1].y,xy[2].x,xy[2].y);
1845            myline(fb,xy[2].x,xy[2].y,xy[3].x,xy[3].y);
1846            myline(fb,xy[3].x,xy[3].y,xy[0].x,xy[0].y);*/
1847#ifdef LOG_NV2A
1848            printf(" (%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)\n\r",xy[0].x,xy[0].y,z[0],xy[1].x,xy[1].y,z[1],xy[2].x,xy[2].y,z[2],xy[3].x,xy[3].y,z[3]);
1849#endif
2886            read_vertices_0x1810(space, vert, n+offset, 4);
2887            convert_vertices_poly(vert, xy, 4);
2888            render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv
18502889         }
18512890         wait();
18522891      } else if (type == nv2a_renderer::TRIANGLE_STRIP) {
1853         vertex_t xy[3];
1854         float z[3],w[3];
1855         UINT32 c[3];
2892         vertex vert[4];
2893         vertex_t xy[4];
18562894
1857         //printf("draw triangle\n\r");
1858         // put first 2 vertices data in elements 0,1 of arrays
1859         for (m=0;m < 2;m++) {
1860            *((UINT32 *)(&xy[m].x))=space.read_dword(vtxbuf_address[0]+(m+offset)*vtxbuf_stride[0]+0);
1861            *((UINT32 *)(&xy[m].y))=space.read_dword(vtxbuf_address[0]+(m+offset)*vtxbuf_stride[0]+4);
1862            *((UINT32 *)(&z[m]))=space.read_dword(vtxbuf_address[0]+(m+offset)*vtxbuf_stride[0]+8);
1863            *((UINT32 *)(&w[m]))=space.read_dword(vtxbuf_address[0]+(m+offset)*vtxbuf_stride[0]+12);
1864            c[m]=space.read_dword(vtxbuf_address[3]+(m+offset)*vtxbuf_stride[3]+0); // color
1865            xy[m].p[0]=c[m] & 0xff; // b
1866            xy[m].p[1]=(c[m] & 0xff00) >> 8;  // g
1867            xy[m].p[2]=(c[m] & 0xff0000) >> 16;  // r
1868            xy[m].p[3]=(c[m] & 0xff000000) >> 24;  // a
1869            for (u=0;u < 4;u++) {
1870               xy[m].p[4+u*2]=0;
1871               xy[m].p[5+u*2]=0;
1872               if (texture[u].enabled) {
1873                  *((UINT32 *)(&xy[m].p[4+u*2]))=space.read_dword(vtxbuf_address[9+u]+(m+offset)*vtxbuf_stride[9+u]+0);
1874                  *((UINT32 *)(&xy[m].p[5+u*2]))=space.read_dword(vtxbuf_address[9+u]+(m+offset)*vtxbuf_stride[9+u]+4);
1875               }
1876            }
2895         read_vertices_0x1810(space, vert, offset, 2);
2896         convert_vertices_poly(vert, xy, 2);
2897         count = count - 2;
2898         offset = offset + 2;
2899         for (n = 0; n <= count; n++) {
2900            read_vertices_0x1810(space, vert + ((n+2) & 3), offset + n, 1);
2901            convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1);
2902            render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1)+n) & 3], xy[((~n & 1)+n) & 3], xy[(2+n) & 3]);
18772903         }
1878         for (n=2;n <= count;n++) {
1879            // put vertex n data in element 2 of arrays
1880            *((UINT32 *)(&xy[2].x))=space.read_dword(vtxbuf_address[0]+(n+offset)*vtxbuf_stride[0]+0);
1881            *((UINT32 *)(&xy[2].y))=space.read_dword(vtxbuf_address[0]+(n+offset)*vtxbuf_stride[0]+4);
1882            *((UINT32 *)(&z[2]))=space.read_dword(vtxbuf_address[0]+(n+offset)*vtxbuf_stride[0]+8);
1883            *((UINT32 *)(&w[2]))=space.read_dword(vtxbuf_address[0]+(n+offset)*vtxbuf_stride[0]+12);
1884            c[2]=space.read_dword(vtxbuf_address[3]+(n+offset)*vtxbuf_stride[3]+0); // color
1885            xy[2].p[0]=c[2] & 0xff; // b
1886            xy[2].p[1]=(c[2] & 0xff00) >> 8; // g
1887            xy[2].p[2]=(c[2] & 0xff0000) >> 16; // r
1888            xy[2].p[3]=(c[2] & 0xff000000) >> 24; // a
1889            for (u=0;u < 4;u++) {
1890               xy[2].p[4+u*2]=0;
1891               xy[2].p[5+u*2]=0;
1892               if (texture[u].enabled) {
1893                  *((UINT32 *)(&xy[2].p[4+u*2]))=space.read_dword(vtxbuf_address[9+u]+(n+offset)*vtxbuf_stride[9+u]+0);
1894                  *((UINT32 *)(&xy[2].p[5+u*2]))=space.read_dword(vtxbuf_address[9+u]+(n+offset)*vtxbuf_stride[9+u]+4);
1895               }
1896            }
1897            // draw triangle
1898            render_triangle(fb.cliprect(),renderspans,4+4*2,xy[n & 1],xy[~n & 1],xy[2]); // 012,102,012,102...
1899            // move elements 1,2 to 0,1
1900            xy[0]=xy[1];
1901            xy[1]=xy[2];
1902            z[0]=z[1];
1903            z[1]=z[2];
1904            w[0]=w[1];
1905            w[1]=w[2];
1906         }
19072904         wait();
19082905      } else {
19092906         logerror("Unsupported primitive %d for method 0x1810\n",type);
r31236r31237
19112908      countlen--;
19122909   }
19132910   if (maddress == 0x1800) {
1914      int vtxbuf_stride[16];
1915      UINT32 vtxbuf_address[16];
1916      UINT32 dmahand[2], dmaoff[2], smasiz[2];
1917      UINT32 type, tmp, n, m, u;
2911      UINT32 type, n;
19182912      render_delegate renderspans;
19192913
19202914      // vertices are selected from the vertex buffer using an array of indexes
19212915      // each dword after 1800 contains two 16 bit index values to select the vartices
19222916      type = channel[chanel][subchannel].object.method[0x17fc / 4];
1923      dmahand[0] = channel[chanel][subchannel].object.method[0x019c / 4];
1924      dmahand[1] = channel[chanel][subchannel].object.method[0x01a0 / 4];
1925      geforce_read_dma_object(dmahand[0], dmaoff[0], smasiz[0]);
1926      geforce_read_dma_object(dmahand[1], dmaoff[1], smasiz[1]);
19272917      if (((channel[chanel][subchannel].object.method[0x1e60 / 4] & 7) > 0) && (combiner.used != 0)) {
19282918         renderspans = render_delegate(FUNC(nv2a_renderer::render_register_combiners), this);
19292919      }
r31236r31237
19352925#ifdef LOG_NV2A
19362926      printf("vertex %d %d %d\n\r", type, offset, count);
19372927#endif
1938      for (n = 0; n < 16; n++) {
1939#ifdef LOG_NV2A
1940         printf(" %08X %08X\n\r", channel[chanel][subchannel].object.method[0x1720 / 4 + n], channel[chanel][subchannel].object.method[0x1760 / 4 + n]);
1941#endif
1942         tmp = channel[chanel][subchannel].object.method[0x1760 / 4 + n]; // VTXBUF_FMT
1943         //vtxbuf_kind[n]=tmp & 15;
1944         //vtxbuf_size[n]=(tmp >> 4) & 15;
1945         vtxbuf_stride[n] = (tmp >> 8) & 255;
1946         tmp = channel[chanel][subchannel].object.method[0x1720 / 4 + n]; // VTXBUF_OFFSET
1947         if (tmp & 0x80000000)
1948            vtxbuf_address[n] = (tmp & 0x0fffffff) + dmaoff[1];
1949         else
1950            vtxbuf_address[n] = (tmp & 0x0fffffff) + dmaoff[0];
1951      }
19522928      if (type == nv2a_renderer::QUADS) {
19532929         while (1) {
2930            vertex vert[4];
19542931            vertex_t xy[4];
1955            float z[4], w[4];
1956            UINT32 c[4];
2932            int c;
19572933
1958            // need 4 per object
1959            // get remaining
1960            while ((indexesleft_count < 4) && (countlen > 0)) {
1961               indexesleft[indexesleft_count] = data & 0xffff;
1962               indexesleft[indexesleft_count+ 1] = (data >> 16) & 0xffff;
1963               indexesleft_count+=2;
1964               countlen--;
1965               address = address + 4;
1966               data = space.read_dword(address);
1967            }
1968            if ((indexesleft_count < 4) && (countlen == 0))
2934            if ((countlen * 2 + indexesleft_count) < 4)
19692935               break;
1970            //printf("draw quad\n\r");
1971            for (m = 0; m < 4; m++) {
1972               *((UINT32 *)(&xy[m].x)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 0);
1973               *((UINT32 *)(&xy[m].y)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 4);
1974               *((UINT32 *)(&z[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 8);
1975               *((UINT32 *)(&w[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 12);
1976               c[m] = space.read_dword(vtxbuf_address[3] + indexesleft[m] * vtxbuf_stride[3] + 0); // color
1977               xy[m].p[0] = c[m] & 0xff; // b
1978               xy[m].p[1] = (c[m] & 0xff00) >> 8; // g
1979               xy[m].p[2] = (c[m] & 0xff0000) >> 16; // r
1980               xy[m].p[3] = (c[m] & 0xff000000) >> 24; // a
1981               for (u = 0; u < 4; u++) {
1982                  xy[m].p[4 + u * 2] = 0;
1983                  xy[m].p[5 + u * 2] = 0;
1984                  if (texture[u].enabled) {
1985                     *((UINT32 *)(&xy[m].p[4 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 0);
1986                     *((UINT32 *)(&xy[m].p[5 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 4);
1987                  }
1988               }
1989            }
1990
2936            c=read_vertices_0x1800(space, vert, address, 4);
2937            address = address + c*4;
2938            countlen = countlen - c;
2939            convert_vertices_poly(vert, xy, 4);
19912940            render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv
1992            /*myline(fb,xy[0].x,xy[0].y,xy[1].x,xy[1].y);
1993            myline(fb,xy[1].x,xy[1].y,xy[2].x,xy[2].y);
1994            myline(fb,xy[2].x,xy[2].y,xy[3].x,xy[3].y);
1995            myline(fb,xy[3].x,xy[3].y,xy[0].x,xy[0].y);*/
1996#ifdef LOG_NV2A
1997            printf(" (%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)\n\r", xy[0].x, xy[0].y, z[0], xy[1].x, xy[1].y, z[1], xy[2].x, xy[2].y, z[2], xy[3].x, xy[3].y, z[3]);
1998#endif
1999            for (m = 4; m < indexesleft_count; m++)
2000               indexesleft[m - 4] = indexesleft[m];
2001            indexesleft_count = indexesleft_count - 4;
20022941         }
2942         while (countlen > 0) {
2943            data = space.read_dword(address);
2944            n = (indexesleft_first + indexesleft_count) & 7;
2945            indexesleft[n] = data & 0xffff;
2946            indexesleft[(n + 1) & 7] = (data >> 16) & 0xffff;
2947            indexesleft_count = indexesleft_count + 2;
2948            address += 4;
2949            countlen--;
2950         }
20032951         wait();
20042952      }
20052953      else if (type == nv2a_renderer::TRIANGLES) {
20062954         while (1) {
2007            vertex_t xy[4];
2008            float z[4], w[4];
2009            UINT32 c[4];
2955            vertex vert[3];
2956            vertex_t xy[3];
2957            int c;
20102958
2011            // need 3 dwords per object
2012            // get remaining
2013            while ((indexesleft_count < 3) && (countlen > 0)) {
2014               indexesleft[indexesleft_count] = data & 0xffff;
2015               indexesleft[indexesleft_count + 1] = (data >> 16) & 0xffff;
2016               indexesleft_count += 2;
2017               countlen--;
2018               address = address + 4;
2019               data = space.read_dword(address);
2020            }
2021            if ((indexesleft_count < 3) && (countlen == 0))
2959            if ((countlen * 2 + indexesleft_count) < 3)
20222960               break;
2023            //printf("draw triangle\n\r");
2024            for (m = 0; m < 3; m++) {
2025               *((UINT32 *)(&xy[m].x)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 0);
2026               *((UINT32 *)(&xy[m].y)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 4);
2027               *((UINT32 *)(&z[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 8);
2028               *((UINT32 *)(&w[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 12);
2029               c[m] = space.read_dword(vtxbuf_address[3] + indexesleft[m] * vtxbuf_stride[3] + 0); // color
2030               xy[m].p[0] = c[m] & 0xff; // b
2031               xy[m].p[1] = (c[m] & 0xff00) >> 8; // g
2032               xy[m].p[2] = (c[m] & 0xff0000) >> 16; // r
2033               xy[m].p[3] = (c[m] & 0xff000000) >> 24; // a
2034               for (u = 0; u < 4; u++) {
2035                  xy[m].p[4 + u * 2] = 0;
2036                  xy[m].p[5 + u * 2] = 0;
2037                  if (texture[u].enabled) {
2038                     *((UINT32 *)(&xy[m].p[4 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 0);
2039                     *((UINT32 *)(&xy[m].p[5 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 4);
2040                  }
2041               }
2042            }
2043
2961            c = read_vertices_0x1800(space, vert, address, 3);
2962            address = address + c * 4;
2963            countlen = countlen - c;
2964            convert_vertices_poly(vert, xy, 3);
20442965            render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[0], xy[1], xy[2]); // 4 rgba, 4 texture units 2 uv
2045            /*myline(fb,xy[0].x,xy[0].y,xy[1].x,xy[1].y);
2046            myline(fb,xy[1].x,xy[1].y,xy[2].x,xy[2].y);
2047            myline(fb,xy[2].x,xy[2].y,xy[3].x,xy[3].y);*/
2048#ifdef LOG_NV2A
2049            printf(" (%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)\n\r", xy[0].x, xy[0].y, z[0], xy[1].x, xy[1].y, z[1], xy[2].x, xy[2].y, z[2]);
2050#endif
2051            for (m = 3; m < indexesleft_count; m++)
2052               indexesleft[m - 3] = indexesleft[m];
2053            indexesleft_count = indexesleft_count - 3;
20542966         }
2967         while (countlen > 0) {
2968            data = space.read_dword(address);
2969            n = (indexesleft_first + indexesleft_count) & 7;
2970            indexesleft[n] = data & 0xffff;
2971            indexesleft[(n + 1) & 7] = (data >> 16) & 0xffff;
2972            indexesleft_count = indexesleft_count + 2;
2973            address += 4;
2974            countlen--;
2975         }
20552976         wait();
20562977      }
20572978      else if (type == nv2a_renderer::TRIANGLE_STRIP) {
2058         while (1) {
2979         if ((countlen * 2 + indexesleft_count) >= 3) {
2980            vertex vert[4];
20592981            vertex_t xy[4];
2060            float z[4], w[4];
2061            UINT32 c[4];
2982            int c, count;
20622983
2063            // need 3 dwords per object
2064            // get remaining
2065            while ((indexesleft_count < 3) && (countlen > 0)) {
2066               indexesleft[indexesleft_count] = data & 0xffff;
2067               indexesleft[indexesleft_count + 1] = (data >> 16) & 0xffff;
2068               indexesleft_count += 2;
2069               countlen--;
2070               address = address + 4;
2071               data = space.read_dword(address);
2984            c = read_vertices_0x1800(space, vert, address, 2);
2985            convert_vertices_poly(vert, xy, 2);
2986            address = address + c * 4;
2987            countlen = countlen - c;
2988            count = countlen * 2 + indexesleft_count;
2989            for (n = 0; n < count; n++) { // <=
2990               c = read_vertices_0x1800(space, vert + ((n + 2) & 3), address, 1);
2991               address = address + c * 4;
2992               countlen = countlen - c;
2993               convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1);
2994               render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]);
20722995            }
2073            if ((indexesleft_count < 3) && (countlen == 0))
2074               break;
2075            //printf("draw triangle\n\r");
2076            for (m = 0; m < 3; m++) {
2077               *((UINT32 *)(&xy[m].x)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 0);
2078               *((UINT32 *)(&xy[m].y)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 4);
2079               *((UINT32 *)(&z[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 8);
2080               *((UINT32 *)(&w[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 12);
2081               c[m] = space.read_dword(vtxbuf_address[3] + indexesleft[m] * vtxbuf_stride[3] + 0); // color
2082               xy[m].p[0] = c[m] & 0xff; // b
2083               xy[m].p[1] = (c[m] & 0xff00) >> 8; // g
2084               xy[m].p[2] = (c[m] & 0xff0000) >> 16; // r
2085               xy[m].p[3] = (c[m] & 0xff000000) >> 24; // a
2086               for (u = 0; u < 4; u++) {
2087                  xy[m].p[4 + u * 2] = 0;
2088                  xy[m].p[5 + u * 2] = 0;
2089                  if (texture[u].enabled) {
2090                     *((UINT32 *)(&xy[m].p[4 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 0);
2091                     *((UINT32 *)(&xy[m].p[5 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 4);
2092                  }
2093               }
2094            }
2095
2096            render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[primitives_count & 1], xy[~primitives_count & 1], xy[2]); // 012,102,012,102...
2097            /*myline(fb,xy[0].x,xy[0].y,xy[1].x,xy[1].y);
2098            myline(fb,xy[1].x,xy[1].y,xy[2].x,xy[2].y);
2099            myline(fb,xy[2].x,xy[2].y,xy[3].x,xy[3].y);*/
2100#ifdef LOG_NV2A
2101            printf(" (%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)\n\r", xy[0].x, xy[0].y, z[0], xy[1].x, xy[1].y, z[1], xy[2].x, xy[2].y, z[2]);
2102#endif
2103            primitives_count++;
2104            for (m = 1; m < indexesleft_count; m++)
2105               indexesleft[m - 1] = indexesleft[m];
2106            indexesleft_count = indexesleft_count - 1;
21072996         }
2997         while (countlen > 0) {
2998            data = space.read_dword(address);
2999            n = (indexesleft_first + indexesleft_count) & 7;
3000            indexesleft[n] = data & 0xffff;
3001            indexesleft[(n + 1) & 7] = (data >> 16) & 0xffff;
3002            indexesleft_count = indexesleft_count + 2;
3003            address += 4;
3004            countlen--;
3005         }
21083006         wait();
21093007      }
21103008      else {
r31236r31237
21133011      }
21143012   }
21153013   if (maddress == 0x1818) {
2116      int n,m,u,vwords;
2117      int vattrpos[16];
3014      int n;
21183015      int type;
21193016      render_delegate renderspans;
21203017
r31236r31237
21243021         renderspans=render_delegate(FUNC(nv2a_renderer::render_texture_simple),this);
21253022      } else
21263023         renderspans=render_delegate(FUNC(nv2a_renderer::render_color),this);
2127      vwords=0;
2128      for (n=0;n < 16;n++) {
2129         vattrpos[n]=vwords;
2130         if ((enabled_vertex_attributes & (1 << n)) != 0)
2131            vwords += words_vertex_attributes[n];
2132      }
21333024      // vertices are taken from the next words, not from a vertex buffer
21343025      // first send primitive type with 17fc
21353026      // then countlen number of dwords with 1818
21363027      // end with 17fc primitive type 0
21373028      // at 1760 16 words specify the vertex format:for each possible vertex attribute the number of components (0=not present) and type of each
2138      if ((countlen % vwords) != 0) {
2139         logerror("Method 0x1818 got %d words, at least %d were expected\n",countlen,(countlen/vwords+1)*vwords);
2140         countlen=0;
2141         return;
2142      }
21433029      type=channel[chanel][subchannel].object.method[0x17fc/4];
21443030      if (type == nv2a_renderer::TRIANGLE_FAN) {
3031         vertex vert[3];
21453032         vertex_t xy[3];
2146         float z[3],w[3];
2147         UINT32 c[3];
3033         int c;
21483034
2149         // put first 2 vertices data in elements 0,1 of arrays
2150         for (m=0;m < 2;m++) {
2151            // consider only attributes: position,color0,texture 0-3
2152            // position
2153            *((UINT32 *)(&xy[m].x))=space.read_dword(address+vattrpos[0]*4+0);
2154            *((UINT32 *)(&xy[m].y))=space.read_dword(address+vattrpos[0]*4+4);
2155            *((UINT32 *)(&z[m]))=space.read_dword(address+vattrpos[0]*4+8);
2156            *((UINT32 *)(&w[m]))=space.read_dword(address+vattrpos[0]*4+12);
2157            // color
2158            c[m]=space.read_dword(address+vattrpos[3]*4+0); // color
2159            xy[m].p[0]=c[m] & 0xff; // b
2160            xy[m].p[1]=(c[m] & 0xff00) >> 8;  // g
2161            xy[m].p[2]=(c[m] & 0xff0000) >> 16;  // r
2162            xy[m].p[3]=(c[m] & 0xff000000) >> 24;  // a
2163            // texture 0-3
2164            for (u=0;u < 4;u++) {
2165               xy[m].p[4+u*2]=0;
2166               xy[m].p[5+u*2]=0;
2167               if (texture[u].enabled) {
2168                  *((UINT32 *)(&xy[m].p[4+u*2]))=space.read_dword(address+vattrpos[9+u]*4+0);
2169                  *((UINT32 *)(&xy[m].p[5+u*2]))=space.read_dword(address+vattrpos[9+u]*4+4);
2170               }
2171            }
2172            address=address+vwords*4;
2173            countlen=countlen-vwords;
2174         }
2175         if (countlen <= 0) {
2176            logerror("Method 0x1818 missing %d words to draw a complete primitive\n",-countlen+vwords);
2177            countlen=0;
3035         c=read_vertices_0x1818(space, vert, address, 2);
3036         convert_vertices_poly(vert, xy, 2);
3037         countlen = countlen - c;
3038         if (countlen < 0) {
3039            logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen);
3040            countlen = 0;
21783041            return;
21793042         }
2180         for (n=2;countlen > 0;n++) {
2181            // put vertex n data in element 2 of arrays
2182            // position
2183            *((UINT32 *)(&xy[2].x))=space.read_dword(address+vattrpos[0]*4+0);
2184            *((UINT32 *)(&xy[2].y))=space.read_dword(address+vattrpos[0]*4+4);
2185            *((UINT32 *)(&z[2]))=space.read_dword(address+vattrpos[0]*4+8);
2186            *((UINT32 *)(&w[2]))=space.read_dword(address+vattrpos[0]*4+12);
2187            // color
2188            c[2]=space.read_dword(address+vattrpos[3]*4+0); // color
2189            xy[2].p[0]=c[2] & 0xff; // b
2190            xy[2].p[1]=(c[2] & 0xff00) >> 8;  // g
2191            xy[2].p[2]=(c[2] & 0xff0000) >> 16;  // r
2192            xy[2].p[3]=(c[2] & 0xff000000) >> 24;  // a
2193            // texture 0-3
2194            for (u=0;u < 4;u++) {
2195               xy[2].p[4+u*2]=0;
2196               xy[2].p[5+u*2]=0;
2197               if (texture[u].enabled) {
2198                  *((UINT32 *)(&xy[2].p[4+u*2]))=space.read_dword(address+vattrpos[9+u]*4+0);
2199                  *((UINT32 *)(&xy[2].p[5+u*2]))=space.read_dword(address+vattrpos[9+u]*4+4);
2200               }
2201            }
2202            address=address+vwords*4;
2203            countlen=countlen-vwords;
3043         address = address + c * 4;
3044         for (n = 1; countlen > 0; n++) {
3045            c=read_vertices_0x1818(space, vert + ((n & 1) + 1), address, 1);
3046            countlen = countlen - c;
22043047            if (countlen < 0) {
2205               logerror("Method 0x1818 missing %d words to draw a complete primitive\n",-countlen);
2206               countlen=0;
3048               logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen);
3049               countlen = 0;
22073050               break;
22083051            }
2209            // draw triangle
2210            render_triangle(fb.cliprect(),renderspans,4+4*2,xy[0],xy[1],xy[2]); // 012
2211            // move element 2 to 1
2212            xy[1]=xy[2];
2213            z[1]=z[2];
2214            w[1]=w[2];
3052            address = address + c * 4;
3053            convert_vertices_poly(vert + ((n & 1) + 1), xy + ((n & 1) + 1), 1);
3054            render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[0], xy[(~n & 1) + 1], xy[(n & 1) + 1]);
22153055         }
22163056         wait();
22173057      } else if (type == nv2a_renderer::TRIANGLE_STRIP) {
2218         vertex_t xy[3];
2219         float z[3],w[3];
2220         UINT32 c[3];
3058         vertex vert[4];
3059         vertex_t xy[4];
3060         int c;
22213061
2222         // put first 2 vertices data in elements 0,1 of arrays
2223         for (m=0;m < 2;m++) {
2224            // consider only attributes: position,color0,texture 0-3
2225            // position
2226            *((UINT32 *)(&xy[m].x))=space.read_dword(address+vattrpos[0]*4+0);
2227            *((UINT32 *)(&xy[m].y))=space.read_dword(address+vattrpos[0]*4+4);
2228            *((UINT32 *)(&z[m]))=space.read_dword(address+vattrpos[0]*4+8);
2229            *((UINT32 *)(&w[m]))=space.read_dword(address+vattrpos[0]*4+12);
2230            // color
2231            c[m]=space.read_dword(address+vattrpos[3]*4+0); // color
2232            xy[m].p[0]=c[m] & 0xff; // b
2233            xy[m].p[1]=(c[m] & 0xff00) >> 8;  // g
2234            xy[m].p[2]=(c[m] & 0xff0000) >> 16;  // r
2235            xy[m].p[3]=(c[m] & 0xff000000) >> 24;  // a
2236            // texture 0-3
2237            for (u=0;u < 4;u++) {
2238               xy[m].p[4+u*2]=0;
2239               xy[m].p[5+u*2]=0;
2240               if (texture[u].enabled) {
2241                  *((UINT32 *)(&xy[m].p[4+u*2]))=space.read_dword(address+vattrpos[9+u]*4+0);
2242                  *((UINT32 *)(&xy[m].p[5+u*2]))=space.read_dword(address+vattrpos[9+u]*4+4);
2243               }
2244            }
2245            address=address+vwords*4;
2246            countlen=countlen-vwords;
2247         }
2248         if (countlen <= 0) {
2249            logerror("Method 0x1818 missing %d words to draw a complete primitive\n",-countlen+vwords);
2250            countlen=0;
3062         c=read_vertices_0x1818(space, vert, address, 2);
3063         convert_vertices_poly(vert, xy, 2);
3064         countlen = countlen - c;
3065         if (countlen < 0) {
3066            logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen);
3067            countlen = 0;
22513068            return;
22523069         }
2253         for (n=2;countlen > 0;n++) {
2254            // put vertex n data in element 2 of arrays
2255            // position
2256            *((UINT32 *)(&xy[2].x))=space.read_dword(address+vattrpos[0]*4+0);
2257            *((UINT32 *)(&xy[2].y))=space.read_dword(address+vattrpos[0]*4+4);
2258            *((UINT32 *)(&z[2]))=space.read_dword(address+vattrpos[0]*4+8);
2259            *((UINT32 *)(&w[2]))=space.read_dword(address+vattrpos[0]*4+12);
2260            // color
2261            c[2]=space.read_dword(address+vattrpos[3]*4+0); // color
2262            xy[2].p[0]=c[2] & 0xff; // b
2263            xy[2].p[1]=(c[2] & 0xff00) >> 8;  // g
2264            xy[2].p[2]=(c[2] & 0xff0000) >> 16;  // r
2265            xy[2].p[3]=(c[2] & 0xff000000) >> 24;  // a
2266            // texture 0-3
2267            for (u=0;u < 4;u++) {
2268               xy[2].p[4+u*2]=0;
2269               xy[2].p[5+u*2]=0;
2270               if (texture[u].enabled) {
2271                  *((UINT32 *)(&xy[2].p[4+u*2]))=space.read_dword(address+vattrpos[9+u]*4+0);
2272                  *((UINT32 *)(&xy[2].p[5+u*2]))=space.read_dword(address+vattrpos[9+u]*4+4);
2273               }
2274            }
2275            address=address+vwords*4;
2276            countlen=countlen-vwords;
3070         address = address + c * 4;
3071         for (n = 0;countlen > 0; n++) {
3072            c=read_vertices_0x1818(space, vert + ((n + 2) & 3), address, 1);
3073            convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1);
3074            countlen = countlen - c;
22773075            if (countlen < 0) {
2278               logerror("Method 0x1818 missing %d words to draw a complete primitive\n",-countlen);
2279               countlen=0;
3076               logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen);
3077               countlen = 0;
22803078               break;
22813079            }
2282            // draw triangle
2283            render_triangle(fb.cliprect(),renderspans,4+4*2,xy[n & 1],xy[~n & 1],xy[2]); // 012,102,012,102...
2284            // move elements 1,2 to 0,1
2285            xy[0]=xy[1];
2286            xy[1]=xy[2];
2287            z[0]=z[1];
2288            z[1]=z[2];
2289            w[0]=w[1];
2290            w[1]=w[2];
3080            address = address + c * 4;
3081            render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]);
22913082         }
22923083         wait();
22933084      } else if (type == nv2a_renderer::QUADS) {
2294         vertex_t xy[4];
2295         float z[4],w[4];
2296         UINT32 c[4];
3085         while (countlen > 0) {
3086            vertex vert[4];
3087            vertex_t xy[4];
3088            int c;
22973089
2298         for (n=0;countlen > 0;n+=4) {
2299            for (m=0;m < 4;m++) {
2300               // consider only attributes: position,color0,texture 0-3
2301               // position
2302               *((UINT32 *)(&xy[m].x))=space.read_dword(address+vattrpos[0]*4+0);
2303               *((UINT32 *)(&xy[m].y))=space.read_dword(address+vattrpos[0]*4+4);
2304               *((UINT32 *)(&z[m]))=space.read_dword(address+vattrpos[0]*4+8);
2305               *((UINT32 *)(&w[m]))=space.read_dword(address+vattrpos[0]*4+12);
2306               // color
2307               c[m]=space.read_dword(address+vattrpos[3]*4+0); // color
2308               xy[m].p[0]=c[m] & 0xff; // b
2309               xy[m].p[1]=(c[m] & 0xff00) >> 8;  // g
2310               xy[m].p[2]=(c[m] & 0xff0000) >> 16;  // r
2311               xy[m].p[3]=(c[m] & 0xff000000) >> 24;  // a
2312               // texture 0-3
2313               for (u=0;u < 4;u++) {
2314                  xy[m].p[4+u*2]=0;
2315                  xy[m].p[5+u*2]=0;
2316                  if (texture[u].enabled) {
2317                     *((UINT32 *)(&xy[m].p[4+u*2]))=space.read_dword(address+vattrpos[9+u]*4+0);
2318                     *((UINT32 *)(&xy[m].p[5+u*2]))=space.read_dword(address+vattrpos[9+u]*4+4);
2319                  }
2320               }
2321               address=address+vwords*4;
2322               countlen=countlen-vwords;
2323            }
3090            c = read_vertices_0x1818(space, vert, address, 4);
3091            convert_vertices_poly(vert, xy, 4);
3092            countlen = countlen - c;
23243093            if (countlen < 0) {
2325               countlen=0;
3094               logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen);
3095               countlen = 0;
23263096               break;
23273097            }
2328
2329            render_polygon<4>(fb.cliprect(),renderspans,4+4*2,xy); // 4 rgba, 4 texture units 2 uv
3098            address = address + c * 4;
3099            render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv
23303100         }
23313101         wait();
23323102      } else if (type == nv2a_renderer::QUAD_STRIP) {
3103         vertex vert[4];
23333104         vertex_t xy[4];
2334         float z[4],w[4];
2335         UINT32 c[4];
3105         int c;
23363106
2337         // put first 2 vertices data in elements 0,1 of arrays
2338         for (m=0;m < 2;m++) {
2339            // consider only attributes: position,color0,texture 0-3
2340            // position
2341            *((UINT32 *)(&xy[m].x))=space.read_dword(address+vattrpos[0]*4+0);
2342            *((UINT32 *)(&xy[m].y))=space.read_dword(address+vattrpos[0]*4+4);
2343            *((UINT32 *)(&z[m]))=space.read_dword(address+vattrpos[0]*4+8);
2344            *((UINT32 *)(&w[m]))=space.read_dword(address+vattrpos[0]*4+12);
2345            // color
2346            c[m]=space.read_dword(address+vattrpos[3]*4+0); // color
2347            xy[m].p[0]=c[m] & 0xff; // b
2348            xy[m].p[1]=(c[m] & 0xff00) >> 8;  // g
2349            xy[m].p[2]=(c[m] & 0xff0000) >> 16;  // r
2350            xy[m].p[3]=(c[m] & 0xff000000) >> 24;  // a
2351            // texture 0-3
2352            for (u=0;u < 4;u++) {
2353               xy[m].p[4+u*2]=0;
2354               xy[m].p[5+u*2]=0;
2355               if (texture[u].enabled) {
2356                  *((UINT32 *)(&xy[m].p[4+u*2]))=space.read_dword(address+vattrpos[9+u]*4+0);
2357                  *((UINT32 *)(&xy[m].p[5+u*2]))=space.read_dword(address+vattrpos[9+u]*4+4);
2358               }
2359            }
2360            address=address+vwords*4;
2361            countlen=countlen-vwords;
2362         }
2363         if (countlen <= 0) {
2364            countlen=0;
3107         c=read_vertices_0x1818(space, vert, address, 2);
3108         convert_vertices_poly(vert, xy, 2);
3109         countlen = countlen - c;
3110         if (countlen < 0) {
3111            logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen);
3112            countlen = 0;
23653113            return;
23663114         }
2367         for (n=2;countlen > 0;n+=2) {
2368            // put vertices n,n+1 data in elements 3,2 of arrays
2369            for (m=3;m >= 2;m--) {
2370               // position
2371               *((UINT32 *)(&xy[m].x))=space.read_dword(address+vattrpos[0]*4+0);
2372               *((UINT32 *)(&xy[m].y))=space.read_dword(address+vattrpos[0]*4+4);
2373               *((UINT32 *)(&z[m]))=space.read_dword(address+vattrpos[0]*4+8);
2374               *((UINT32 *)(&w[m]))=space.read_dword(address+vattrpos[0]*4+12);
2375               // color
2376               c[m]=space.read_dword(address+vattrpos[3]*4+0); // color
2377               xy[m].p[0]=c[m] & 0xff; // b
2378               xy[m].p[1]=(c[m] & 0xff00) >> 8;  // g
2379               xy[m].p[2]=(c[m] & 0xff0000) >> 16;  // r
2380               xy[m].p[3]=(c[m] & 0xff000000) >> 24;  // a
2381               // texture 0-3
2382               for (u=0;u < 4;u++) {
2383                  xy[m].p[4+u*2]=0;
2384                  xy[m].p[5+u*2]=0;
2385                  if (texture[u].enabled) {
2386                     *((UINT32 *)(&xy[m].p[4+u*2]))=space.read_dword(address+vattrpos[9+u]*4+0);
2387                     *((UINT32 *)(&xy[m].p[5+u*2]))=space.read_dword(address+vattrpos[9+u]*4+4);
2388                  }
2389               }
2390               address=address+vwords*4;
2391               countlen=countlen-vwords;
2392            }
3115         address = address + c * 4;
3116         for (n = 0; countlen > 0; n+=2) {
3117            c = read_vertices_0x1818(space, vert + ((n + 2) & 3), address + ((n + 2) & 3), 2);
3118            convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 2);
3119            countlen = countlen - c;
23933120            if (countlen < 0) {
2394               countlen=0;
2395               break;
3121               logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen);
3122               countlen = 0;
3123               return;
23963124            }
2397            render_polygon<4>(fb.cliprect(),renderspans,4+4*2,xy); // 4 rgba, 4 texture units 2 uv
2398            // copy elements 3,2 of arrays to elements 0,1 of arrays
2399            xy[0]=xy[3];
2400            z[0]=z[3];
2401            w[0]=w[3];
2402            xy[1]=xy[2];
2403            z[1]=z[2];
2404            w[1]=w[2];
3125            address = address + c * 4;
3126            render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[n & 3], xy[(n + 1) & 3], xy[(n + 2) & 3]);
3127            render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[(n + 2) & 3], xy[(n + 1) & 3], xy[(n + 3) & 3]);
24053128         }
24063129         wait();
24073130      } else {
r31236r31237
24093132         countlen = 0;
24103133      }
24113134   }
3135   if ((maddress >= 0x1720) && (maddress < 0x1760)) {
3136      int bit = method - 0x1720 / 4;
3137
3138      if (data & 0x80000000)
3139         vertexbuffer_address[bit] = (data & 0x0fffffff) + dma_offset[1];
3140      else
3141         vertexbuffer_address[bit] = (data & 0x0fffffff) + dma_offset[0];
3142   }
24123143   if ((maddress >= 0x1760) && (maddress < 0x17A0)) {
24133144      int bit=method-0x1760/4;
24143145
2415      data=data & 255;
2416      if (data > 15)
2417         enabled_vertex_attributes |= (1 << bit);
2418      else
2419         enabled_vertex_attributes &= ~(1 << bit);
3146      vertexbuffer_stride[bit] = (data >> 8) & 255;
3147      //vertexbuffer_kind[n]=tmp & 15;
3148      //vertexbuffer_size[n]=(tmp >> 4) & 15;
3149      data = data & 255;
24203150      switch (data & 15) {
24213151         case 0:
2422            words_vertex_attributes[bit]=(((data >> 4) + 3) & 15) >> 2;
3152            vertex_attribute_words[bit]=(((data >> 4) + 3) & 15) >> 2;
24233153            break;
24243154         case nv2a_renderer::FLOAT:
2425            words_vertex_attributes[bit]=(data >> 4);
3155            vertex_attribute_words[bit]=(data >> 4);
24263156            break;
24273157         case nv2a_renderer::UBYTE:
2428            words_vertex_attributes[bit]=(((data >> 4) + 3) & 15) >> 2;
3158            vertex_attribute_words[bit]=(((data >> 4) + 3) & 15) >> 2;
24293159            break;
24303160         case nv2a_renderer::USHORT:
2431            words_vertex_attributes[bit]=(((data >> 4) + 1) & 15) >> 1;
3161            vertex_attribute_words[bit]=(((data >> 4) + 1) & 15) >> 1;
24323162            break;
24333163         default:
2434            words_vertex_attributes[bit]=0;
3164            vertex_attribute_words[bit]=0;
24353165      }
3166      if (data > 15)
3167         enabled_vertex_attributes |= (1 << bit);
3168      else
3169         enabled_vertex_attributes &= ~(1 << bit);
3170      for (int n = bit+1; n < 16; n++) {
3171         if ((enabled_vertex_attributes & (1 << (n - 1))) != 0)
3172            vertex_attribute_offset[n] = vertex_attribute_offset[n - 1] + vertex_attribute_words[n - 1];
3173         else
3174            vertex_attribute_offset[n] = vertex_attribute_offset[n - 1];
3175      }
24363176      countlen--;
24373177   }
24383178   if ((maddress == 0x1d6c) || (maddress == 0x1d70) || (maddress == 0x1a4))
24393179      countlen--;
3180   if (maddress == 0x019c) {
3181      geforce_read_dma_object(data, dma_offset[0], dma_size[0]);
3182   }
3183   if (maddress == 0x01a0) {
3184      geforce_read_dma_object(data, dma_offset[1], dma_size[1]);
3185   }
24403186   if (maddress == 0x1d70) {
24413187      // with 1d70 write the value at offest [1d6c] inside dma object [1a4]
24423188      UINT32 offset,base;
r31236r31237
24503196      countlen--;
24513197   }
24523198   if (maddress == 0x1d94) {
3199      // possible buffers: color, depth, stencil, and accumulation
24533200      // clear framebuffer
24543201      if (data & 0xf0) {
24553202         // clear colors
24563203         UINT32 color=channel[chanel][subchannel].object.method[0x1d90/4];
2457         fb.fill(color & 0xffffff);
3204         fb.fill(color);
24583205         //printf("clearscreen\n\r");
24593206      }
24603207      if (data & 0x03) {
r31236r31237
24623209      }
24633210      countlen--;
24643211   }
3212   if (maddress == 0x0300) {
3213      alpha_test_enabled = data != 0;
3214   }
3215   if (maddress == 0x033c) {
3216      alpha_func = data;
3217   }
3218   if (maddress == 0x0340) {
3219      alpha_reference = data;
3220   }
3221   if (maddress == 0x0304) {
3222      if (logical_operation_enabled)
3223         blending_enabled = false;
3224      else
3225         blending_enabled = data != 0;
3226   }
3227   if (maddress == 0x0344) {
3228      blend_function_source = data;
3229   }
3230   if (maddress == 0x0348) {
3231      blend_function_destination = data;
3232   }
3233   if (maddress == 0x034c) {
3234      blend_color = data;
3235   }
3236   if (maddress == 0x0350) {
3237      blend_equation = data;
3238   }
3239   if (maddress == 0x0d40) {
3240      if (data != 0)
3241         blending_enabled = false;
3242      else
3243         blending_enabled = channel[chanel][subchannel].object.method[0x0304 / 4] != 0;
3244      logical_operation_enabled = data != 0;
3245   }
3246   if (maddress == 0x0d44) {
3247      logical_operation = data;
3248   }
24653249   // Texture Units
24663250   if ((maddress >= 0x1b00) && (maddress < 0x1c00)) {
24673251      int unit;//,off;
r31236r31237
25683352         logerror("Enabled both fixed function pipeline and vertex program ?\n");
25693353      else
25703354         logerror("Unknown value %d to method 0x1e94\n",data);*/
3355      vertex_pipeline = data & 6;
25713356      countlen--;
25723357   }
25733358   if (maddress == 0x1e9c) {
r31236r31237
25783363   if (maddress == 0x1ea0) {
25793364      //logerror("VP_START_FROM_ID %d\n",data);
25803365      vertexprogram.instructions=vertexprogram.upload_instruction/4;
3366      vertexprogram.start_instruction = data * 4;
25813367      countlen--;
25823368   }
25833369   if (maddress == 0x1ea4) {
25843370      //logerror("VP_UPLOAD_CONST_ID %d\n",data);
2585      vertexprogram.upload_parameter=data;
3371      vertexprogram.upload_parameter=data*4;
25863372      countlen--;
25873373   }
25883374   if ((maddress >= 0x0b00) && (maddress < 0x0b80)) {
r31236r31237
25963382   if ((maddress >= 0x0b80) && (maddress < 0x0c00)) {
25973383      //logerror("VP_UPLOAD_CONST\n");
25983384      if (vertexprogram.upload_parameter < 1024)
2599         vertexprogram.parameter[vertexprogram.upload_parameter] = data;
3385         *(UINT32 *)(&vertexprogram.parameter[vertexprogram.upload_parameter]) = data;
26003386      else
26013387         logerror("Need to increase size of vertexprogram.parameter to %d\n\r", vertexprogram.upload_parameter);
26023388      vertexprogram.upload_parameter++;
r31236r31237
27383524   strncpy(debug_grab_textfile, filename, 127);
27393525}
27403526
3527void nv2a_renderer::debug_grab_vertex_program_slot(int slot, UINT32 *instruction)
3528{
3529   if (slot >= 1024 / 4)
3530      return;
3531   instruction[0] = vertexprogram.instruction[slot * 4 + 0];
3532   instruction[1] = vertexprogram.instruction[slot * 4 + 1];
3533   instruction[2] = vertexprogram.instruction[slot * 4 + 2];
3534   instruction[3] = vertexprogram.instruction[slot * 4 + 3];
3535}
3536
27413537void nv2a_renderer::savestate_items()
27423538{
27433539}
r31236r31237
34564252   }
34574253}
34584254
3459void chihiro_state::debug_grab_texture(int type, char *filename)
3460{
3461   nvidia_nv2a->debug_grab_texture(type, filename);
3462}
3463
34644255void chihiro_state::vblank_callback(screen_device &screen, bool state)
34654256{
34664257   nvidia_nv2a->vblank_callback(screen,state);

Previous 199869 Revisions Next


© 1997-2024 The MAME Team