34cf4058 |
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"}, |
1f4ee9e9 |
45 | {F3DCBFD, FALSE, 0x1b4ace88, "RSP Gfx ucode F3DEXBG.NoN fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo."}, |
34cf4058 |
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 | |