1: /*
     2:  *  Guitar-ZyX(tm)::MasterControlProgram - portable guitar F/X controller
     3:  *  Copyright (C) 2009  Douglas McClendon
     4:  *
     5:  *  This program is free software: you can redistribute it and/or modify
     6:  *  it under the terms of the GNU General Public License as published by
     7:  *  the Free Software Foundation, version 3 of the License.
     8:  *
     9:  *  This program is distributed in the hope that it will be useful,
    10:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    11:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12:  *  GNU General Public License for more details.
    13:  *
    14:  *  You should have received a copy of the GNU General Public License
    15:  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16: */
    17: /*
    18: #############################################################################
    19: #############################################################################
    20: ## 
    21: ## gzmcpc::graphics: visual output rendering
    22: ##
    23: #############################################################################
    24: ##
    25: ## Copyright 2008-2009 Douglas McClendon <dmc AT filteredperception DOT org>
    26: ##
    27: #############################################################################
    28: #############################################################################
    29: #
    30: */
    31: 
    32: 
    33: 
    34: 
    35: #include <nds.h> 
    36: 
    37: #include <stdio.h> 
    38: 
    39: #include <stdarg.h> 
    40: 
    41: #include <math.h>  
    42: 
    43: 
    44: #include "graphics.h" 
    45: 
    46: #include "debug.h" 
    47: 
    48: #include "input.h" 
    49: 
    50: #include "mcp.h" 
    51: 
    52: #include "modes.h" 
    53: 
    54: #include "mode__tpw__jam.h" 
    55: 
    56: #include "network.h" 
    57: 
    58: #include "sound.h" 
    59: 
    60: #include "time.h" 
    61: 
    62: 
    63: #include "sounds.h" 
    64: 
    65: #include "sounds_bin.h" 
    66: 
    67: 
    68: 
    69: 
    70: char text_output_line[TLT_NUM_TEXT_OUTPUT_LINE_TYPES][MAX_TEXT_OUTPUT_LINE_SIZE];
    71: 
    72: float cursor_rotation = 0.0f;
    73: 
    74: float cursor_intensity = DEFAULT_CURSOR_INTESITY;
    75: 
    76: v16 touch_pos_x = 128;
    77: v16 touch_pos_y = 96;
    78: 
    79: int cursor_rotating = 1;
    80: 
    81: unsigned char font_intensity = DEFAULT_FONT_INTENSITY;
    82: 
    83: PrintConsole top_screen;
    84: PrintConsole bottom_screen;
    85: PrintConsole top_screen_x;
    86: PrintConsole bottom_screen_x;
    87: 
    88: Keyboard keyboard;
    89: 
    90: float sqrt_three;
    91: 
    92: unsigned char top_render_rate = DEFAULT_TOP_RENDER_RATE;
    93: unsigned char bottom_render_rate = DEFAULT_BOTTOM_RENDER_RATE;
    94: time_val next_top_render = {0, 0};
    95: time_val next_bottom_render = {0, 0};
    96: 
    97: int bg0, bg1, bg2, bg3;
    98: int bgs0, bgs1, bgs2, bgs3;
    99: 
   100: 
   101: 
   102: 
   103: 
   104: 
   105: void gzmcpc_init_3d(void) {
   106: 
   107:   int i, j;
   108: 
   109:   // initialize openGL-ish 3d engine
   110:   glInit();
   111:   
   112:   // initialize comb charge matrix
   113:   for (i = 0; i < COMB_WIDTH ; i++) { 
   114:     for (j = 0; j < COMB_WIDTH ; j++) { 
   115:       comb_charge[i][j] = 0;
   116:     }
   117:   }
   118: 
   119:   // single value lut
   120:   sqrt_three=sqrtf(3.0f);
   121:   
   122:   // enable antialiasing
   123:   glEnable(GL_ANTIALIAS);
   124:   
   125:   // background must be opaque for antialiasing 
   126:   glClearColor(0,0,0,31);
   127: 
   128:   // background must have a unique polyID for antialiasing
   129:   glClearPolyID(63);
   130: 
   131:   glClearDepth(0x7FFF);
   132:   
   133:   // enable translucency
   134:   // XXX: haven't actually figured out nds opengl-ish alpha yet
   135:   //  glEnable(GL_BLEND);
   136:   
   137:   // real OGL
   138:   //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   139:   // nds OGL: use as a state, thus polys (and by that we mean tris or quads),
   140:   //          will have this 0..15 alpha value
   141:   // POLY_CULL_NONE for now
   142:   glPolyFmt(POLY_ALPHA(15) | POLY_CULL_NONE);
   143:   //glPolyFmt(POLY_CULL_NONE);
   144: 
   145:   // use threshold below ?? need to read up...
   146:   // XXX: haven't actually figured out nds opengl-ish alpha yet
   147:   //  glEnable(GL_ALPHA_TEST);
   148:   // 0..15 from nds, not sure ... 4 bits alpha?
   149:   // "sets minimum alpha value that will be used" ???
   150:   //  glAlphaFunc(7);
   151: 
   152:   ////	  
   153:   //// begin effective window reshape/init function
   154:   ////	  
   155: 
   156:   // set viewport to the screen resolution
   157:   glViewport(0,0,255,191);
   158:   
   159:   glMatrixMode(GL_PROJECTION);
   160: 
   161:   glLoadIdentity();
   162: 
   163:   // set 3d perspective 'camera' type/parameters:
   164:   // fov(?), aspect-ratio, nearz, farz
   165:   //  gluPerspective(70, 256.0 / 192.0, 0.1, 100);
   166: 
   167:   // set 2d orthographic 'camera' type/parameters:
   168:   glOrthof32(MODEL_XMIN,
   169: 	     MODEL_XMAX,
   170: 	     MODEL_YMIN,
   171: 	     MODEL_YMAX,
   172: 	     MODEL_ZMIN,
   173: 	     MODEL_ZMAX);
   174: 
   175:   glMatrixMode(GL_MODELVIEW);
   176: 
   177:   ////	  
   178:   //// end effective window reshape/init function
   179:   ////	  
   180: 
   181:   // nds openGL-ish: several nds specific attributes can be set
   182:   glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE);
   183:   
   184: 
   185: }  
   186: 
   187: 
   188: 
   189: void gzmcpc_display_main_splash_text(void) {
   190: 
   191:   //  printf("\x1b[04;0H |----------------------------| ");
   192:       printf("\x1b[02;0H       Guitar-ZyX::M.C.P.       ");
   193: 
   194:       printf("\x1b[04;0H     Master Control Program     ");
   195: 
   196: }  
   197: 
   198: 
   199: 
   200: void textout(text_output_line_type linetype, const char *fmt, ...) {
   201: 
   202:   //
   203:   // XXX would making these vars static help at all?
   204:   //
   205: 
   206:   va_list arg;
   207: 
   208:   char message_prefix[MAX_TEXT_OUTPUT_LINE_SIZE];
   209:   char temp_buffer[MAX_TEXT_OUTPUT_LINE_SIZE];
   210: 
   211:   // XXX is there a cleaner way to do this with an array (effective hash) initialization?
   212:   switch (linetype) {
   213:     
   214:   case TLT_DEBUG:
   215:     snprintf(message_prefix, 
   216: 	     MAX_TEXT_OUTPUT_LINE_SIZE,
   217: 	     "DBG::");
   218:     break;
   219:   case TLT_ERROR:
   220:     snprintf(message_prefix, 
   221: 	     MAX_TEXT_OUTPUT_LINE_SIZE,
   222: 	     "ERROR: ");
   223:     break;
   224:   case TLT_FX_MODE:
   225:     snprintf(message_prefix, 
   226: 	     MAX_TEXT_OUTPUT_LINE_SIZE,
   227: 	     " F/X Mode /\\/ ");
   228:     break;
   229:   case TLT_MODE:
   230:     snprintf(message_prefix, 
   231: 	     MAX_TEXT_OUTPUT_LINE_SIZE,
   232: 	     "   MCP /\\/ ");
   233:     break;
   234:   case TLT_NETWORK_STATUS:
   235:     snprintf(message_prefix, 
   236: 	     MAX_TEXT_OUTPUT_LINE_SIZE,
   237: 	     " network /\\/ ");
   238:     break;
   239:   case TLT_STATUS:
   240:     snprintf(message_prefix, 
   241: 	     MAX_TEXT_OUTPUT_LINE_SIZE,
   242: 	    " status /\\/ ");
   243:     break;
   244:   case TLT_TOUCH_VAL:
   245:     snprintf(message_prefix, 
   246: 	     MAX_TEXT_OUTPUT_LINE_SIZE,
   247: 	     " WhAmMyPaD /\\/ ");
   248:     break;
   249:   case TLT_TOUCH_VALXP:
   250:     snprintf(message_prefix, 
   251: 	     MAX_TEXT_OUTPUT_LINE_SIZE,
   252: 	     "   WPX// ");
   253:     break;
   254:   case TLT_TOUCH_VALYP:
   255:     snprintf(message_prefix, 
   256: 	     MAX_TEXT_OUTPUT_LINE_SIZE,
   257: 	     "     WPY// ");
   258:     break;
   259:   case TLT_NODEBUG:
   260:     //snprintf(message_prefix, MAX_TEXT_OUTPUT_LINE_SIZE"");
   261:     // nicer way to avoid warning??
   262:     message_prefix[0]='\0';
   263:     break;
   264:   case TLT_AESTHETIC:
   265:     //snprintf(message_prefix, MAX_TEXT_OUTPUT_LINE_SIZE"");
   266:     message_prefix[0]='\0';
   267:     break;
   268:   case TLT_NUM_TEXT_OUTPUT_LINE_TYPES:
   269:     // handling all enum values, even the utility one avoids compiler warning
   270:     break;
   271:   }
   272: 
   273:   va_start(arg, fmt);
   274:   vsnprintf(temp_buffer, 
   275: 	    MAX_TEXT_OUTPUT_LINE_SIZE, 
   276: 	    fmt, 
   277: 	    arg);
   278:   va_end(arg);
   279: 
   280:   snprintf(text_output_line[linetype],
   281: 	   MAX_TEXT_OUTPUT_LINE_SIZE,
   282: 	   "%s%s", 
   283: 	   message_prefix, 
   284: 	   temp_buffer);
   285: 
   286:   debug_log_more("textout::%s\n",
   287: 		 text_output_line[linetype]);
   288: }
   289: 
   290: 
   291: 
   292: void render_textout(void) {
   293: 
   294:   int i;
   295: 
   296:   // 3 should work too (max 99 would be fine)
   297:   char rownum[4];
   298: 
   299: 
   300:   // clear the screen
   301:   printf("\x1b[2J");
   302: 
   303:   // the banner
   304:   gzmcpc_display_main_splash_text();
   305: 
   306:   for (i = 0 ; i < TLT_NUM_TEXT_OUTPUT_LINE_TYPES ; i++) {
   307: 
   308:     // XXX as mentioned elsewhere, this screams for a hash, but don't care now
   309:     switch (i) {
   310:     case TLT_DEBUG:
   311:       snprintf(rownum, 4, "%d", TS_DEBUG_ROW);
   312:       break;
   313:     case TLT_ERROR:
   314:       snprintf(rownum, 4, "%d", TS_ERROR_ROW);
   315:       break;
   316:     case TLT_FX_MODE:
   317:       snprintf(rownum, 4, "%d", TS_FX_MODE_ROW);
   318:       break;
   319:     case TLT_MODE:
   320:       snprintf(rownum, 4, "%d", TS_MODE_ROW);
   321:       break;
   322:     case TLT_NETWORK_STATUS:
   323:       snprintf(rownum, 4, "%d", TS_NETWORK_STATUS_ROW);
   324:       break;
   325:     case TLT_STATUS:
   326:       snprintf(rownum, 4, "%d", TS_STATUS_ROW);
   327:       break;
   328:     case TLT_TOUCH_VAL:
   329:       // XXX uh, yeah, inconsistent
   330:       snprintf(rownum, 4, "%d", TS_TOUCH_VAL_ROW);
   331:       break;
   332:     case TLT_TOUCH_VALXP:
   333:       snprintf(rownum, 4, "%d", TS_TOUCH_VALXP_ROW);
   334:       break;
   335:     case TLT_TOUCH_VALYP:
   336:       snprintf(rownum, 4, "%d", TS_TOUCH_VALYP_ROW);
   337:       break;
   338:     case TLT_NODEBUG:
   339:       snprintf(rownum, 4, "%d", TS_DEBUG_ROW);
   340:       break;
   341:     case TLT_AESTHETIC:
   342:       snprintf(rownum, 4, "%d", TS_AESTHETIC_ROW);
   343:       break;
   344:     }
   345: 
   346:     // XXX obsolete due to screen clear?
   347:     // note: with this, 345 wraps
   348:     //    printf("\x1b[%s;0H12345678901234567890123456789012345", rownum);
   349:     printf("\x1b[%s;0H                                ", rownum);
   350: 
   351:     printf("\x1b[%s;0H%s", rownum, text_output_line[i]);
   352: 
   353:   } // end for iteration over linetypes
   354: 
   355: }
   356: 
   357: 
   358: 
   359: void init_modelview_matrix(void) {
   360: 
   361:   glMatrixMode(GL_MODELVIEW);
   362: 
   363:   glLoadIdentity();
   364: 
   365:   // for non-ortho 3d
   366:   //  void gluLookAtf32(int32 eyex, int32 eyey, int32 eyez, 
   367:   //		    int32 lookAtx, int32 lookAty, int32 lookAtz, 
   368:   //		    int32 upx, int32 upy, int32 upz)
   369: 
   370:   // global (animation?) xforms if desired...
   371: 
   372:   // move the camera, currently at the default origin looking
   373:   // down the negative Z axis, backwards half the depth, thus
   374:   // will use z=0 for all z's in this 2d ortho world.  Much of
   375:   // this is for explicit educational value (though don't believe
   376:   // any of it till initial code reviews are done)
   377:   //
   378:   // note: you wouldn't use divf32 instead of '/' unless you also
   379:   //       used inttof32(-4).  Fixed point sucks.  Especially because
   380:   //       f32(1.19.12) and v16(1.3.12) are both used in what seems
   381:   //       ugly- i.e. f32 only for glOrtho, and v16 only for glVertex,
   382:   //       thus confusing.
   383:   glTranslate3f32(0,
   384: 		  0,
   385: 		  model_depth / -4);
   386: 
   387: 
   388:   // example simple time based animation camera xform
   389:   // - side to side motion, distance
   390:   //
   391:   //  if (num_ticks.s % 2) {
   392:   //    glTranslate3f32((model_width / 8) *
   393:   //		    (num_ticks.ms / 1000), 
   394:   //		    0, 
   395:   //		    0);
   396:   //  } else {
   397:   //    glTranslate3f32((model_width / 8) *
   398:   //		    (1 - (num_ticks.ms / 1000)), 
   399:   //		    0, 
   400:   //		    0);
   401:   //  }
   402: 
   403: }
   404: 
   405: void 
   406: draw_hex(v16 centerx, v16 centery, 
   407: 	 v16 z, 
   408: 	 v16 radius, 
   409: 	 float rotation,
   410: 	 uint8 centerr, uint8 centerg, uint8 centerb, uint8 centera,
   411: 	 uint8 outterr, uint8 outterg, uint8 outterb, uint8 outtera,
   412: 	 uint8 rimr, uint8 rimg, uint8 rimb, uint8 rima,
   413: 	 u16 intensity)
   414: {
   415: 
   416:   uint8 act_center_r;
   417:   uint8 act_center_g;
   418:   uint8 act_center_b;
   419:   uint8 act_outter_r;
   420:   uint8 act_outter_g;
   421:   uint8 act_outter_b;
   422: 
   423: 
   424:   act_center_r = (uint8)((u16)centerr * (u16)(RGB15_TO_R5(intensity)) / 31);
   425:   act_center_g = (uint8)((u16)centerg * (u16)(RGB15_TO_G5(intensity)) / 31);
   426:   act_center_b = (uint8)((u16)centerb * (u16)(RGB15_TO_B5(intensity)) / 31);
   427:   act_outter_r = (uint8)((u16)outterr * (u16)(RGB15_TO_R5(intensity)) / 31);
   428:   act_outter_g = (uint8)((u16)outterg * (u16)(RGB15_TO_G5(intensity)) / 31);
   429:   act_outter_b = (uint8)((u16)outterb * (u16)(RGB15_TO_B5(intensity)) / 31);
   430: 
   431:   // save current modelview matrix
   432:   // note: I think I am following the global method of thinking 
   433:   //       rather than the local method, as described in the red
   434:   //       book (p106 2nd ed).  
   435:   glPushMatrix();
   436: 
   437:   // move to the desired center/location
   438:   glTranslate3f32(centerx,
   439: 		  centery,
   440: 		  z);
   441: 
   442:   // rotate around the z axis
   443:   glRotatef(rotation + 30.0f,0.0f,0.0f,1.0f);
   444:     
   445: 
   446: #define P_A_X (0) 
   447: #define P_A_Y (0) 
   448: #define P_B_X (radius * -1) 
   449: #define P_B_Y (0) 
   450: #define P_C_X ((radius >> 1) * -1) 
   451:   // XXX? single value lut?
   452: #define P_C_Y (mulf32(P_C_X, sqrtf32(inttof32(3)))) 
   453: #define P_D_X (P_C_X * -1) 
   454: #define P_D_Y (P_C_Y) 
   455: #define P_E_X (radius) 
   456: #define P_E_Y (0) 
   457: #define P_F_X P_D_X 
   458: #define P_F_Y (P_D_Y * -1) 
   459: #define P_G_X ((radius >> 1) * -1) 
   460: #define P_G_Y P_F_Y 
   461:     
   462:   glBegin(GL_TRIANGLE_STRIP);
   463:     
   464:   glColor3b(act_outter_r, act_outter_g, act_outter_b);
   465: 
   466:   // f-g-a-b-c
   467:   glColor3b(act_outter_r, act_outter_g, act_outter_b);
   468:   glVertex3v16(P_F_X, P_F_Y, z);
   469:   glVertex3v16(P_G_X, P_G_Y, z);
   470:   glColor3b(act_center_r, act_center_g, act_center_b);
   471:   glVertex3v16(P_A_X, P_A_Y, z);
   472:   glColor3b(act_outter_r, act_outter_g, act_outter_b);
   473:   glVertex3v16(P_B_X, P_B_Y, z);
   474:   glVertex3v16(P_C_X, P_C_Y, z);
   475: 
   476:   // c-d-a-e-f
   477:   glColor3b(act_outter_r, act_outter_g, act_outter_b);
   478:   glVertex3v16(P_C_X, P_C_Y, z);
   479:   glVertex3v16(P_D_X, P_D_Y, z);
   480:   glColor3b(act_center_r, act_center_g, act_center_b);
   481:   glVertex3v16(P_A_X, P_A_Y, z);
   482:   glColor3b(act_outter_r, act_outter_g, act_outter_b);
   483:   glVertex3v16(P_E_X, P_E_Y, z);
   484:   glVertex3v16(P_F_X, P_F_Y, z);
   485:   
   486:   glEnd();
   487:   glPopMatrix(1);
   488: 
   489: }
   490:  
   491: 
   492: void 
   493: draw_simple_hex_grid(int width, 
   494: 		     int height, 
   495: 		     u16 intensity) {
   496: 
   497:   uint32 myx, myy;
   498:   int i, j;
   499:   v16 myz;
   500:   uint8 comb_center_r;
   501:   uint8 comb_center_g;
   502:   uint8 comb_center_b;
   503:   float anim_rotate;
   504:   float anim_fraction;
   505: 
   506:   //
   507:   // simple intro animation
   508:   //
   509: 
   510:   // crude method to stop z-fighting (no glDisable(GL_DEPTH_BUFFERING)?)
   511:   // i.e. below myz++ happens for each hex rendered
   512:   myz = floattov16(0.25f);
   513: 
   514:   // XXX: this is clumsy for now (i don't know or care what I'm doing)
   515:   glPushMatrix();
   516:   glTranslate3f32(model_width >> 1,
   517: 		  model_height >> 1,
   518: 		  0);
   519: 
   520:   //
   521:   // intro animation
   522:   //
   523:   if (mode_ms < INTRO_ANIM_3DSPINZOOM_START) {
   524:     glScalef(INTRO_ANIM_3DSPINZOOM_SCALE_FACTOR * 1.0f, 
   525: 	     INTRO_ANIM_3DSPINZOOM_SCALE_FACTOR * 1.0f, 
   526: 	     1.0f);
   527:   } else if (mode_ms < (INTRO_ANIM_3DSPINZOOM_START + INTRO_ANIM_3DSPINZOOM_DURATION)) {
   528: 
   529:     // a float from 0.0 to 1.0 representing how far along during the 3DSPINZOOM animation
   530:     anim_fraction = ((float)(mode_ms - INTRO_ANIM_3DSPINZOOM_START)) /
   531:       (INTRO_ANIM_3DSPINZOOM_DURATION * 1.0f);
   532:     
   533:     glScalef(((INTRO_ANIM_3DSPINZOOM_SCALE_FACTOR * 1.0f) - 
   534: 	      anim_fraction * 
   535: 	      (INTRO_ANIM_3DSPINZOOM_SCALE_FACTOR - 1.0f)),
   536: 	     ((INTRO_ANIM_3DSPINZOOM_SCALE_FACTOR * 1.0f) - 
   537: 	      anim_fraction * 
   538: 	      (INTRO_ANIM_3DSPINZOOM_SCALE_FACTOR - 1.0f)),
   539: 	     1.0f);
   540: 
   541:     anim_rotate = anim_fraction * -360.0f;
   542: 
   543:     glRotatef(anim_rotate,
   544: 	      0.0f,0.0f,1.0f);
   545:   }
   546: 
   547: 
   548:   comb_center_r = 13;
   549:   comb_center_g = 13;
   550:   comb_center_b = 13;
   551: 
   552:   comb_center_r = cstate_wpy << 1;
   553:   comb_center_g = 0;
   554:   comb_center_b = cstate_wpx << 1;
   555: 
   556:   // iterate over the 2D hex grid, prepping and drawing cells
   557:   for (j = 0 ; j < height ; j++) {
   558:     for (i = 0 ; i < width ; i++) {
   559: 
   560:       comb_center_g = comb_charge[i][j];
   561:       
   562:       // offset odd rows a bit to the right
   563:       if (j % 2) {
   564: 	myx = MODEL_XMIN + ((MODEL_XMAX - MODEL_XMIN) * COMB_XBORDER / 100) +
   565: 	  (i  * (((MODEL_XMAX - MODEL_XMIN) * (100 - 2 * COMB_XBORDER) / 100) / (width - 1)));
   566:       } else {
   567: 	myx = MODEL_XMIN + ((MODEL_XMAX - MODEL_XMIN) * COMB_XBORDER / 100) +
   568: 	  ((2 * i + 1) * (((MODEL_XMAX - MODEL_XMIN) * (100 - 2 * COMB_XBORDER) / 100) / 2 / (width - 1)));
   569:       }
   570:       
   571:       // this formula is a hack, but achieves reasonable packing (for me, now)
   572:       // AHH, now I remember the old code.  The reason for the border may
   573:       //      have been part of this hack, i.e. with a different value 
   574:       //      than 10 / 6 below, and maybe better looking result (if
   575:       //      my tired rememory is correct)
   576:       myy = MODEL_YMIN + ((MODEL_YMAX - MODEL_YMIN) * COMB_YBORDER / 100) +
   577: 	(j * (((MODEL_YMAX - MODEL_YMIN) * (100 - 2 * COMB_YBORDER) / 100) / (height - 1)));
   578:       
   579:       // note: in the trenches pitfall of fixed point hazard
   580:       //      myx = MODEL_XMIN + ((4 * i + 2) / 4) * (model_width / width);
   581:       //      myy = MODEL_YMIN + ((4 * j + 2) / 4) * (model_height / height);
   582:       // note: this works
   583:       //      myx = MODEL_XMIN + (model_width / width * (4 * i + 2)) / 4;
   584:       //      myy = MODEL_YMIN + (model_height / height * (4 * j + 2)) / 4;
   585: 
   586:       // draw the comb cell 
   587:       // note: ... / 2 * 2, when was / 2 * 4, looked pretty overlappn cool
   588:       draw_hex(myx - (model_width >> 1), 
   589: 	       myy - (model_height >> 1), 
   590: 	       myz++,
   591: 	       ((((MODEL_XMAX - MODEL_XMIN) + 
   592: 		  (MODEL_YMAX - MODEL_YMIN)) / 2) / 
   593: 		(width + height) * debug_tweak_var / 6),
   594: 	       0,
   595: 	       comb_center_r, 
   596: 	       comb_center_g, 
   597: 	       comb_center_b, 
   598: 	       13,
   599: 	       13, 197, 13, 231,
   600: 	       228, 228, 114, 253,
   601: 	       intensity);
   602:     }
   603:   }
   604: 
   605:   glPopMatrix(1);
   606: }
   607: 
   608: 
   609: void gzmcpc_flush_frame(void) {
   610: 
   611:   // XXX: maybe this should be made per mode
   612:   glFlush(0);
   613: 
   614:   // wait for vblank
   615:   swiWaitForVBlank();
   616: 
   617: }
   618: