Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / Debugger.cpp
1 /*
2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002  Dave2001
4 * Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 //****************************************************************
22 //
23 // Glide64 - Glide Plugin for Nintendo 64 emulators
24 // Project started on December 29th, 2001
25 //
26 // Authors:
27 // Dave2001, original author, founded the project in 2001, left it in 2002
28 // Gugaman, joined the project in 2002, left it in 2002
29 // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
30 // Hiroshi 'KoolSmoky' Morii, joined the project in 2007
31 //
32 //****************************************************************
33 //
34 // To modify Glide64:
35 // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
36 // * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
37 //
38 //****************************************************************
39
40 #include "Gfx_1.3.h"
41 #include "Util.h"
42 #include "Debugger.h"
43
44 GLIDE64_DEBUGGER _debugger;
45
46 #define SX(x) ((x)*rdp.scale_1024)
47 #define SY(x) ((x)*rdp.scale_768)
48
49 #ifdef COLORED_DEBUGGER
50 #define COL_CATEGORY()  grConstantColorValue(0xD288F400)
51 #define COL_UCC()   grConstantColorValue(0xFF000000)
52 #define COL_CC()    grConstantColorValue(0x88C3F400)
53 #define COL_UAC()   grConstantColorValue(0xFF808000)
54 #define COL_AC()    grConstantColorValue(0x3CEE5E00)
55 #define COL_TEXT()    grConstantColorValue(0xFFFFFF00)
56 #define COL_SEL(x)    grConstantColorValue((x)?0x00FF00FF:0x800000FF)
57 #else
58 #define COL_CATEGORY()
59 #define COL_UCC()
60 #define COL_CC()
61 #define COL_UAC()
62 #define COL_AC()
63 #define COL_TEXT()
64 #define COL_SEL(x)
65 #endif
66
67 #define COL_GRID    0xFFFFFF80
68
69 int  grid = 0;
70 static const char *tri_type[4] = { "TRIANGLE", "TEXRECT", "FILLRECT", "BACKGROUND" };
71
72 //Platform-specific stuff
73 #ifndef WIN32
74 typedef struct dbgPOINT {
75    int x;
76    int y;
77 } POINT;
78 #endif
79 void DbgCursorPos(POINT * pt)
80 {
81 #ifdef __WINDOWS__
82   GetCursorPos (pt);
83 #else //!todo find a way to get cursor position on Unix
84   pt->x = pt->y = 0;
85 #endif
86 }
87
88 //
89 // debug_init - initialize the debugger
90 //
91
92 void debug_init ()
93 {
94   _debugger.capture = 0;
95   _debugger.selected = SELECTED_TRI;
96   _debugger.screen = NULL;
97   _debugger.tri_list = NULL;
98   _debugger.tri_last = NULL;
99   _debugger.tri_sel = NULL;
100   _debugger.tmu = 0;
101
102   _debugger.tex_scroll = 0;
103   _debugger.tex_sel = 0;
104
105   _debugger.draw_mode = 0;
106 }
107
108 //
109 // debug_cacheviewer - views the debugger's cache
110 //
111
112 void debug_cacheviewer ()
113 {
114   grCullMode (GR_CULL_DISABLE);
115
116   int i;
117   for (i=0; i<2; i++)
118   {
119     grTexFilterMode (i,
120       (settings.filter_cache)?GR_TEXTUREFILTER_BILINEAR:GR_TEXTUREFILTER_POINT_SAMPLED,
121       (settings.filter_cache)?GR_TEXTUREFILTER_BILINEAR:GR_TEXTUREFILTER_POINT_SAMPLED);
122     grTexClampMode (i,
123       GR_TEXTURECLAMP_CLAMP,
124       GR_TEXTURECLAMP_CLAMP);
125   }
126
127   switch (_debugger.draw_mode)
128   {
129   case 0:
130     grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
131       GR_COMBINE_FACTOR_ONE,
132       GR_COMBINE_LOCAL_NONE,
133       GR_COMBINE_OTHER_TEXTURE,
134       FXFALSE);
135     grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
136       GR_COMBINE_FACTOR_ONE,
137       GR_COMBINE_LOCAL_NONE,
138       GR_COMBINE_OTHER_TEXTURE,
139       FXFALSE);
140     break;
141   case 1:
142     grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
143       GR_COMBINE_FACTOR_ONE,
144       GR_COMBINE_LOCAL_NONE,
145       GR_COMBINE_OTHER_TEXTURE,
146       FXFALSE);
147     grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
148       GR_COMBINE_FACTOR_NONE,
149       GR_COMBINE_LOCAL_CONSTANT,
150       GR_COMBINE_OTHER_NONE,
151       FXFALSE);
152     grConstantColorValue (0xFFFFFFFF);
153     break;
154   case 2:
155     grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
156       GR_COMBINE_FACTOR_NONE,
157       GR_COMBINE_LOCAL_CONSTANT,
158       GR_COMBINE_OTHER_NONE,
159       FXFALSE);
160     grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
161       GR_COMBINE_FACTOR_ONE,
162       GR_COMBINE_LOCAL_NONE,
163       GR_COMBINE_OTHER_TEXTURE,
164       FXFALSE);
165     grConstantColorValue (0xFFFFFFFF);
166   }
167
168   if (_debugger.tmu == 1)
169   {
170     grTexCombine (GR_TMU1,
171       GR_COMBINE_FUNCTION_LOCAL,
172       GR_COMBINE_FACTOR_NONE,
173       GR_COMBINE_FUNCTION_LOCAL,
174       GR_COMBINE_FACTOR_NONE,
175       FXFALSE,
176       FXFALSE);
177
178     grTexCombine (GR_TMU0,
179       GR_COMBINE_FUNCTION_SCALE_OTHER,
180       GR_COMBINE_FACTOR_ONE,
181       GR_COMBINE_FUNCTION_SCALE_OTHER,
182       GR_COMBINE_FACTOR_ONE,
183       FXFALSE,
184       FXFALSE);
185   }
186   else
187   {
188     grTexCombine (GR_TMU0,
189       GR_COMBINE_FUNCTION_LOCAL,
190       GR_COMBINE_FACTOR_NONE,
191       GR_COMBINE_FUNCTION_LOCAL,
192       GR_COMBINE_FACTOR_NONE,
193       FXFALSE,
194       FXFALSE);
195   }
196
197   grAlphaBlendFunction (GR_BLEND_SRC_ALPHA,
198     GR_BLEND_ONE_MINUS_SRC_ALPHA,
199     GR_BLEND_ONE,
200     GR_BLEND_ZERO);
201
202   // Draw texture memory
203   for (i=0; i<4; i++)
204   {
205     for (wxUint32 x=0; x<16; x++)
206     {
207       wxUint32 y = i+_debugger.tex_scroll;
208       if (x+y*16 >= (wxUint32)rdp.n_cached[_debugger.tmu]) break;
209       CACHE_LUT * cache = voodoo.tex_UMA?rdp.cache[0]:rdp.cache[_debugger.tmu];
210
211       VERTEX v[4] = {
212           { SX(x*64.0f), SY(512+64.0f*i), 1, 1,       0, 0, 0, 0, {0, 0, 0, 0} },
213           { SX(x*64.0f+64.0f*cache[x+y*16].scale_x), SY(512+64.0f*i), 1, 1,    255*cache[x+y*16].scale_x, 0, 0, 0, {0, 0, 0, 0} },
214           { SX(x*64.0f), SY(512+64.0f*i+64.0f*cache[x+y*16].scale_y), 1, 1,    0, 255*cache[x+y*16].scale_y, 0, 0, {0, 0, 0, 0} },
215           { SX(x*64.0f+64.0f*cache[x+y*16].scale_x), SY(512+64.0f*i+64.0f*cache[x+y*16].scale_y), 1, 1, 255*cache[x+y*16].scale_x, 255*cache[x+y*16].scale_y, 0, 0, {0, 0, 0, 0} }
216           };
217       for
218       (int i=0; i<4; i++)
219       {
220         v[i].u1 = v[i].u0;
221         v[i].v1 = v[i].v0;
222       }
223
224       ConvertCoordsConvert (v, 4);
225
226       grTexSource(_debugger.tmu,
227         voodoo.tex_min_addr[_debugger.tmu] + cache[x+y*16].tmem_addr,
228         GR_MIPMAPLEVELMASK_BOTH,
229         &cache[x+y*16].t_info);
230
231       grDrawTriangle (&v[2], &v[1], &v[0]);
232       grDrawTriangle (&v[2], &v[3], &v[1]);
233     }
234   }
235
236 }
237
238 //
239 // debug_capture - does a frame capture event (for debugging)
240 //
241
242 void debug_capture ()
243 {
244   wxUint32 i,j;
245
246   if (_debugger.tri_list == NULL) goto END;
247   _debugger.tri_sel = _debugger.tri_list;
248   _debugger.selected = SELECTED_TRI;
249
250   // Connect the list
251   _debugger.tri_last->pNext = _debugger.tri_list;
252
253   while (!CheckKeyPressed(G64_VK_INSERT, 0x0001)) //INSERT
254   {
255     // Check for clicks
256     if (CheckKeyPressed(G64_VK_LBUTTON, 0x0001)) //LBUTTON
257     {
258       POINT pt;
259       DbgCursorPos(&pt);
260
261       //int diff = settings.scr_res_y-settings.res_y;
262
263       if (pt.y <= (int)settings.res_y)
264       {
265         int x = pt.x;
266         int y = pt.y;//settings.res_y - (pt.y - diff);
267
268         TRI_INFO *start;
269         TRI_INFO *tri;
270         if (_debugger.tri_sel == NULL) tri = _debugger.tri_list, start = _debugger.tri_list;
271         else tri = _debugger.tri_sel->pNext, start = _debugger.tri_sel;
272
273         // Select a triangle (start from the currently selected one)
274         do {
275           if (tri->v[0].x == tri->v[1].x &&
276             tri->v[0].y == tri->v[1].y)
277           {
278             tri = tri->pNext;
279             continue;
280           }
281
282           for (i=0; i<tri->nv; i++)
283           {
284             j=i+1;
285             if (j==tri->nv) j=0;
286
287             if ((y-tri->v[i].y)*(tri->v[j].x-tri->v[i].x) -
288               (x-tri->v[i].x)*(tri->v[j].y-tri->v[i].y) < 0)
289               break;    // It's outside
290           }
291
292           if (i==tri->nv) // all lines passed
293           {
294             _debugger.tri_sel = tri;
295             break;
296           }
297
298           for (i=0; i<tri->nv; i++)
299           {
300             j=i+1;
301             if (j==tri->nv) j=0;
302
303             if ((y-tri->v[i].y)*(tri->v[j].x-tri->v[i].x) -
304               (x-tri->v[i].x)*(tri->v[j].y-tri->v[i].y) > 0)
305               break;    // It's outside
306           }
307
308           if (i==tri->nv) // all lines passed
309           {
310             _debugger.tri_sel = tri;
311             break;
312           }
313
314           tri = tri->pNext;
315         } while (tri != start);
316       }
317       else
318       {
319         // on a texture
320         _debugger.tex_sel = (((wxUint32)((pt.y-SY(512))/SY(64))+_debugger.tex_scroll)*16) +
321           (wxUint32)(pt.x/SX(64));
322       }
323     }
324
325     debug_keys ();
326
327     grBufferClear (0, 0, 0xFFFF);
328
329     // Copy the screen capture back to the screen:
330     grLfbWriteRegion(GR_BUFFER_BACKBUFFER,
331       (wxUint32)rdp.offset_x,
332       (wxUint32)rdp.offset_y,
333       GR_LFB_SRC_FMT_565,
334       settings.res_x,
335       settings.res_y,
336       FXFALSE,
337       settings.res_x<<1,
338       _debugger.screen);
339
340     // Do the cacheviewer
341     debug_cacheviewer ();
342
343     // **
344     // 3/16/02: Moved texture viewer out of loop, remade it.  Now it's simpler, and
345     //   supports TMU1. [Dave2001]
346     // Original by Gugaman
347
348     CACHE_LUT * cache = voodoo.tex_UMA?rdp.cache[0]:rdp.cache[_debugger.tmu];
349     if (_debugger.page == PAGE_TEX_INFO)
350     {
351       grTexSource(_debugger.tmu,
352         voodoo.tex_min_addr[_debugger.tmu] + cache[_debugger.tex_sel].tmem_addr,
353         GR_MIPMAPLEVELMASK_BOTH,
354         &cache[_debugger.tex_sel].t_info);
355
356 #ifdef SHOW_FULL_TEXVIEWER
357       float scx = 1.0f;
358       float scy = 1.0f;
359 #else
360       float scx = cache[_debugger.tex_sel].scale_x;
361       float scy = cache[_debugger.tex_sel].scale_y;
362 #endif
363       VERTEX v[4] = {
364               { SX(704.0f), SY(221.0f), 1, 1, 0, 0,  0, 0, {0, 0, 0, 0} },
365               { SX(704.0f+256.0f*scx), SY(221.0f), 1, 1, 255*scx, 0, 255*scx, 0, {0, 0, 0, 0} },
366               { SX(704.0f), SY(221.0f+256.0f*scy), 1, 1, 0, 255*scy, 0, 255*scy, {0, 0, 0, 0} },
367               { SX(704.0f+256.0f*scx), SY(221.0f+256.0f*scy), 1, 1, 255*scx, 255*scy, 255*scx, 255*scy, {0, 0, 0, 0} }
368               };
369       ConvertCoordsConvert (v, 4);
370       VERTEX *varr[4] = { &v[0], &v[1], &v[2], &v[3] };
371       grDrawVertexArray (GR_TRIANGLE_STRIP, 4, varr);
372     }
373
374     // **
375
376     grTexFilterMode (GR_TMU0,
377       GR_TEXTUREFILTER_BILINEAR,
378       GR_TEXTUREFILTER_BILINEAR);
379
380     grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
381       GR_COMBINE_FACTOR_NONE,
382       GR_COMBINE_LOCAL_CONSTANT,
383       GR_COMBINE_OTHER_NONE,
384       FXFALSE);
385
386     grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
387       GR_COMBINE_FACTOR_NONE,
388       GR_COMBINE_LOCAL_CONSTANT,
389       GR_COMBINE_OTHER_NONE,
390       FXFALSE);
391
392     grConstantColorValue (0x0000FFFF);
393
394     VERTEX *v[8];
395     if (_debugger.tri_sel)
396     {
397       // Draw the outline around the selected triangle
398       for (i=0; i<_debugger.tri_sel->nv; i++)
399       {
400         j=i+1;
401         if (j>=_debugger.tri_sel->nv) j=0;
402
403         grDrawLine (&_debugger.tri_sel->v[i], &_debugger.tri_sel->v[j]);
404
405         v[i] = &_debugger.tri_sel->v[i];
406       }
407     }
408
409     // and the selected texture
410     wxUint32 t_y = ((_debugger.tex_sel & 0xFFFFFFF0) >> 4) - _debugger.tex_scroll;
411     wxUint32 t_x = _debugger.tex_sel & 0xF;
412     VERTEX vt[4] = {
413       { SX(t_x*64.0f), SY(512+64.0f*t_y), 1, 1 },
414       { SX(t_x*64.0f+64.0f), SY(512+64.0f*t_y), 1, 1 },
415       { SX(t_x*64.0f), SY(512+64.0f*t_y+64.0f), 1, 1 },
416       { SX(t_x*64.0f+64.0f), SY(512+64.0f*t_y+64.0f), 1, 1 } };
417     if (t_y < 4)
418     {
419       grDrawLine (&vt[0], &vt[1]);
420       grDrawLine (&vt[1], &vt[3]);
421       grDrawLine (&vt[3], &vt[2]);
422       grDrawLine (&vt[2], &vt[0]);
423     }
424
425     grConstantColorValue (0xFF000020);
426
427     if (t_y < 4)
428     {
429       grDrawTriangle (&vt[2], &vt[1], &vt[0]);
430       grDrawTriangle (&vt[2], &vt[3], &vt[1]);
431     }
432
433     if (_debugger.tri_sel)
434       grDrawVertexArray (GR_TRIANGLE_FAN, _debugger.tri_sel->nv, &v);
435
436     // Draw the outline of the cacheviewer
437     if (_debugger.page == PAGE_TEX_INFO)
438     {
439       float scx = cache[_debugger.tex_sel].scale_x;
440       float scy = cache[_debugger.tex_sel].scale_y;
441
442       // And the grid
443       if (grid)
444       {
445         grConstantColorValue (COL_GRID);
446
447         float scale_y = (256.0f * scy) / (float)cache[_debugger.tex_sel].height;
448         for (int y=0; y<=(int)cache[_debugger.tex_sel].height; y++)
449         {
450           float y_val = SY(221.0f+y*scale_y);
451           VERTEX vh[2] = {
452             { SX(704.0f), y_val, 1, 1 },
453             { SX(704.0f+255.0f*scx), y_val, 1, 1 } };
454           grDrawLine (&vh[0], &vh[1]);
455         }
456
457         float scale_x = (256.0f * scx) / (float)cache[_debugger.tex_sel].width;
458         for (int x=0; x<=(int)cache[_debugger.tex_sel].width; x++)
459         {
460           float x_val = SX(704.0f+x*scale_x);
461           VERTEX vv[2] = {
462             { x_val, SX(221.0f), 1, 1 },
463             { x_val, SX(221.0f+256.0f*scy), 1, 1 } };
464           grDrawLine (&vv[0], &vv[1]);
465         }
466       }
467     }
468
469     grTexCombine (GR_TMU0,
470         GR_COMBINE_FUNCTION_LOCAL,
471         GR_COMBINE_FACTOR_NONE,
472         GR_COMBINE_FUNCTION_LOCAL,
473         GR_COMBINE_FACTOR_NONE,
474         FXFALSE,
475         FXFALSE);
476
477     grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
478       GR_COMBINE_FACTOR_NONE,
479       GR_COMBINE_LOCAL_CONSTANT,
480       GR_COMBINE_OTHER_NONE,
481       FXFALSE);
482
483     grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
484       GR_COMBINE_FACTOR_ONE,
485       GR_COMBINE_LOCAL_NONE,
486       GR_COMBINE_OTHER_TEXTURE,
487       FXFALSE);
488
489     grConstantColorValue (0xFFFFFF00);
490
491     // Output the information about the selected triangle
492     grTexSource(GR_TMU0,      // Text
493       voodoo.tex_min_addr[_debugger.tmu]+ offset_font,
494       GR_MIPMAPLEVELMASK_BOTH,
495       &fontTex);
496
497     static const char *cycle_mode_s[4] = { "1 cycle (0)", "2 cycle (1)", "copy (2)", "fill (3)" };
498
499 #define OUTPUT(fmt,other) output(642,(float)i,1,fmt,other); i-=16;
500 #define OUTPUT1(fmt,other,other1) output(642,(float)i,1,fmt,other,other1); i-=16;
501 #define OUTPUT_(fmt,cc) COL_SEL(cc); x=642; output(x,(float)i,1,fmt,0); x+=8*(strlen(fmt)+1)
502 #define _OUTPUT(fmt,cc) COL_SEL(cc); output(x,(float)i,1,fmt,0); x+=8*(strlen(fmt)+1)
503     i = 740;
504     float x;
505     if (_debugger.page == PAGE_GENERAL && _debugger.tri_sel)
506     {
507       COL_CATEGORY();
508       OUTPUT ("GENERAL (page 1):",0);
509       COL_TEXT();
510       OUTPUT ("tri #%d", _debugger.tri_sel->tri_n);
511       OUTPUT ("type: %s", tri_type[_debugger.tri_sel->type]);
512       OUTPUT ("geom:   0x%08lx", _debugger.tri_sel->geom_mode);
513       OUTPUT ("othermode_h: 0x%08lx", _debugger.tri_sel->othermode_h);
514       OUTPUT ("othermode_l: 0x%08lx", _debugger.tri_sel->othermode_l);
515       OUTPUT ("flags: 0x%08lx", _debugger.tri_sel->flags);
516       OUTPUT ("",0);
517       COL_CATEGORY();
518       OUTPUT ("COMBINE:",0);
519       COL_TEXT();
520       OUTPUT ("cycle_mode: %s", cycle_mode_s[_debugger.tri_sel->cycle_mode]);
521       OUTPUT ("cycle1: 0x%08lx", _debugger.tri_sel->cycle1);
522       OUTPUT ("cycle2: 0x%08lx", _debugger.tri_sel->cycle2);
523       if (_debugger.tri_sel->uncombined & 1)
524         COL_UCC();
525       else
526         COL_CC();
527       OUTPUT ("a0: %s", Mode0[(_debugger.tri_sel->cycle1)&0x0000000F]);
528       OUTPUT ("b0: %s", Mode1[(_debugger.tri_sel->cycle1>>4)&0x0000000F]);
529       OUTPUT ("c0: %s", Mode2[(_debugger.tri_sel->cycle1>>8)&0x0000001F]);
530       OUTPUT ("d0: %s", Mode3[(_debugger.tri_sel->cycle1>>13)&0x00000007]);
531       if (_debugger.tri_sel->uncombined & 2)
532         COL_UAC();
533       else
534         COL_AC();
535       OUTPUT ("Aa0: %s", Alpha0[(_debugger.tri_sel->cycle1>>16)&0x00000007]);
536       OUTPUT ("Ab0: %s", Alpha1[(_debugger.tri_sel->cycle1>>19)&0x00000007]);
537       OUTPUT ("Ac0: %s", Alpha2[(_debugger.tri_sel->cycle1>>22)&0x00000007]);
538       OUTPUT ("Ad0: %s", Alpha3[(_debugger.tri_sel->cycle1>>25)&0x00000007]);
539       if (_debugger.tri_sel->uncombined & 1)
540         COL_UCC();
541       else
542         COL_CC();
543       OUTPUT ("a1: %s", Mode0[(_debugger.tri_sel->cycle2)&0x0000000F]);
544       OUTPUT ("b1: %s", Mode1[(_debugger.tri_sel->cycle2>>4)&0x0000000F]);
545       OUTPUT ("c1: %s", Mode2[(_debugger.tri_sel->cycle2>>8)&0x0000001F]);
546       OUTPUT ("d1: %s", Mode3[(_debugger.tri_sel->cycle2>>13)&0x00000007]);
547       if (_debugger.tri_sel->uncombined & 2)
548         COL_UAC();
549       else
550         COL_AC();
551       OUTPUT ("Aa1: %s", Alpha0[(_debugger.tri_sel->cycle2>>16)&0x00000007]);
552       OUTPUT ("Ab1: %s", Alpha1[(_debugger.tri_sel->cycle2>>19)&0x00000007]);
553       OUTPUT ("Ac1: %s", Alpha2[(_debugger.tri_sel->cycle2>>22)&0x00000007]);
554       OUTPUT ("Ad1: %s", Alpha3[(_debugger.tri_sel->cycle2>>25)&0x00000007]);
555     }
556     if ((_debugger.page == PAGE_TEX1 || _debugger.page == PAGE_TEX2) && _debugger.tri_sel)
557     {
558       COL_CATEGORY ();
559       OUTPUT1 ("TEXTURE %d (page %d):", _debugger.page-PAGE_TEX1, 2+_debugger.page-PAGE_TEX1);
560       COL_TEXT();
561       int tmu = _debugger.page - PAGE_TEX1;
562       OUTPUT1 ("cur cache: %d,%d", _debugger.tri_sel->t[tmu].cur_cache[tmu]&0x0F, _debugger.tri_sel->t[tmu].cur_cache[tmu]>>4);
563       OUTPUT ("tex_size: %d", _debugger.tri_sel->t[tmu].size);
564       OUTPUT ("tex_format: %d", _debugger.tri_sel->t[tmu].format);
565       OUTPUT ("width: %d", _debugger.tri_sel->t[tmu].width);
566       OUTPUT ("height: %d", _debugger.tri_sel->t[tmu].height);
567       OUTPUT ("palette: %d", _debugger.tri_sel->t[tmu].palette);
568       OUTPUT ("clamp_s: %d", _debugger.tri_sel->t[tmu].clamp_s);
569       OUTPUT ("clamp_t: %d", _debugger.tri_sel->t[tmu].clamp_t);
570       OUTPUT ("mirror_s: %d", _debugger.tri_sel->t[tmu].mirror_s);
571       OUTPUT ("mirror_t: %d", _debugger.tri_sel->t[tmu].mirror_t);
572       OUTPUT ("mask_s: %d", _debugger.tri_sel->t[tmu].mask_s);
573       OUTPUT ("mask_t: %d", _debugger.tri_sel->t[tmu].mask_t);
574       OUTPUT ("shift_s: %d", _debugger.tri_sel->t[tmu].shift_s);
575       OUTPUT ("shift_t: %d", _debugger.tri_sel->t[tmu].shift_t);
576       OUTPUT ("ul_s: %d", _debugger.tri_sel->t[tmu].ul_s);
577       OUTPUT ("ul_t: %d", _debugger.tri_sel->t[tmu].ul_t);
578       OUTPUT ("lr_s: %d", _debugger.tri_sel->t[tmu].lr_s);
579       OUTPUT ("lr_t: %d", _debugger.tri_sel->t[tmu].lr_t);
580       OUTPUT ("t_ul_s: %d", _debugger.tri_sel->t[tmu].t_ul_s);
581       OUTPUT ("t_ul_t: %d", _debugger.tri_sel->t[tmu].t_ul_t);
582       OUTPUT ("t_lr_s: %d", _debugger.tri_sel->t[tmu].t_lr_s);
583       OUTPUT ("t_lr_t: %d", _debugger.tri_sel->t[tmu].t_lr_t);
584       OUTPUT ("scale_s: %f", _debugger.tri_sel->t[tmu].scale_s);
585       OUTPUT ("scale_t: %f", _debugger.tri_sel->t[tmu].scale_t);
586       OUTPUT ("s_mode: %s", str_cm[((_debugger.tri_sel->t[tmu].clamp_s << 1) | _debugger.tri_sel->t[tmu].mirror_s)&3]);
587       OUTPUT ("t_mode: %s", str_cm[((_debugger.tri_sel->t[tmu].clamp_t << 1) | _debugger.tri_sel->t[tmu].mirror_t)&3]);
588     }
589     if (_debugger.page == PAGE_COLORS && _debugger.tri_sel)
590     {
591       COL_CATEGORY();
592       OUTPUT ("COLORS (page 4)", 0);
593       COL_TEXT();
594       OUTPUT ("fill:  %08lx", _debugger.tri_sel->fill_color);
595       OUTPUT ("prim:  %08lx", _debugger.tri_sel->prim_color);
596       OUTPUT ("blend: %08lx", _debugger.tri_sel->blend_color);
597       OUTPUT ("env:   %08lx", _debugger.tri_sel->env_color);
598       OUTPUT ("fog: %08lx", _debugger.tri_sel->fog_color);
599       OUTPUT ("prim_lodmin:  %d", _debugger.tri_sel->prim_lodmin);
600       OUTPUT ("prim_lodfrac: %d", _debugger.tri_sel->prim_lodfrac);
601     }
602     if (_debugger.page == PAGE_FBL && _debugger.tri_sel)
603     {
604       COL_CATEGORY();
605       OUTPUT ("BLENDER", 0);
606       COL_TEXT();
607       OUTPUT ("fbl_a0: %s", FBLa[(_debugger.tri_sel->othermode_l>>30)&0x3]);
608       OUTPUT ("fbl_b0: %s", FBLb[(_debugger.tri_sel->othermode_l>>26)&0x3]);
609       OUTPUT ("fbl_c0: %s", FBLc[(_debugger.tri_sel->othermode_l>>22)&0x3]);
610       OUTPUT ("fbl_d0: %s", FBLd[(_debugger.tri_sel->othermode_l>>18)&0x3]);
611       OUTPUT ("fbl_a1: %s", FBLa[(_debugger.tri_sel->othermode_l>>28)&0x3]);
612       OUTPUT ("fbl_b1: %s", FBLb[(_debugger.tri_sel->othermode_l>>24)&0x3]);
613       OUTPUT ("fbl_c1: %s", FBLc[(_debugger.tri_sel->othermode_l>>20)&0x3]);
614       OUTPUT ("fbl_d1: %s", FBLd[(_debugger.tri_sel->othermode_l>>16)&0x3]);
615       OUTPUT ("", 0);
616       OUTPUT ("fbl:    %08lx", _debugger.tri_sel->othermode_l&0xFFFF0000);
617       OUTPUT ("fbl #1: %08lx", _debugger.tri_sel->othermode_l&0xCCCC0000);
618       OUTPUT ("fbl #2: %08lx", _debugger.tri_sel->othermode_l&0x33330000);
619     }
620     if (_debugger.page == PAGE_OTHERMODE_L && _debugger.tri_sel)
621     {
622       wxUint32 othermode_l = _debugger.tri_sel->othermode_l;
623       COL_CATEGORY ();
624       OUTPUT ("OTHERMODE_L: %08lx", othermode_l);
625       OUTPUT_ ("AC_NONE", (othermode_l & 3) == 0);
626       _OUTPUT ("AC_THRESHOLD", (othermode_l & 3) == 1);
627       _OUTPUT ("AC_DITHER", (othermode_l & 3) == 3);
628       i -= 16;
629       OUTPUT_ ("ZS_PIXEL", !(othermode_l & 4));
630       _OUTPUT ("ZS_PRIM", (othermode_l & 4));
631       i -= 32;
632       COL_CATEGORY ();
633       OUTPUT ("RENDERMODE: %08lx", othermode_l);
634       OUTPUT_ ("AA_EN", othermode_l & 0x08);
635       i -= 16;
636       OUTPUT_ ("Z_CMP", othermode_l & 0x10);
637       i -= 16;
638       OUTPUT_ ("Z_UPD", othermode_l & 0x20);
639       i -= 16;
640       OUTPUT_ ("IM_RD", othermode_l & 0x40);
641       i -= 16;
642       OUTPUT_ ("CLR_ON_CVG", othermode_l & 0x80);
643       i -= 16;
644       OUTPUT_ ("CVG_DST_CLAMP", (othermode_l & 0x300) == 0x000);
645       _OUTPUT ("CVG_DST_WRAP", (othermode_l & 0x300) == 0x100);
646       _OUTPUT (".._FULL", (othermode_l & 0x300) == 0x200);
647       _OUTPUT (".._SAVE", (othermode_l & 0x300) == 0x300);
648       i -= 16;
649       OUTPUT_ ("ZM_OPA", (othermode_l & 0xC00) == 0x000);
650       _OUTPUT ("ZM_INTER", (othermode_l & 0xC00) == 0x400);
651       _OUTPUT ("ZM_XLU", (othermode_l & 0xC00) == 0x800);
652       _OUTPUT ("ZM_DEC", (othermode_l & 0xC00) == 0xC00);
653       i -= 16;
654       OUTPUT_ ("CVG_X_ALPHA", othermode_l & 0x1000);
655       i -= 16;
656       OUTPUT_ ("ALPHA_CVG_SEL", othermode_l & 0x2000);
657       i -= 16;
658       OUTPUT_ ("FORCE_BL", othermode_l & 0x4000);
659     }
660     if (_debugger.page == PAGE_OTHERMODE_H && _debugger.tri_sel)
661     {
662       wxUint32 othermode_h = _debugger.tri_sel->othermode_h;
663       COL_CATEGORY ();
664       OUTPUT ("OTHERMODE_H: %08lx", othermode_h);
665       OUTPUT_ ("CK_NONE", (othermode_h & 0x100) == 0);
666       _OUTPUT ("CK_KEY", (othermode_h & 0x100) == 1);
667       i -= 16;
668       OUTPUT_  ("TC_CONV", (othermode_h & 0xE00) == 0x200);
669       _OUTPUT ("TC_FILTCONV", (othermode_h & 0xE00) == 0xA00);
670       _OUTPUT ("TC_FILT", (othermode_h & 0xE00) == 0xC00);
671       i -= 16;
672       OUTPUT_ ("TF_POINT", (othermode_h & 0x3000) == 0x0000);
673       _OUTPUT ("TF_AVERAGE", (othermode_h & 0x3000) == 0x3000);
674       _OUTPUT ("TF_BILERP", (othermode_h & 0x3000) == 0x2000);
675       i -= 16;
676       OUTPUT_ ("TT_NONE", (othermode_h & 0xC000) == 0x0000);
677       _OUTPUT ("TT_RGBA16", (othermode_h & 0xC000) == 0x8000);
678       _OUTPUT ("TT_IA16", (othermode_h & 0xC000) == 0xC000);
679       i -= 16;
680       OUTPUT_ ("TL_TILE", (othermode_h & 0x10000) == 0x00000);
681       _OUTPUT ("TL_LOD", (othermode_h & 0x10000) == 0x10000);
682       i -= 16;
683       OUTPUT_ ("TD_CLAMP", (othermode_h & 0x60000) == 0x00000);
684       _OUTPUT ("TD_SHARPEN", (othermode_h & 0x60000) == 0x20000);
685       _OUTPUT ("TD_DETAIL", (othermode_h & 0x60000) == 0x40000);
686       i -= 16;
687       OUTPUT_ ("TP_NONE", (othermode_h & 0x80000) == 0x00000);
688       _OUTPUT ("TP_PERSP", (othermode_h & 0x80000) == 0x80000);
689       i -= 16;
690       OUTPUT_ ("1CYCLE", (othermode_h & 0x300000) == 0x000000);
691       _OUTPUT ("2CYCLE", (othermode_h & 0x300000) == 0x100000);
692       _OUTPUT ("COPY", (othermode_h & 0x300000) == 0x200000);
693       _OUTPUT ("FILL", (othermode_h & 0x300000) == 0x300000);
694       i -= 16;
695       OUTPUT_ ("PM_1PRIM", (othermode_h & 0x400000) == 0x000000);
696       _OUTPUT ("PM_NPRIM", (othermode_h & 0x400000) == 0x400000);
697     }
698     if (_debugger.page == PAGE_TEXELS && _debugger.tri_sel)
699     {
700       // change these to output whatever you need, ou for triangles, or u0 for texrects
701       COL_TEXT();
702       OUTPUT ("n: %d", _debugger.tri_sel->nv);
703       OUTPUT ("",0);
704       for (j=0; j<_debugger.tri_sel->nv; j++)
705       {
706         OUTPUT1 ("v[%d].s0: %f", j, _debugger.tri_sel->v[j].ou);
707         OUTPUT1 ("v[%d].t0: %f", j, _debugger.tri_sel->v[j].ov);
708       }
709       OUTPUT ("",0);
710       for (j=0; j<_debugger.tri_sel->nv; j++)
711       {
712         OUTPUT1 ("v[%d].s1: %f", j, _debugger.tri_sel->v[j].u0);
713         OUTPUT1 ("v[%d].t1: %f", j, _debugger.tri_sel->v[j].v0);
714       }
715     }
716     if (_debugger.page == PAGE_COORDS && _debugger.tri_sel)
717     {
718       COL_TEXT();
719       OUTPUT ("n: %d", _debugger.tri_sel->nv);
720       for (j=0; j<_debugger.tri_sel->nv; j++)
721       {
722         OUTPUT1 ("v[%d].x: %f", j, _debugger.tri_sel->v[j].x);
723         OUTPUT1 ("v[%d].y: %f", j, _debugger.tri_sel->v[j].y);
724         OUTPUT1 ("v[%d].z: %f", j, _debugger.tri_sel->v[j].z);
725         OUTPUT1 ("v[%d].w: %f", j, _debugger.tri_sel->v[j].w);
726         OUTPUT1 ("v[%d].f: %f", j, 1.0f/_debugger.tri_sel->v[j].f);
727         OUTPUT1 ("v[%d].r: %d", j, _debugger.tri_sel->v[j].r);
728         OUTPUT1 ("v[%d].g: %d", j, _debugger.tri_sel->v[j].g);
729         OUTPUT1 ("v[%d].b: %d", j, _debugger.tri_sel->v[j].b);
730         OUTPUT1 ("v[%d].a: %d", j, _debugger.tri_sel->v[j].a);
731       }
732     }
733     if (_debugger.page == PAGE_TEX_INFO && _debugger.tex_sel < (wxUint32)rdp.n_cached[_debugger.tmu])
734     {
735       COL_CATEGORY();
736       OUTPUT ("CACHE (page 0)", 0);
737       COL_TEXT();
738       //OUTPUT ("t_mem: %08lx", rdp.cache[0][_debugger.tex_sel].t_mem);
739       //OUTPUT ("crc: %08lx", rdp.cache[0][_debugger.tex_sel].crc);
740       OUTPUT ("addr: %08lx", cache[_debugger.tex_sel].addr);
741       OUTPUT ("scale_x: %f", cache[_debugger.tex_sel].scale_x);
742       OUTPUT ("scale_y: %f", cache[_debugger.tex_sel].scale_y);
743       OUTPUT ("tmem_addr: %08lx", cache[_debugger.tex_sel].tmem_addr);
744       OUTPUT ("palette: %08lx", cache[_debugger.tex_sel].palette);
745       OUTPUT ("set_by: %08lx", cache[_debugger.tex_sel].set_by);
746       OUTPUT ("texrecting: %d", cache[_debugger.tex_sel].texrecting);
747
748       OUTPUT ("mod: %08lx", cache[_debugger.tex_sel].mod);
749       OUTPUT ("mod_col: %08lx", cache[_debugger.tex_sel].mod_color);
750       OUTPUT ("mod_col1: %08lx", cache[_debugger.tex_sel].mod_color1);
751       i=740;
752       output(800,(float)i,1,"width: %d", cache[_debugger.tex_sel].width);
753       i-=16;
754       output(800,(float)i,1,"height: %d", cache[_debugger.tex_sel].height);
755       i-=16;
756       output(800,(float)i,1,"format: %d", cache[_debugger.tex_sel].format);
757       i-=16;
758       output(800,(float)i,1,"size: %d", cache[_debugger.tex_sel].size);
759       i-=16;
760       output(800,(float)i,1,"crc: %08lx", cache[_debugger.tex_sel].crc);
761       i-=16;
762 #ifdef TEXTURE_FILTER
763       output(800,(float)i,1,"RiceCrc: %08lx", (wxUint32)(rdp.cache[_debugger.tmu][_debugger.tex_sel].ricecrc&0xFFFFFFFF));
764       i-=16;
765       output(800,(float)i,1,"RicePalCrc: %08lx", (wxUint32)(rdp.cache[_debugger.tmu][_debugger.tex_sel].ricecrc>>32));
766       i-=16;
767 #endif
768       output(800,(float)i,1,"flags: %08lx", cache[_debugger.tex_sel].flags);
769       i-=16;
770       output(800,(float)i,1,"line: %d", cache[_debugger.tex_sel].line);
771       i-=16;
772       output(800,(float)i,1,"mod_factor: %08lx", cache[_debugger.tex_sel].mod_factor);
773       i-=32;
774
775       output(800,(float)i,1,"lod: %s", str_lod[cache[_debugger.tex_sel].lod]);
776       i-=16;
777       output(800,(float)i,1,"aspect: %s", str_aspect[cache[_debugger.tex_sel].aspect + 3]);
778
779 //  debug_texture(_debugger.tmu, cache[_debugger.tex_sel].addr, _debugger.tex_sel);
780     }
781
782     // Draw the vertex numbers
783     if (_debugger.tri_sel)
784     {
785       for (i=0; i<_debugger.tri_sel->nv; i++)
786       {
787         grConstantColorValue (0x000000FF);
788         output (_debugger.tri_sel->v[i].x+1, settings.scr_res_y-_debugger.tri_sel->v[i].y+1, 1,
789           "%d", i);
790         grConstantColorValue (0xFFFFFFFF);
791         output (_debugger.tri_sel->v[i].x, settings.scr_res_y-_debugger.tri_sel->v[i].y, 1,
792           "%d", i);
793       }
794     }
795
796     // Draw the cursor
797     debug_mouse ();
798
799     grBufferSwap (1);
800   }
801
802 END:
803   // Release all data
804   delete [] _debugger.screen;
805   TRI_INFO *tri;
806   for (tri=_debugger.tri_list; tri != _debugger.tri_last;)
807   {
808     TRI_INFO *tmp = tri;
809     tri = tri->pNext;
810     delete [] tmp->v;
811     delete tmp;
812   }
813   delete [] tri->v;
814   delete tri;
815
816   // Reset all values
817   _debugger.capture = 0;
818   _debugger.selected = SELECTED_TRI;
819   _debugger.screen = NULL;
820   _debugger.tri_list = NULL;
821   _debugger.tri_last = NULL;
822   _debugger.tri_sel = NULL;
823   _debugger.tex_sel = 0;
824 }
825
826 //
827 // debug_mouse - draws the debugger mouse
828 //
829
830 void debug_mouse ()
831 {
832   grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
833     GR_COMBINE_FACTOR_ONE,
834     GR_COMBINE_LOCAL_NONE,
835     GR_COMBINE_OTHER_TEXTURE,
836     FXFALSE);
837
838   grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
839     GR_COMBINE_FACTOR_ONE,
840     GR_COMBINE_LOCAL_NONE,
841     GR_COMBINE_OTHER_TEXTURE,
842     FXFALSE);
843
844   // Draw the cursor
845   POINT pt;
846   DbgCursorPos(&pt);
847   float cx = (float)pt.x;
848   float cy = (float)pt.y;
849
850   VERTEX v[4] = {
851     { cx,       cy, 1, 1,   0,   0,   0, 0, {0, 0, 0, 0} },
852     { cx+32,    cy, 1, 1, 255,   0,   0, 0, {0, 0, 0, 0} },
853     { cx,    cy+32, 1, 1,   0, 255,   0, 0, {0, 0, 0, 0} },
854     { cx+32, cy+32, 1, 1, 255, 255,   0, 0, {0, 0, 0, 0} }
855     };
856
857   ConvertCoordsKeep (v, 4);
858
859   grTexSource(GR_TMU0,
860     voodoo.tex_min_addr[GR_TMU0] + offset_cursor,
861     GR_MIPMAPLEVELMASK_BOTH,
862     &cursorTex);
863
864   if (voodoo.num_tmu >= 3)
865     grTexCombine (GR_TMU2,
866       GR_COMBINE_FUNCTION_NONE,
867       GR_COMBINE_FACTOR_NONE,
868       GR_COMBINE_FUNCTION_NONE,
869       GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE);
870   if (voodoo.num_tmu >= 2)
871     grTexCombine (GR_TMU1,
872       GR_COMBINE_FUNCTION_NONE,
873       GR_COMBINE_FACTOR_NONE,
874       GR_COMBINE_FUNCTION_NONE,
875       GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE);
876   grTexCombine (GR_TMU0,
877     GR_COMBINE_FUNCTION_LOCAL,
878     GR_COMBINE_FACTOR_NONE,
879     GR_COMBINE_FUNCTION_LOCAL,
880     GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE);
881
882   grDrawTriangle (&v[0], &v[1], &v[2]);
883   grDrawTriangle (&v[1], &v[3], &v[2]);
884 }
885
886 //
887 // debug_keys - receives debugger key input
888 //
889
890 void debug_keys ()
891 {
892   if (CheckKeyPressed(G64_VK_RIGHT, 0x0001) && _debugger.tri_sel)
893   {
894     TRI_INFO *start = _debugger.tri_sel;
895
896     while (_debugger.tri_sel->pNext != start)
897       _debugger.tri_sel = _debugger.tri_sel->pNext;
898   }
899
900   if (CheckKeyPressed(G64_VK_LEFT, 0x0001) && _debugger.tri_sel)
901     _debugger.tri_sel = _debugger.tri_sel->pNext;
902
903   // Check for page changes
904   if (CheckKeyPressed(G64_VK_1, 0x0001))
905     _debugger.page = PAGE_GENERAL;
906   if (CheckKeyPressed(G64_VK_2, 0x0001))
907     _debugger.page = PAGE_TEX1;
908   if (CheckKeyPressed(G64_VK_3, 0x0001))
909     _debugger.page = PAGE_TEX2;
910   if (CheckKeyPressed(G64_VK_4, 0x0001))
911     _debugger.page = PAGE_COLORS;
912   if (CheckKeyPressed(G64_VK_5, 0x0001))
913     _debugger.page = PAGE_FBL;
914   if (CheckKeyPressed(G64_VK_6, 0x0001))
915     _debugger.page = PAGE_OTHERMODE_L;
916   if (CheckKeyPressed(G64_VK_7, 0x0001))
917     _debugger.page = PAGE_OTHERMODE_H;
918   if (CheckKeyPressed(G64_VK_8, 0x0001))
919     _debugger.page = PAGE_TEXELS;
920   if (CheckKeyPressed(G64_VK_9, 0x0001))
921     _debugger.page = PAGE_COORDS;
922   if (CheckKeyPressed(G64_VK_0, 0x0001))
923     _debugger.page = PAGE_TEX_INFO;
924   if (CheckKeyPressed(G64_VK_Q, 0x0001))
925     _debugger.tmu = 0;
926   if (CheckKeyPressed(G64_VK_W, 0x0001))
927     _debugger.tmu = 1;
928
929   if (CheckKeyPressed(G64_VK_G, 0x0001))
930     grid = !grid;
931
932   // Go to texture
933   if (CheckKeyPressed(G64_VK_SPACE, 0x0001))
934   {
935     int tile = -1;
936     if (_debugger.page == PAGE_TEX2)
937       tile = 1;
938     else
939       tile = 0;
940     if (tile != -1)
941     {
942       _debugger.tmu = _debugger.tri_sel->t[tile].tmu;
943       _debugger.tex_sel = _debugger.tri_sel->t[tile].cur_cache[_debugger.tmu];
944       _debugger.tex_scroll = (_debugger.tri_sel->t[tile].cur_cache[_debugger.tmu] >> 4) - 1;
945     }
946   }
947
948   // Go to triangle
949   CACHE_LUT * cache = voodoo.tex_UMA?rdp.cache[0]:rdp.cache[_debugger.tmu];
950   if (CheckKeyPressed(G64_VK_CONTROL, 0x0001))
951   {
952     int count = rdp.debug_n - cache[_debugger.tex_sel].uses - 1;
953     if (cache[_debugger.tex_sel].last_used == frame_count)
954     {
955       TRI_INFO *t = _debugger.tri_list;
956       while (count && t) {
957         t = t->pNext;
958         count --;
959       }
960       _debugger.tri_sel = t;
961     }
962     else
963       _debugger.tri_sel = NULL;
964   }
965
966   if (CheckKeyPressed(G64_VK_A, 0x0001))
967     _debugger.draw_mode = 0;  // texture & texture alpha
968   if (CheckKeyPressed(G64_VK_S, 0x0001))
969     _debugger.draw_mode = 1;  // texture
970   if (CheckKeyPressed(G64_VK_D, 0x0001))
971     _debugger.draw_mode = 2;  // texture alpha
972
973   // Check for texture scrolling
974   if (CheckKeyPressed(G64_VK_DOWN, 0x0001))
975     _debugger.tex_scroll ++;
976   if (CheckKeyPressed(G64_VK_UP, 0x0001))
977     _debugger.tex_scroll --;
978 }
979
980 //
981 // output - output debugger text
982 //
983
984 void output (float x, float y, int scale, const char *fmt, ...)
985 {
986   va_list ap;
987   va_start(ap,fmt);
988   vsprintf(out_buf, fmt, ap);
989   va_end(ap);
990
991   wxUint8 c,r;
992   for (wxUint32 i=0; i<strlen(out_buf); i++)
993   {
994     c = ((out_buf[i]-32) & 0x1F) * 8;//<< 3;
995     r = (((out_buf[i]-32) & 0xE0) >> 5) * 16;//<< 4;
996     VERTEX v[4] = { { SX(x), SY(768-y), 1, 1,   (float)c, r+16.0f, 0, 0, {0, 0, 0, 0} },
997       { SX(x+8), SY(768-y), 1, 1,   c+8.0f, r+16.0f, 0, 0, {0, 0, 0, 0} },
998       { SX(x), SY(768-y-16), 1, 1,  (float)c, (float)r, 0, 0, {0, 0, 0, 0} },
999       { SX(x+8), SY(768-y-16), 1, 1,  c+8.0f, (float)r, 0, 0, {0, 0, 0, 0} }
1000       };
1001     if (!scale)
1002     {
1003       v[0].x = x;
1004       v[0].y = y;
1005       v[1].x = x+8;
1006       v[1].y = y;
1007       v[2].x = x;
1008       v[2].y = y-16;
1009       v[3].x = x+8;
1010       v[3].y = y-16;
1011     }
1012
1013     ConvertCoordsKeep (v, 4);
1014
1015     grDrawTriangle (&v[0], &v[1], &v[2]);
1016     grDrawTriangle (&v[1], &v[3], &v[2]);
1017
1018     x+=8;
1019   }
1020 }