daa6de7c96f0ba6e07bb47a7a6f6346260371b44
[mupen64plus-pandora.git] / source / gles2n64 / src / GBI.cpp
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include "gles2N64.h"
5 #include "GBI.h"
6 #include "RDP.h"
7 #include "RSP.h"
8 #include "F3D.h"
9 #include "F3DEX.h"
10 #include "F3DEX2.h"
11 #include "L3D.h"
12 #include "L3DEX.h"
13 #include "L3DEX2.h"
14 #include "S2DEX.h"
15 #include "S2DEX2.h"
16 #include "F3DDKR.h"
17 #include "F3DWRUS.h"
18 #include "F3DPD.h"
19 #include "F3DCBFD.h"
20 #include "Types.h"
21 # include <string.h>
22 # include <unistd.h>
23 # include <stdlib.h>
24 # include "convert.h"
25 #include "Common.h"
26 #include "ticks.h"
27
28 #include "CRC.h"
29 #include "Debug.h"
30
31 u32 uc_crc, uc_dcrc;
32 char uc_str[256];
33
34 SpecialMicrocodeInfo specialMicrocodes[] =
35 {
36     {F3DWRUS, FALSE, 0xd17906e2, "RSP SW Version: 2.0D, 04-01-96"},
37     {F3DWRUS, FALSE,  0x94c4c833, "RSP SW Version: 2.0D, 04-01-96"},
38     {S2DEX, FALSE, 0x9df31081, "RSP Gfx ucode S2DEX  1.06 Yoshitaka Yasumoto Nintendo."},
39     {F3DDKR, FALSE, 0x8d91244f, "Diddy Kong Racing"},
40     {F3DDKR, FALSE, 0x6e6fc893, "Diddy Kong Racing"},
41     {F3DDKR, FALSE, 0xbde9d1fb, "Jet Force Gemini"},
42     {F3DPD, FALSE, 0x1c4f7869, "Perfect Dark"},
43     {F3DEX, FALSE, 0x0ace4c3f, "Mario Kart"},
44     //{F3DEX, FALSE, 0xda51ccdb, "Rogue Squadron"},
45     //{F3DCBFD, FALSE, 0x1b4ace88, "RSP Gfx ucode F3DEXBG.NoN fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo."},
46 };
47
48 u32 G_RDPHALF_1, G_RDPHALF_2, G_RDPHALF_CONT;
49 u32 G_SPNOOP;
50 u32 G_SETOTHERMODE_H, G_SETOTHERMODE_L;
51 u32 G_DL, G_ENDDL, G_CULLDL, G_BRANCH_Z;
52 u32 G_LOAD_UCODE;
53 u32 G_MOVEMEM, G_MOVEWORD;
54 u32 G_MTX, G_POPMTX;
55 u32 G_GEOMETRYMODE, G_SETGEOMETRYMODE, G_CLEARGEOMETRYMODE;
56 u32 G_TEXTURE;
57 u32 G_DMA_IO, G_DMA_DL, G_DMA_TRI, G_DMA_MTX, G_DMA_VTX, G_DMA_OFFSETS;
58 u32 G_SPECIAL_1, G_SPECIAL_2, G_SPECIAL_3;
59 u32 G_VTX, G_MODIFYVTX, G_VTXCOLORBASE;
60 u32 G_TRI1, G_TRI2, G_TRI4;
61 u32 G_QUAD, G_LINE3D;
62 u32 G_RESERVED0, G_RESERVED1, G_RESERVED2, G_RESERVED3;
63 u32 G_SPRITE2D_BASE;
64 u32 G_BG_1CYC, G_BG_COPY;
65 u32 G_OBJ_RECTANGLE, G_OBJ_SPRITE, G_OBJ_MOVEMEM;
66 u32 G_SELECT_DL, G_OBJ_RENDERMODE, G_OBJ_RECTANGLE_R;
67 u32 G_OBJ_LOADTXTR, G_OBJ_LDTX_SPRITE, G_OBJ_LDTX_RECT, G_OBJ_LDTX_RECT_R;
68 u32 G_RDPHALF_0, G_TRI_UNKNOWN;
69
70 u32 G_MTX_STACKSIZE;
71 u32 G_MTX_MODELVIEW;
72 u32 G_MTX_PROJECTION;
73 u32 G_MTX_MUL;
74 u32 G_MTX_LOAD;
75 u32 G_MTX_NOPUSH;
76 u32 G_MTX_PUSH;
77
78 u32 G_TEXTURE_ENABLE;
79 u32 G_SHADING_SMOOTH;
80 u32 G_CULL_FRONT;
81 u32 G_CULL_BACK;
82 u32 G_CULL_BOTH;
83 u32 G_CLIPPING;
84
85 u32 G_MV_VIEWPORT;
86
87 u32 G_MWO_aLIGHT_1, G_MWO_bLIGHT_1;
88 u32 G_MWO_aLIGHT_2, G_MWO_bLIGHT_2;
89 u32 G_MWO_aLIGHT_3, G_MWO_bLIGHT_3;
90 u32 G_MWO_aLIGHT_4, G_MWO_bLIGHT_4;
91 u32 G_MWO_aLIGHT_5, G_MWO_bLIGHT_5;
92 u32 G_MWO_aLIGHT_6, G_MWO_bLIGHT_6;
93 u32 G_MWO_aLIGHT_7, G_MWO_bLIGHT_7;
94 u32 G_MWO_aLIGHT_8, G_MWO_bLIGHT_8;
95
96 //GBIFunc GBICmd[256];
97 GBIInfo GBI;
98
99 void GBI_Unknown( u32 w0, u32 w1 )
100 {
101 }
102
103 #if 0
104 INT_PTR CALLBACK MicrocodeDlgProc( HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
105 {
106     switch (uMsg)
107     {
108         case WM_INITDIALOG:
109             for (int i = 0; i < numMicrocodeTypes; i++)
110             {
111                 SendDlgItemMessage( hWndDlg, IDC_MICROCODE, CB_ADDSTRING, 0, (LPARAM)MicrocodeTypes[i] );
112             }
113             SendDlgItemMessage( hWndDlg, IDC_MICROCODE, CB_SETCURSEL, 0, 0 );
114
115             char text[1024];
116             sprintf( text, "Microcode CRC:\t\t0x%08x\r\nMicrocode Data CRC:\t0x%08x\r\nMicrocode Text:\t\t%s", uc_crc, uc_dcrc, uc_str );
117             SendDlgItemMessage( hWndDlg, IDC_TEXTBOX, WM_SETTEXT, NULL, (LPARAM)text );
118             return TRUE;
119
120         case WM_COMMAND:
121             switch (LOWORD(wParam))
122             {
123                 case IDOK:
124                     EndDialog( hWndDlg, SendDlgItemMessage( hWndDlg, IDC_MICROCODE, CB_GETCURSEL, 0, 0 ) );
125                     return TRUE;
126
127                 case IDCANCEL:
128                     EndDialog( hWndDlg, NONE );
129                     return TRUE;
130             }
131             break;
132     }
133
134     return FALSE;
135 }
136 #elif defined(USE_GTK)
137 static int selectedMicrocode = -1;
138 static GtkWidget *microcodeWindow = 0;
139 static GtkWidget *microcodeList = 0;
140
141 static void okButton_clicked( GtkWidget *widget, void *data )
142 {
143     gtk_widget_hide( microcodeWindow );
144     if (GTK_LIST(microcodeList)->selection != 0)
145     {
146         char *text = 0;
147         GtkListItem *item = GTK_LIST_ITEM(GTK_LIST(microcodeList)->selection->data);
148         GtkLabel *label = GTK_LABEL(GTK_BIN(item)->child);
149         gtk_label_get( label, &text );
150         if (text != 0)
151             for (int i = 0; i < numMicrocodeTypes; i++)
152                 if (!strcmp( text, MicrocodeTypes[i] ))
153                 {
154                     selectedMicrocode = i;
155                     return;
156                 }
157     }
158
159     selectedMicrocode = NONE;
160 }
161
162 static void stopButton_clicked( GtkWidget *widget, void *data )
163 {
164     gtk_widget_hide( microcodeWindow );
165     selectedMicrocode = NONE;
166 }
167
168 static gint
169 delete_question_event(GtkWidget *widget, GdkEvent *event, gpointer data)
170 {
171     return TRUE; // undeleteable
172 }
173
174 static int MicrocodeDialog()
175 {
176     GtkWidget *infoLabel;
177     GtkWidget *infoFrame, *infoTable;
178     GtkWidget *crcInfoLabel, *crcDataInfoLabel, *textInfoLabel;
179     GtkWidget *crcLabel = NULL, *crcDataLabel = NULL, *textLabel = NULL;
180     GtkWidget *selectUcodeLabel;
181     //GtkWidget *microcodeLabel;
182     GtkWidget *okButton, *stopButton;
183     GList *ucodeList = 0;
184     char buf[1024];
185
186     if (!g_thread_supported())
187         g_thread_init( NULL );
188     gdk_threads_enter();
189
190     // create dialog
191     if (microcodeWindow == 0)
192     {
193         microcodeWindow = gtk_dialog_new();
194         gtk_signal_connect( GTK_OBJECT(microcodeWindow), "delete_event",
195                             GTK_SIGNAL_FUNC(delete_question_event), (gpointer)NULL );
196         sprintf( buf, "%s - unknown microcode", pluginName );
197         gtk_window_set_title( GTK_WINDOW(microcodeWindow), buf );
198         gtk_container_set_border_width( GTK_CONTAINER(GTK_DIALOG(microcodeWindow)->vbox), 11 );
199
200         // ok button
201         okButton = gtk_button_new_with_label( "Ok" );
202         gtk_signal_connect_object( GTK_OBJECT(okButton), "clicked",
203                                GTK_SIGNAL_FUNC(okButton_clicked), NULL );
204         gtk_container_add( GTK_CONTAINER(GTK_DIALOG(microcodeWindow)->action_area), okButton );
205
206         // stop button
207         stopButton = gtk_button_new_with_label( "Stop" );
208         gtk_signal_connect_object( GTK_OBJECT(stopButton), "clicked",
209                                GTK_SIGNAL_FUNC(stopButton_clicked), NULL );
210         gtk_container_add( GTK_CONTAINER(GTK_DIALOG(microcodeWindow)->action_area), stopButton );
211
212         // info label
213         infoLabel = gtk_label_new( "Unknown microcode. Please notify Orkin, including the following information:" );
214         gtk_box_pack_start_defaults( GTK_BOX(GTK_DIALOG(microcodeWindow)->vbox), infoLabel );
215
216         // info frame
217         infoFrame = gtk_frame_new( "Microcode info" );
218         gtk_container_set_border_width( GTK_CONTAINER(infoFrame), 7 );
219         gtk_box_pack_start_defaults( GTK_BOX(GTK_DIALOG(microcodeWindow)->vbox), infoFrame );
220
221         infoTable = gtk_table_new( 3, 2, FALSE );
222         gtk_container_set_border_width( GTK_CONTAINER(infoTable), 7 );
223         gtk_table_set_col_spacings( GTK_TABLE(infoTable), 3 );
224         gtk_table_set_row_spacings( GTK_TABLE(infoTable), 3 );
225         gtk_container_add( GTK_CONTAINER(infoFrame), infoTable );
226
227         crcInfoLabel = gtk_label_new( "Microcode CRC:" );
228         crcDataInfoLabel = gtk_label_new( "Microcode Data CRC:" );
229         textInfoLabel = gtk_label_new( "Microcode Text:" );
230
231         crcLabel = gtk_label_new( "" );
232         crcDataLabel = gtk_label_new( "" );
233         textLabel = gtk_label_new( "" );
234
235         gtk_table_attach_defaults( GTK_TABLE(infoTable), crcInfoLabel, 0, 1, 0, 1 );
236         gtk_table_attach_defaults( GTK_TABLE(infoTable), crcLabel, 1, 2, 0, 1 );
237         gtk_table_attach_defaults( GTK_TABLE(infoTable), crcDataInfoLabel, 0, 1, 1, 2 );
238         gtk_table_attach_defaults( GTK_TABLE(infoTable), crcDataLabel, 1, 2, 1, 2 );
239         gtk_table_attach_defaults( GTK_TABLE(infoTable), textInfoLabel, 0, 1, 2, 3 );
240         gtk_table_attach_defaults( GTK_TABLE(infoTable), textLabel, 1, 2, 2, 3 );
241
242         selectUcodeLabel = gtk_label_new( "You can manually select the closest matching microcode." );
243         for (int i = 0; i < numMicrocodeTypes; i++)
244             ucodeList = g_list_append( ucodeList, gtk_list_item_new_with_label( MicrocodeTypes[i] ) );
245         microcodeList = gtk_list_new();
246         gtk_list_set_selection_mode( GTK_LIST(microcodeList), GTK_SELECTION_SINGLE );
247         gtk_list_append_items( GTK_LIST(microcodeList), ucodeList );
248
249         gtk_box_pack_start_defaults( GTK_BOX(GTK_DIALOG(microcodeWindow)->vbox), selectUcodeLabel );
250         gtk_box_pack_start_defaults( GTK_BOX(GTK_DIALOG(microcodeWindow)->vbox), microcodeList );
251     }
252
253     snprintf( buf, 1024, "0x%8.8X", (unsigned int)uc_crc );
254         if(crcLabel) gtk_label_set_text( GTK_LABEL(crcLabel), buf );
255     snprintf( buf, 1024, "0x%8.8X", (unsigned int)uc_dcrc );
256     if(crcDataLabel) gtk_label_set_text( GTK_LABEL(crcDataLabel), buf );
257     if(textLabel) gtk_label_set_text( GTK_LABEL(textLabel), uc_str );
258
259     selectedMicrocode = -1;
260     gtk_widget_show_all( microcodeWindow );
261
262     while (selectedMicrocode == -1)
263     {
264         if( gtk_main_iteration() )
265             break;
266         usleep( 10000 );
267     }
268     gdk_threads_leave();
269
270     return selectedMicrocode;
271 }
272 #else
273 static int MicrocodeDialog()
274 {
275     // FIXME
276     return 0;
277 }
278 #endif
279
280 MicrocodeInfo *GBI_AddMicrocode()
281 {
282     MicrocodeInfo *newtop = (MicrocodeInfo*)malloc( sizeof( MicrocodeInfo ) );
283
284     newtop->lower = GBI.top;
285     newtop->higher = NULL;
286
287     if (GBI.top)
288         GBI.top->higher = newtop;
289
290     if (!GBI.bottom)
291         GBI.bottom = newtop;
292
293     GBI.top = newtop;
294
295     GBI.numMicrocodes++;
296
297
298     return newtop;
299 }
300
301 void GBI_Init()
302 {
303     GBI.top = NULL;
304     GBI.bottom = NULL;
305     GBI.current = NULL;
306     GBI.numMicrocodes = 0;
307
308     for (u32 i = 0; i <= 0xFF; i++)
309         GBI.cmd[i] = GBI_Unknown;
310
311 #ifdef PROFILE_GBI
312     GBI_ProfileInit();
313 #endif
314 }
315
316 void GBI_Destroy()
317 {
318     while (GBI.bottom)
319     {
320         MicrocodeInfo *newBottom = GBI.bottom->higher;
321
322         if (GBI.bottom == GBI.top)
323             GBI.top = NULL;
324
325         free( GBI.bottom );
326
327         GBI.bottom = newBottom;
328
329         if (GBI.bottom)
330             GBI.bottom->lower = NULL;
331
332         GBI.numMicrocodes--;
333     }
334 }
335
336 #ifdef PROFILE_GBI
337 void GBI_ProfileInit()
338 {
339     GBI_ProfileReset();
340 }
341
342 void GBI_ProfileBegin(u32 cmd)
343 {
344     GBI.profileTmp = ticksGetTicks();
345 }
346
347 void GBI_ProfileEnd(u32 cmd)
348 {
349     unsigned int i = 256*GBI.current->type + cmd;
350     GBI.profileNum[i]++;
351     GBI.profileTimer[i] += ticksGetTicks() - GBI.profileTmp;
352 }
353
354 void
355 GBI_ProfileReset()
356 {
357     memset(GBI.profileTimer, 0, 12 * 256 * sizeof(int));
358     memset(GBI.profileNum, 0, 12 * 256 * sizeof(int));
359 }
360
361 u32
362 GBI_GetFuncTime(u32 ucode, u32 cmd)
363 {
364     return GBI.profileTimer[ucode*256+cmd];
365 }
366
367 u32
368 GBI_GetFuncNum(u32 ucode, u32 cmd)
369 {
370     return GBI.profileNum[ucode*256+cmd];
371 }
372
373 u32
374 GBI_ProfilePrint(FILE *file)
375 {
376     int uc, cmd, total=0;
377
378     for(uc=0;uc<12;uc++)
379     {
380         for(cmd=0;cmd<256;cmd++)
381         {
382             total += GBI_GetFuncTime(uc, cmd);
383         }
384     }
385
386
387     for(uc=0;uc<12;uc++)
388     {
389         for(cmd=0;cmd<256;cmd++)
390         {
391             unsigned int t = GBI_GetFuncTime(uc, cmd);
392             if (t != 0)
393             {
394                 fprintf(file, "%s x %i = %u ms (%.2f%%)\n", GBI_GetFuncName(uc,cmd), GBI_GetFuncNum(uc, cmd), t, 100.0f * (float)t / total);
395             }
396         }
397     }
398     return total;
399 }
400
401 const char*
402 GBI_GetUcodeName(u32 ucode)
403 {
404     switch(ucode)
405     {
406         case F3D:       return "F3D";
407         case F3DEX:     return "F3DEX";
408         case F3DEX2:    return "F3DEX2";
409         case L3D:       return "L3D";
410         case L3DEX:     return "L3DEX";
411         case L3DEX2:    return "L3DEX2";
412         case S2DEX:     return "S2DEX";
413         case S2DEX2:    return "S2DEX2";
414         case F3DPD:     return "F3DPD";
415         case F3DDKR:    return "F3DDKR";
416         case F3DWRUS:   return "F3DWRUS";
417         case NONE:      return "NONE";
418         default:        return "UNKNOWN UCODE";
419     }
420 }
421
422 const char*
423 GBI_GetFuncName(unsigned int ucode, unsigned int cmd)
424 {
425     switch(cmd)
426     {
427         //common
428         case G_SETCIMG:             return "G_SETCIMG";
429         case G_SETZIMG:             return "G_SETZIMG";
430         case G_SETTIMG:             return "G_SETTIMG";
431         case G_SETCOMBINE:          return "G_SETCOMBINE";
432         case G_SETENVCOLOR:         return "G_SETENVCOLOR";
433         case G_SETPRIMCOLOR:        return "G_SETPRIMCOLOR";
434         case G_SETBLENDCOLOR:       return "G_SETBLENDCOLOR";
435         case G_SETFOGCOLOR:         return "G_SETFOGCOLOR";
436         case G_SETFILLCOLOR:        return "G_SETFILLCOLOR";
437         case G_FILLRECT:            return "G_FILLRECT";
438         case G_SETTILE:             return "G_SETTILE";
439         case G_LOADTILE:            return "G_LOADTILE";
440         case G_LOADBLOCK:           return "G_LOADBLOCK";
441         case G_SETTILESIZE:         return "G_SETTILESIZE";
442         case G_LOADTLUT:            return "G_LOADTLUT";
443         case G_RDPSETOTHERMODE:     return "G_RDPSETOTHERMODE";
444         case G_SETPRIMDEPTH:        return "G_SETPRIMDEPTH";
445         case G_SETSCISSOR:          return "G_SETSCISSOR";
446         case G_SETCONVERT:          return "G_SETCONVERT";
447         case G_SETKEYR:             return "G_SETKEYR";
448         case G_SETKEYGB:            return "G_SETKEYGB";
449         case G_RDPFULLSYNC:         return "G_RDPFULLSYNC";
450         case G_RDPTILESYNC:         return "G_RDPTILESYNC";
451         case G_RDPPIPESYNC:         return "G_RDPPIPESYNC";
452         case G_RDPLOADSYNC:         return "G_RDPLOADSYNC";
453         case G_TEXRECTFLIP:         return "G_TEXRECTFLIP";
454
455         //ucode
456         case 0x00:                  return "SPNOOP";
457
458 /*
459         F3D_MTX:                0x01
460         F3DEX2_VTX              0x01
461         F3DDKR_DMA_MTX          0x01
462         S2DEX_BG_1CYC           0x01
463         S2DEX2_OBJ_RECTANGLE    0x01
464 */
465         case 0x01:
466         {
467             switch(ucode)
468             {
469                 case F3DEX2:        return "F3DEX2_VTX";
470                 case F3DDKR:        return "F3DDKR_DMA_MTX";
471                 case S2DEX:         return "S2DEX_BG_1CYC";
472                 case S2DEX2:        return "S2DEX2_OBJ_RECTANGLE";
473                 default:            return "F3D_MTX";
474             }
475         }
476 /*
477         F3D_RESERVED0:          0x02
478         F3DEX2_MODIFYVTX        0x02
479         S2DEX_BG_COPY           0x02
480         S2DEX2_OBJ_SPRITE       0x02
481 */
482         case 0x02:
483         {
484             switch(ucode)
485             {
486                 case F3DEX2:        return "F3DEX2_MODIFYVTX";
487                 case S2DEX:         return "S2DEX_BG_COPY";
488                 case S2DEX2:        return "S2DEX2_OBJ_SPRITE";
489                 default:            return "F3D_RESERVED0";
490             }
491         }
492 /*
493         F3D_MOVEMEM:            0x03
494         F3DEX2_CULLDL           0x03
495         S2DEX_OBJ_RECTANGLE     0x03
496 */
497         case 0x03:
498         {
499             switch(ucode)
500             {
501                 case F3DEX2:        return "F3DEX2_CULLDL";
502                 case S2DEX:         return "S2DEX_OBJ_RECTANGLE";
503                 default:            return "F3D_MOVEMEM";
504             }
505         }
506 /*
507         F3D_VTX:                0x04
508         F3DEX2_BRANCH_Z         0x04
509         F3DDKR_DMA_VTX          0x04
510         S2DEX_OBJ_SPRITE        0x04
511         S2DEX2_SELECT_DL        0x04
512 */
513         case 0x04:
514         {
515             switch(ucode)
516             {
517                 case F3DEX2:        return "F3DEX2_BRANCH_Z";
518                 case F3DDKR:        return "F3DDKR_DMA_VTX";
519                 case S2DEX:         return "S2DEX_OBJ_SPRITE";
520                 case S2DEX2:        return "S2DEX2_SELECT_DL";
521                 default:            return "F3D_VTX";
522             }
523         }
524
525 /*
526         F3D_RESERVED1:          0x05
527         F3DEX2_TRI1             0x05
528         F3DDKR_DMA_TRI          0x05
529         S2DEX_OBJ_MOVEMEM       0x05
530         S2DEX2_OBJ_LOADTXTR     0x05
531 */
532         case 0x05:
533         {
534             switch(ucode)
535             {
536                 case F3DEX2:        return "F3DEX2_TR1";
537                 case F3DDKR:        return "F3DDKR_DMA_TRI";
538                 case S2DEX:         return "S2DEX_OBJ_MOVEMEM";
539                 case S2DEX2:        return "S2DEX2_OBJ_LOADTXTR";
540                 default:            return "F3D_RESERVED1";
541             }
542         }
543 /*
544         F3D_DL:                 0x06
545         F3DEX2_TRI2             0x06
546         S2DEX2_OBJ_LDTX_SPRITE  0x06
547 */
548         case 0x06:
549         {
550             switch(ucode)
551             {
552                 case F3DEX2:        return "F3DEX2_TR2";
553                 case S2DEX2:        return "S2DEX2_OBJ_LDTX_SPRITE";
554                 default:            return "F3D_DL";
555             }
556         }
557
558 /*
559         F3D_RESERVED2:          0x07
560         F3DEX2_QUAD             0x07
561         F3DPD_VTXCOLORBASE      0x07
562         F3DDKR_DMA_DL           0x07
563         S2DEX2_OBJ_LDTX_RECT    0x07
564 */
565         case 0x07:
566         {
567             switch(ucode)
568             {
569                 case F3DEX2:        return "F3DEX2_QUAD";
570                 case F3DPD:         return "F3DPD_VTXCOLORBASE";
571                 case F3DDKR:        return "F3DDKR_DMA_DL";
572                 case S2DEX2:        return "S2DEX2_OBJ_LDTX_RECT";
573                 default:            return "F3D_RESERVED2";
574             }
575         }
576 /*
577         F3D_RESERVED3:          0x08
578         L3DEX2_LINE3D           0x08
579         S2DEX2_OBJ_LDTX_RECT_R  0x08
580 */
581         case 0x08:
582         {
583             switch(ucode)
584             {
585                 case L3DEX2:        return "L3DEX2_LINE3D";
586                 case S2DEX2:        return "S2DEX2_OBJ_LDTX_RECT_R";
587                 default:            return "F3D_RESERVED3";
588             }
589         }
590
591 /*
592         F3D_SPRITE2D_BASE:      0x09
593         S2DEX2_BG_1CYC          0x09
594 */
595         case 0x09:
596         {
597             switch(ucode)
598             {
599                 case S2DEX2:        return "S2DEX2_BG_1CYC";
600                 default:            return "F3D_SPRITE2D_BASE";
601             }
602         }
603
604 //        S2DEX2_BG_COPY          0x0A
605         case 0x0A:                  return "S2DEX2_BG_COPY";
606 //        S2DEX2_OBJ_RENDERMODE   0x0B
607         case 0x0B:                  return "S2DEX2_OBJ_RENDERMODE";
608 //        F3DEX2_RDPHALF_2        0xF1
609         case 0xF1:                  return "F3DEX2_RDPHALF_2";
610 /*
611         S2DEX_RDPHALF_0         0xE4
612         S2DEX2_RDPHALF_0        0xE4
613 */
614         case 0xE4:
615         {
616             switch(ucode)
617             {
618                 case S2DEX:         return "S2DEX_RDPHALF_0";
619                 case S2DEX2:        return "S2DEX2_RDPHALF_0";
620                 default:            return "G_TEXRECT";
621             }
622         }
623 //        F3DEX2_SETOTHERMODE_H   0xE3
624         case 0xE3:                  return "F3DEX2_SETOTHERMODE_H";
625 //        F3DEX2_SETOTHERMODE_L   0xE2
626         case 0xE2:                  return "F3DEX2_SETOTHERMODE_L";
627 //        F3DEX2_RDPHALF_1        0xE1
628         case 0xE1:                  return "F3DEX2_RDPHALF_1";
629 //        F3DEX2_SPNOOP           0xE0
630         case 0xE0:                  return "F3DEX2_SPNOOP";
631 //        F3DEX2_ENDDL            0xDF
632         case 0xDF:                  return "F3DEX2_ENDDL";
633 //        F3DEX2_DL               0xDE
634         case 0xDE:                  return "F3DEX2_DL";
635 //        F3DEX2_LOAD_UCODE       0xDD
636         case 0xDD:                  return "F3DEX2_LOAD_UCODE";
637 /*
638         F3DEX2_MOVEMEM          0xDC
639         S2DEX2_OBJ_MOVEMEM      0xDC
640 */
641         case 0xDC:
642         {
643             switch(ucode)
644             {
645                 case S2DEX2:        return "S2DEX2_OBJ_MOVEMEM";
646                 default:            return "F3DEX2_MOVEMEM";
647             }
648         }
649 //        F3DEX2_MOVEWORD         0xDB
650         case 0xDB:                  return "F3DEX2_MOVEWORD";
651 /*
652         F3DEX2_MTX              0xDA
653         S2DEX2_OBJ_RECTANGLE_R  0xDA
654 */
655         case 0xDA:
656         {
657             switch(ucode)
658             {
659                 case S2DEX2:        return "S2DEX2_OBJ_RECTANGLE_R";
660                 default:            return "F3DEX2_MTX";
661             }
662         }
663 //        F3DEX2_GEOMETRYMODE     0xD9
664         case 0xD9:                  return "F3DEX2_GEOMETRYMODE";
665 //        F3DEX2_POPMTX           0xD8
666         case 0xD8:                  return "F3DEX2_POPMTX";
667 //        F3DEX2_TEXTURE          0xD7
668         case 0xD7:                  return "F3DEX2_TEXTURE";
669 //        F3DEX2_DMA_IO           0xD6
670         case 0xD6:                  return "F3DEX2_DMA_IO";
671 //        F3DEX2_SPECIAL_1        0xD5
672         case 0xD5:                  return "F3DEX2_SPECIAL_1";
673 //        F3DEX2_SPECIAL_2        0xD4
674         case 0xD4:                  return "F3DEX2_SPECIAL_2";
675 //        F3DEX2_SPECIAL_3        0xD3
676         case 0xD3:                  return "F3DEX2_SPECIAL_3";
677
678 //        S2DEX_OBJ_LOADTXTR      0xC1
679         case 0xC1:                  return "S2DEX_OBJ_LOADTXTR";
680 //        S2DEX_OBJ_LDTX_SPRITE   0xC2
681         case 0xC2:                  return "S2DEX_OBJ_LDTX_SPRITE";
682 //        S2DEX_OBJ_LDTX_RECT     0xC3
683         case 0xC3:                  return "S2DEX_OBJ_LDTX_RECT";
684 //        S2DEX_OBJ_LDTX_RECT_R   0xC4
685         case 0xC4:                  return "S2DEX_OBJ_LDTX_RECT_R";
686 /*
687         F3D_TRI1:               0xBF
688         F3DDKR_DMA_OFFSETS      0xBF
689 */
690         case 0xBF:
691         {
692             switch(ucode)
693             {
694                 case F3DDKR:        return "F3DDKR_DMA_OFFSETS";
695                 default:            return "F3D_TRI1";
696             }
697         }
698
699 //        F3D_CULLDL:             0xBE
700         case 0xBE:                  return "F3D_CULLDL";
701 //        F3D_POPMTX:             0xBD
702         case 0xBD:                  return "F3D_POPMTX";
703 //        F3D_MOVEWORD:           0xBC
704         case 0xBC:                  return "F3D_MOVEWORD";
705 //        F3D_TEXTURE:            0xBB
706         case 0xBB:                  return "F3D_TEXTURE";
707 //        F3D_SETOTHERMODE_H:     0xBA
708         case 0xBA:                  return "F3D_SETOTHERMODE_H";
709 //        F3D_SETOTHERMODE_L:     0xB9
710         case 0xB9:                  return "F3D_SETOTHERMODE_L";
711 //        F3D_ENDDL:              0xB8
712         case 0xB8:                  return "F3D_ENDDL";
713 //        F3D_SETGEOMETRYMODE:    0xB7
714         case 0xB7:                  return "F3D_SETGEOMETRYMODE";
715 //        F3D_CLEARGEOMETRYMODE:  0xB6
716         case 0xB6:                  return "F3D_CLEARGEOMETRYMODE";
717 /*
718         F3D_QUAD:               0xB5
719         L3D_LINE3D              0xB5
720 */
721         case 0xB5:
722         {
723             switch(ucode)
724             {
725                 case L3D:           return "L3D_LINE3D";
726                 default:            return "F3D_QUAD";
727             }
728         }
729
730 //        F3D_RDPHALF_1:          0xB4
731         case 0xB4:                  return "F3D_RDPHALF_1";
732 //        F3D_RDPHALF_2:          0xB3
733         case 0xB3:                  return "F3D_RDPHALF_2";
734 /*
735         F3D_RDPHALF_CONT:       0xB2
736         F3DEX_MODIFYVTX         0xB2
737         S2DEX_OBJ_RECTANGLE_R   0xB2
738 */
739         case 0xB2:
740         {
741             switch(ucode)
742             {
743                 case F3DEX:         return "F3DEX_MODIFYVTX";
744                 case S2DEX:         return "S2DEX_OBJ_RECTANGLE_R";
745                 default:            return "F3D_RDPHALF_CONT";
746             }
747         }
748 /*
749         F3D_TRI4:               0xB1
750         F3DEX_TRI2              0xB1
751         F3DWRUS_TRI2            0xB1
752         S2DEX_OBJ_RENDERMODE    0xB1
753 */
754         case 0xB1:
755         {
756             switch(ucode)
757             {
758                 case F3DEX:         return "F3DEX_TRI2";
759                 case F3DWRUS:       return "F3DWRUS_TRI2";
760                 case S2DEX:         return "S2DEX_OBJ_RENDERMODE";
761                 default:            return "F3D_TRI4";
762             }
763         }
764 /*
765         F3DEX_BRANCH_Z          0xB0
766         S2DEX_SELECT_DL         0xB0
767 */
768         case 0xB0:
769         {
770             switch(ucode)
771             {
772                 case S2DEX:         return "S2DEX_SELECT_DL";
773                 default:            return "F3DEX_BRANCH_Z";
774             }
775         }
776 /*
777         F3DEX_LOAD_UCODE        0xAF
778         S2DEX_LOAD_UCODE        0xAF
779 */
780         case 0xAF:
781         {
782             switch(ucode)
783             {
784                 case S2DEX:         return "S2DEX_LOAD_UCODE";
785                 default:            return "F3DEX_LOAD_UCODE";
786             }
787         }
788
789         default:
790         {
791             if (ucode == F3DCBFD)
792             {
793                 if (cmd >= 0x10 && cmd <= 0x1f)
794                     return "F3DCBFD_TRI4";
795
796             }
797             return "UNKNOWN CMD";
798         }
799     }
800 }
801 #endif
802
803 MicrocodeInfo *GBI_DetectMicrocode( u32 uc_start, u32 uc_dstart, u16 uc_dsize )
804 {
805     MicrocodeInfo *current;
806
807     for (unsigned int i = 0; i < GBI.numMicrocodes; i++)
808     {
809         current = GBI.top;
810
811         while (current)
812         {
813             if ((current->address == uc_start) && (current->dataAddress == uc_dstart) && (current->dataSize == uc_dsize))
814                 return current;
815
816             current = current->lower;
817         }
818     }
819
820     current = GBI_AddMicrocode();
821
822     current->address = uc_start;
823     current->dataAddress = uc_dstart;
824     current->dataSize = uc_dsize;
825     current->NoN = FALSE;
826     current->type = NONE;
827
828     // See if we can identify it by CRC
829     uc_crc = CRC_Calculate( 0xFFFFFFFF, &RDRAM[uc_start & 0x1FFFFFFF], 4096);
830     LOG(LOG_MINIMAL, "UCODE CRC=0x%x\n", uc_crc);
831
832     for (u32 i = 0; i < sizeof( specialMicrocodes ) / sizeof( SpecialMicrocodeInfo ); i++)
833     {
834         if (uc_crc == specialMicrocodes[i].crc)
835         {
836             current->type = specialMicrocodes[i].type;
837             return current;
838         }
839     }
840
841     // See if we can identify it by text
842     char uc_data[2048];
843     UnswapCopy( &RDRAM[uc_dstart & 0x1FFFFFFF], uc_data, 2048 );
844     strcpy( uc_str, "Not Found" );
845
846     for (u32 i = 0; i < 2048; i++)
847     {
848         if ((uc_data[i] == 'R') && (uc_data[i+1] == 'S') && (uc_data[i+2] == 'P'))
849         {
850             u32 j = 0;
851             while (uc_data[i+j] > 0x0A)
852             {
853                 uc_str[j] = uc_data[i+j];
854                 j++;
855             }
856
857             uc_str[j] = 0x00;
858
859             int type = NONE;
860
861             if (strncmp( &uc_str[4], "SW", 2 ) == 0)
862             {
863                 type = F3D;
864             }
865             else if (strncmp( &uc_str[4], "Gfx", 3 ) == 0)
866             {
867                 current->NoN = (strncmp( &uc_str[20], ".NoN", 4 ) == 0);
868
869                 if (strncmp( &uc_str[14], "F3D", 3 ) == 0)
870                 {
871                     if (uc_str[28] == '1')
872                         type = F3DEX;
873                     else if (uc_str[31] == '2')
874                         type = F3DEX2;
875                 }
876                 else if (strncmp( &uc_str[14], "L3D", 3 ) == 0)
877                 {
878                     if (uc_str[28] == '1')
879                         type = L3DEX;
880                     else if (uc_str[31] == '2')
881                         type = L3DEX2;
882                 }
883                 else if (strncmp( &uc_str[14], "S2D", 3 ) == 0)
884                 {
885                     if (uc_str[28] == '1')
886                         type = S2DEX;
887                     else if (uc_str[31] == '2')
888                         type = S2DEX2;
889                 }
890             }
891
892             LOG(LOG_VERBOSE, "UCODE STRING=%s\n", uc_str);
893
894             if (type != NONE)
895             {
896                 current->type = type;
897                 return current;
898             }
899
900             break;
901         }
902     }
903
904
905     for (u32 i = 0; i < sizeof( specialMicrocodes ) / sizeof( SpecialMicrocodeInfo ); i++)
906     {
907         if (strcmp( uc_str, specialMicrocodes[i].text ) == 0)
908         {
909             current->type = specialMicrocodes[i].type;
910             return current;
911         }
912     }
913
914     // Let the user choose the microcode
915     LOG(LOG_ERROR, "[gles2n64]: Warning - unknown ucode!!!\n");
916     if(last_good_ucode != (u32)-1)
917     {
918         current->type=last_good_ucode;
919     }
920     else
921     {
922         current->type = MicrocodeDialog();
923     }
924     return current;
925 }
926
927 void GBI_MakeCurrent( MicrocodeInfo *current )
928 {
929     if (current != GBI.top)
930     {
931         if (current == GBI.bottom)
932         {
933             GBI.bottom = current->higher;
934             GBI.bottom->lower = NULL;
935         }
936         else
937         {
938             current->higher->lower = current->lower;
939             current->lower->higher = current->higher;
940         }
941
942         current->higher = NULL;
943         current->lower = GBI.top;
944         GBI.top->higher = current;
945         GBI.top = current;
946     }
947
948     if (!GBI.current || (GBI.current->type != current->type))
949     {
950
951         for (int i = 0; i <= 0xFF; i++)
952             GBI.cmd[i] = GBI_Unknown;
953
954         RDP_Init();
955         switch (current->type)
956         {
957             case F3D:       F3D_Init();     break;
958             case F3DEX:     F3DEX_Init();   break;
959             case F3DEX2:    F3DEX2_Init();  break;
960             case L3D:       L3D_Init();     break;
961             case L3DEX:     L3DEX_Init();   break;
962             case L3DEX2:    L3DEX2_Init();  break;
963             case S2DEX:     S2DEX_Init();   break;
964             case S2DEX2:    S2DEX2_Init();  break;
965             case F3DDKR:    F3DDKR_Init();  break;
966             case F3DWRUS:   F3DWRUS_Init(); break;
967             case F3DPD:     F3DPD_Init();   break;
968             case F3DCBFD:   F3DCBFD_Init(); break;
969         }
970     }
971
972
973     GBI.current = current;
974 }
975