home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the 3D Game Programming Gurus / gurus.iso / Articles / XtremeDebugging / mono.cpp < prev    next >
C/C++ Source or Header  |  1996-04-10  |  11KB  |  422 lines

  1. // MONO.CPP - C++ METHOD IMPLEMENTATION FOR MONOCHROME PRINTING ENGINE ///////////
  2.  
  3. // INCLUDES //////////////////////////////////////////////////////////////////////
  4.  
  5. #include <conio.h>
  6. #include <stdlib.h>
  7. #include <malloc.h>
  8. #include <memory.h>
  9. #include <string.h>
  10. #include <stdarg.h>
  11. #include <stdio.h>
  12. #include <math.h>
  13. #include <io.h>
  14. #include <fcntl.h>
  15.  
  16. #include "mono.h" // include the monochrome header 
  17.  
  18. // CLASS METHODS IMPLEMENTATION //////////////////////////////////////////////////
  19.  
  20. mono_print::mono_print(void)
  21. {
  22. // the constructor simply initializes the system and sets the cursor to the upper
  23. // left hand corner
  24.  
  25. cx = cy            = 0;                    // position cursor at (0,0)
  26. style            = MONO_BRIGHT;            // set style to bright text
  27. output_enable    = 1;                    // enable the output to mono monitor
  28. mono_video        = (USHORT *)0xB0000;    // pointer to the monochrome video buffer
  29. num_watches        = 0;                    // set number of watches to 0
  30.  
  31. } // end mono_print
  32.  
  33. //////////////////////////////////////////////////////////////////////////////////
  34.     
  35. void mono_print::print(char *string)
  36. {
  37. // this function is similar to printf in that it will scroll, wrap, and can interpret
  38. // newlines, note: we probably could have used the draw function, but the logic needed to control
  39. // it from this function would be as long as copying the draw function as changing it
  40.  
  41. USHORT char_attr,   // the total character attribute
  42.        char_part,   // the ascii part of the character low byte
  43.        attr_part;   // the color part of the character high byte
  44.  
  45. int index;                // looping index
  46.     
  47. // only print if gate is enabled
  48.  
  49. if (!output_enable) return;
  50.  
  51. // enter main loop and print each character
  52.  
  53. for (index=0; index<(int)strlen(string); index++)
  54.     {
  55.     // extract the character and attribute
  56.  
  57.     char_part = (USHORT)string[index];
  58.     attr_part = ((USHORT)style) << 8;
  59.  
  60.     // merge character and attribute
  61.  
  62.     char_attr = (char_part | attr_part);
  63.  
  64.     // test if this is a control character?
  65.     // for now only test \n = 0x0A
  66.  
  67.     if (char_part==0x0A)
  68.         {
  69.         // reset cursor to left edge
  70.         cx=0;
  71.  
  72.         // advance cursor down a line and test for scroll
  73.         if (++cy>=25)
  74.             {
  75.             scroll(1);
  76.             cy=24;
  77.              } // end if
  78.             
  79.         } // end if
  80.     else
  81.         {
  82.         // display character
  83.  
  84.         mono_video[cy*(MONO_BYTES_PER_LINE/2) + cx] = char_attr;
  85.  
  86.         // update cursor position
  87.  
  88.         if (++cx>=MONO_COLUMNS)
  89.             {
  90.             cx=0;
  91.             // test for vertical scroll
  92.             if (++cy>=25)
  93.                 {
  94.                 scroll(1);
  95.                 cy=24;
  96.                  } // end if
  97.             } // end if
  98.         } // end else
  99.  
  100.     } // end for index
  101.  
  102. } // end print
  103.     
  104. //////////////////////////////////////////////////////////////////////////////////
  105.  
  106. void mono_print::draw(char *string,int x,int y,int style)
  107. {
  108. // this function is lower level that print, it simply prints the sent string at
  109. // the sent position and color and doesn't update anything
  110. // note that the function has simple clipping
  111.  
  112. USHORT char_attr,   // the total character attribute
  113.        char_part,   // the ascii part of the character low byte
  114.        attr_part;   // the color part of the character high byte
  115.  
  116. int index,                // looping index
  117.     length,                // length of sent string
  118.     offset=0;            // used in clipping algorithm
  119.  
  120. char temp_string[256];    // holds working copy of string
  121.  
  122. // only print if gate is enabled
  123.  
  124. if (!output_enable) return;
  125.  
  126. // do trivial rejections first
  127.  
  128. length = strlen(string);
  129.  
  130. if (y<0 || y>(MONO_ROWS-1) || x>(MONO_COLUMNS-1) || (x<=-length)) return;
  131.  
  132. // make working copy of string
  133.  
  134. strcpy(temp_string,string);
  135.  
  136. // now test if string is partially clipped on X axis
  137.  
  138. if (x<0) // test left extent
  139.     {
  140.     // set offset into string
  141.     offset = -x;
  142.  
  143.     // reset x
  144.     x=0;
  145.  
  146.     } // end if
  147.  
  148. // note that we test both cases, since the string may be longer than the width of display
  149.  
  150. if (x+length>MONO_COLUMNS) // test right extent
  151.     length = MONO_COLUMNS-x;
  152.  
  153. // enter main loop and print each character
  154.  
  155. for (index=0; index<length; index++)
  156.     {
  157.     // extract the character and attribute
  158.  
  159.     char_part = (USHORT)temp_string[index+offset];
  160.     attr_part = ((USHORT)style) << 8;
  161.  
  162.     // merge character and attribute
  163.  
  164.     char_attr = (char_part | attr_part);
  165.  
  166.     // display character
  167.  
  168.     mono_video[y*(MONO_BYTES_PER_LINE/2)  + x+index] = char_attr;
  169.  
  170.     } // end for index
  171.  
  172. } // end draw
  173.  
  174. //////////////////////////////////////////////////////////////////////////////////
  175.  
  176. void mono_print::set_cursor(int x, int y)        
  177. {
  178. // this function sets the position of the printing cursor
  179.  
  180. // check if x position is valid
  181.  
  182. if (x<0) cx=0;
  183. else
  184. if (x>=MONO_COLUMNS) cx=MONO_COLUMNS-1;
  185. else
  186.     cx = x;
  187.  
  188. // check if y position is valid
  189.  
  190. if (y<0) cy=0;
  191. else
  192. if (y>=MONO_ROWS) cy=MONO_ROWS-1;
  193. else
  194.     cy = y;
  195.  
  196. } // end set_cursor
  197.  
  198. //////////////////////////////////////////////////////////////////////////////////
  199.     
  200. void mono_print::get_cursor(int &x, int &y)        
  201. {
  202. // this function retrieves the position of the cursor
  203. x = cx;
  204. y = cy;
  205.  
  206. } // end get_cursor
  207.  
  208. //////////////////////////////////////////////////////////////////////////////////
  209.  
  210. void mono_print::set_style(int new_style)        
  211. {
  212. // this function sets the printing style
  213.  
  214. // make sure the style is somewhat reasonable
  215.  
  216. if (style<0 || style>255)
  217.     style = MONO_BRIGHT;
  218. else
  219.     style = new_style;
  220.  
  221. } // end set_style
  222.  
  223. //////////////////////////////////////////////////////////////////////////////////
  224.  
  225. void mono_print::enable()                        
  226. {
  227. // this function sets the output enable gate so that output is sent to the display
  228. output_enable = 1;
  229.  
  230. } // end enable
  231.  
  232. //////////////////////////////////////////////////////////////////////////////////
  233.  
  234. void mono_print::disable()                        
  235. {
  236. // this function is used to disable the output gate to the monitor
  237. output_enable = 0;
  238.  
  239. } // end disable
  240.  
  241. //////////////////////////////////////////////////////////////////////////////////
  242.  
  243. void mono_print::scroll(int num_lines)            
  244. {
  245. // this function scrolls the display upward the requested number of lines
  246. // only print if gate is enabled
  247. // note that mono_video is a USHORT pointer!
  248.  
  249. if (!output_enable) return;
  250.  
  251. // the display is 25 lines long, all we need to do is move the last 24 up one
  252. // line and blank out the last line
  253.  
  254. while (num_lines-->0)
  255.     {
  256.     // scroll the last 24 lines up, use memmove since dest & source overlap
  257.     memmove((void *)mono_video, (void *)(mono_video+MONO_BYTES_PER_LINE/2),24*MONO_BYTES_PER_LINE);
  258.  
  259.     // now blank out the last line
  260.     memset((void *)(mono_video+24*MONO_BYTES_PER_LINE/2),0,MONO_BYTES_PER_LINE);
  261.  
  262.     } // end while
  263.  
  264. } // end scroll
  265.  
  266. //////////////////////////////////////////////////////////////////////////////////
  267.  
  268. void mono_print::clear()
  269. {
  270. // this function clears the monchrome display
  271.  
  272. // only print if gate is enabled
  273. if (!output_enable) return;
  274.  
  275. // clear the display
  276. memset((void *)mono_video,0,25*MONO_BYTES_PER_LINE);
  277.  
  278. //reset the cursor
  279. cx = cy    = 0;        
  280.  
  281. } // end clear
  282.  
  283. //////////////////////////////////////////////////////////////////////////////////
  284.  
  285. void mono_print::delete_watches(void)
  286. {
  287. // this deletes all the watches
  288.  
  289. num_watches = 0;
  290. memset(watch, 0, sizeof(mono_watch)*MONO_MAX_WATCHES);
  291.  
  292. } // end delete_watches
  293.     
  294. //////////////////////////////////////////////////////////////////////////////////
  295.  
  296. int mono_print::add_watch(char *name,    // name or symbol for watch, up to 15 chars
  297.                           void *addr,    // address of variable to watch
  298.                           int type,        // type of variable
  299.                             int x,        // position of watch on display
  300.                           int y,
  301.                           int field_width) // size of ouput field, for blank padding
  302. {
  303. // this function creates a watch variable and enters it into the watch list
  304.  
  305. if (num_watches>=MONO_MAX_WATCHES)
  306.     return(-1);
  307.  
  308. // insert this watch at current location
  309.  
  310. strcpy(watch[num_watches].name, name);
  311. watch[num_watches].data            = addr;
  312. watch[num_watches].type            = type;
  313. watch[num_watches].x            = x;
  314. watch[num_watches].y            = y;
  315. watch[num_watches].field_width    = field_width;
  316.  
  317. // increment number of watches
  318.  
  319. num_watches++;
  320.  
  321. // return the position of this watch
  322. return(num_watches-1);
  323.  
  324. } // end add_watch
  325.  
  326. //////////////////////////////////////////////////////////////////////////////////
  327.  
  328. void mono_print::update_watches(void)
  329. {
  330. // this function updates the visual display with the current values of all
  331. // the watches
  332.  
  333. int index;                // looping var
  334. char temp_string[256];    // temporary working string
  335.  
  336. // only print if gate is enabled
  337. if (!output_enable) return;
  338.  
  339. // loop thru all the watch variables and display them
  340.  
  341. for (index=0; index<num_watches; index++)
  342.     {
  343.     // first generate display string based on type of variable being watched
  344.     
  345.     switch (watch[index].type)
  346.         {
  347.         case MONO_WATCH_CHAR:
  348.             {
  349.             sprintf(temp_string,"%s=%c",watch[index].name,*((char *)(watch[index].data)));  
  350.             } break;
  351.  
  352.         case MONO_WATCH_UCHAR:
  353.             {
  354.             sprintf(temp_string,"%s=%u",watch[index].name,*((UCHAR *)(watch[index].data)));  
  355.             } break;
  356.  
  357.         case MONO_WATCH_SHORT:            
  358.             {
  359.             sprintf(temp_string,"%s=%d",watch[index].name,*((short *)(watch[index].data)));  
  360.             } break;
  361.  
  362.         case MONO_WATCH_USHORT:            
  363.             {
  364.             sprintf(temp_string,"%s=%u",watch[index].name,*((USHORT *)(watch[index].data)));  
  365.             } break;
  366.  
  367.         case MONO_WATCH_INT:            
  368.             {
  369.             sprintf(temp_string,"%s=%d",watch[index].name,*((int *)(watch[index].data)));  
  370.             } break;
  371.  
  372.         case MONO_WATCH_UINT:                
  373.             {
  374.             sprintf(temp_string,"%s=%u",watch[index].name,*((unsigned int *)(watch[index].data)));  
  375.             } break;
  376.  
  377.         case MONO_WATCH_STRING:
  378.             {
  379.             sprintf(temp_string,"%s=%s",watch[index].name,(char *)(watch[index].data));  
  380.             } break;
  381.     
  382.         case MONO_WATCH_STRING_HEX:
  383.             {
  384.             sprintf(temp_string,"%s=",watch[index].name);  
  385.             
  386.             // merge in hex values for characters
  387.             for (int bc=0; bc<(int)strlen((char *)watch[index].data); bc++)
  388.                 {
  389.                 char hexvalue[8];
  390.                 sprintf(hexvalue,"%X,",*(bc+(UCHAR *)watch[index].data));
  391.                 strcat(temp_string,hexvalue);
  392.                 } // end for bc
  393.  
  394.             } break;
  395.  
  396.         case MONO_WATCH_FLOAT:            
  397.             {
  398.             sprintf(temp_string,"%s=%f",watch[index].name,*((float *)(watch[index].data)));  
  399.             } break;
  400.  
  401.         case MONO_WATCH_PTR:            
  402.             {
  403.             sprintf(temp_string,"%s=%X",watch[index].name,*((unsigned int *)watch[index].data));  
  404.             } break;
  405.  
  406.         default:break;
  407.  
  408.         } // end switch
  409.     
  410.     // fill in tail of string with blanks
  411.     strncat(temp_string,"                                                                ",
  412.             watch[index].field_width - (strlen(temp_string) - strlen(watch[index].name) - 1));
  413.  
  414.     // print out the watch
  415.     draw(temp_string, watch[index].x, watch[index].y, MONO_BRIGHT);
  416.  
  417.     } // end for index
  418.  
  419. } // end update_watches
  420.  
  421. //////////////////////////////////////////////////////////////////////////////////
  422.