Advertisement
ngld

Debug console (updated) GIT patch

Mar 10th, 2014
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 269.66 KB | None | 0 0
  1. diff --git a/code/Makefile.am b/code/Makefile.am
  2. index 2972f47..e22b1b4 100644
  3. --- a/code/Makefile.am
  4. +++ b/code/Makefile.am
  5. @@ -262,7 +262,9 @@ FS2_SOURCES =   \
  6.     ddsutils/ddsutils.h \
  7.     debris/debris.cpp   \
  8.     debris/debris.h \
  9. +   debugconsole/consolecmds.cpp    \
  10.     debugconsole/console.cpp    \
  11. +   debugconsole/consoleparse.cpp   \
  12.     debugconsole/dbugfile.h \
  13.     debugconsole/timerbar.cpp   \
  14.     debugconsole/timerbar.h \
  15. diff --git a/code/ai/aicode.cpp b/code/ai/aicode.cpp
  16. index e94fce9..3d5de1b 100644
  17. --- a/code/ai/aicode.cpp
  18. +++ b/code/ai/aicode.cpp
  19. @@ -18,6 +18,7 @@
  20.  
  21.  
  22.  #include "ai/ai.h"
  23. +#include "debugconsole/console.h"
  24.  #include "globalincs/linklist.h"
  25.  #include "object/object.h"
  26.  #include "physics/physics.h"
  27. @@ -11367,16 +11368,14 @@ float get_wing_largest_radius(object *objp, int formation_object_flag)
  28.  
  29.  float Wing_y_scale = 2.0f;
  30.  float Wing_scale = 1.0f;
  31. -DCF(wing_y_scale, "")
  32. +DCF(wing_y_scale, "Adjusts the wing formation scale along the Y axis (Default is 2.0)")
  33.  {
  34. -   dc_get_arg(ARG_FLOAT);
  35. -   Wing_y_scale = Dc_arg_float;
  36. +   dc_stuff_float(&Wing_y_scale);
  37.  }
  38.  
  39. -DCF(wing_scale, "")
  40. +DCF(wing_scale, "Adjusts the wing formation scale. (Default is 1.0f)")
  41.  {
  42. -   dc_get_arg(ARG_FLOAT);
  43. -   Wing_scale = Dc_arg_float;
  44. +   dc_stuff_float(&Wing_scale);
  45.  }
  46.  
  47.  /**
  48. diff --git a/code/ai/aiturret.cpp b/code/ai/aiturret.cpp
  49. index ad8c4da..5ee314f 100644
  50. --- a/code/ai/aiturret.cpp
  51. +++ b/code/ai/aiturret.cpp
  52. @@ -22,6 +22,7 @@
  53.  #include "iff_defs/iff_defs.h"
  54.  #include "weapon/muzzleflash.h"
  55.  #include "parse/scripting.h"
  56. +#include "debugconsole/console.h"
  57.  
  58.  #include <limits.h>
  59.  
  60. @@ -38,8 +39,7 @@
  61.  float Lethality_range_const = 2.0f;
  62.  DCF(lethality_range, "N for modifying range: 1 / (1+N) at 100")
  63.  {
  64. -   dc_get_arg(ARG_FLOAT);
  65. -   Lethality_range_const = Dc_arg_float;
  66. +   dc_stuff_float(&Lethality_range_const);
  67.  }
  68.  
  69.  float Player_lethality_bump[NUM_SKILL_LEVELS] = {
  70. @@ -1466,10 +1466,16 @@ ship_subsys *aifft_list[MAX_AIFFT_TURRETS];
  71.  float aifft_rank[MAX_AIFFT_TURRETS];
  72.  int aifft_list_size = 0;
  73.  int aifft_max_checks = 5;
  74. -DCF(mf, "")
  75. +DCF(mf, "Adjusts the maximum number of tries an AI may do when trying to pick a subsystem to attack (Default is 5)")
  76.  {
  77. -   dc_get_arg(ARG_INT);
  78. -   aifft_max_checks = Dc_arg_int;
  79. +   dc_stuff_int(&aifft_max_checks);
  80. +
  81. +   if (aifft_max_checks <= 0) {
  82. +       dc_printf("Value must be a non-negative, non-zero integer\n");
  83. +       dc_printf("aifft_max_checks set to default value of 5\n");
  84. +
  85. +       aifft_max_checks = 5;
  86. +   }
  87.  }
  88.  
  89.  
  90. diff --git a/code/asteroid/asteroid.cpp b/code/asteroid/asteroid.cpp
  91. index 99b6bad..cf87c48 100644
  92. --- a/code/asteroid/asteroid.cpp
  93. +++ b/code/asteroid/asteroid.cpp
  94. @@ -39,6 +39,8 @@
  95.  #include "network/multimsgs.h"
  96.  #include "network/multi.h"
  97.  #include "parse/scripting.h"
  98. +#include "debugconsole/console.h"
  99. +
  100.  #include <algorithm>
  101.  #include "globalincs/compatibility.h"
  102.  
  103. @@ -1404,23 +1406,8 @@ void asteroid_level_close()
  104.     Asteroid_field.num_initial_asteroids=0;
  105.  }
  106.  
  107. -DCF(asteroids,"Turns asteroids on/off")
  108. -{ 
  109. -   if ( Dc_command )   {  
  110. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  111. -       if ( Dc_arg_type & ARG_TRUE )  
  112. -           Asteroids_enabled = 1
  113. -       else if ( Dc_arg_type & ARG_FALSE )
  114. -           Asteroids_enabled = 0
  115. -       else if ( Dc_arg_type & ARG_NONE )
  116. -           Asteroids_enabled ^= 1;
  117. -   }  
  118. -   if ( Dc_help ) 
  119. -       dc_printf( "Usage: asteroids [bool]\nTurns asteroid system on/off.  If nothing passed, then toggles it.\n" );  
  120. -  
  121. -   if ( Dc_status )   
  122. -       dc_printf( "asteroids are %s\n", (Asteroids_enabled?"ON":"OFF") )
  123. -}
  124. +DCF_BOOL2(asteroids, Asteroids_enabled, "enables or disables asteroids", "Usage: asteroids [bool]\nTurns asteroid system on/off.  If nothing passed, then toggles it.\n");
  125. +
  126.  
  127.  void hud_target_asteroid()
  128.  {
  129. diff --git a/code/bmpman/bmpman.cpp b/code/bmpman/bmpman.cpp
  130. index 1340437..0e5af20 100644
  131. --- a/code/bmpman/bmpman.cpp
  132. +++ b/code/bmpman/bmpman.cpp
  133. @@ -37,6 +37,7 @@
  134.  #include "jpgutils/jpgutils.h"
  135.  #include "parse/parselo.h"
  136.  #include "network/multiutil.h"
  137. +#include "debugconsole/console.h"
  138.  
  139.  #define BMPMAN_INTERNAL
  140.  #include "bmpman/bm_internal.h"
  141. @@ -669,46 +670,53 @@ int bm_reload(int bitmap_handle, const char* filename)
  142.  
  143.  DCF(bm_frag,"Shows BmpMan fragmentation")
  144.  {
  145. -   if ( Dc_command )   {
  146. +   if (dc_optional_string_either("help", "--help")) {
  147. +       dc_printf("Displays a graphic showing the BmpMan fragmentation. Color key:\n");
  148. +       dc_printf("\tGray  : NONE\n");
  149. +       dc_printf("\tRed   : PCXn");
  150. +       dc_printf("\tGreen : USER, TGA, PNG, DDS\n");
  151. +       dc_printf("\tBlue  : ANI, EFF\n\n");
  152.  
  153. -       gr_clear();
  154. -
  155. -       int x=0, y=0;
  156. -       int xs=2, ys=2;
  157. -       int w=4, h=4;
  158. -
  159. -       for (int i=0; i<MAX_BITMAPS; i++ )  {
  160. -           switch( bm_bitmaps[i].type )    {
  161. -           case BM_TYPE_NONE:
  162. -               gr_set_color(128,128,128);
  163. -               break;
  164. -           case BM_TYPE_PCX:
  165. -               gr_set_color(255,0,0);
  166. -               break;
  167. -           case BM_TYPE_USER:
  168. -           case BM_TYPE_TGA:
  169. -           case BM_TYPE_PNG:
  170. -           case BM_TYPE_DDS:
  171. -               gr_set_color(0,255,0);
  172. -               break;
  173. -           case BM_TYPE_ANI:
  174. -           case BM_TYPE_EFF:
  175. -               gr_set_color(0,0,255);
  176. -               break;
  177. -           }
  178. +       dc_printf("Once done reviewing the graphic, press any key to return to the console\n");
  179. +       return;
  180. +   }
  181. +  
  182. +   gr_clear();
  183.  
  184. -           gr_rect( x+xs, y+ys, w, h );
  185. -           x += w+xs+xs;
  186. -           if ( x > 639 )  {
  187. -               x = 0;
  188. -               y += h + ys + ys;
  189. -           }
  190. +   int x=0, y=0;
  191. +   int xs=2, ys=2;
  192. +   int w=4, h=4;
  193.  
  194. +   for (int i=0; i<MAX_BITMAPS; i++ )  {
  195. +       switch( bm_bitmaps[i].type )    {
  196. +       case BM_TYPE_NONE:
  197. +           gr_set_color(128,128,128);
  198. +           break;
  199. +       case BM_TYPE_PCX:
  200. +           gr_set_color(255,0,0);
  201. +           break;
  202. +       case BM_TYPE_USER:
  203. +       case BM_TYPE_TGA:
  204. +       case BM_TYPE_PNG:
  205. +       case BM_TYPE_DDS:
  206. +           gr_set_color(0,255,0);
  207. +           break;
  208. +       case BM_TYPE_ANI:
  209. +       case BM_TYPE_EFF:
  210. +           gr_set_color(0,0,255);
  211. +           break;
  212.         }
  213.  
  214. -       gr_flip();
  215. -       key_getch();
  216. +       gr_rect( x+xs, y+ys, w, h );
  217. +       x += w+xs+xs;
  218. +       if ( x > 639 )  {
  219. +           x = 0;
  220. +           y += h + ys + ys;
  221. +       }
  222.     }
  223. +
  224. +   gr_flip();
  225. +   key_getch();
  226.  }
  227.  
  228.  static int find_block_of(int n)
  229. @@ -2068,48 +2076,52 @@ void bm_unload_all()
  230.  
  231.  DCF(bmpman,"Shows/changes bitmap caching parameters and usage")
  232.  {
  233. -   if ( Dc_command )   {
  234. -       dc_get_arg(ARG_STRING);
  235. -       if ( !strcmp( Dc_arg, "flush" ))    {
  236. -           dc_printf( "Total RAM usage before flush: %d bytes\n", bm_texture_ram );
  237. -           int i;
  238. -           for (i = 0; i < MAX_BITMAPS; i++)   {
  239. -               if ( bm_bitmaps[i].type != BM_TYPE_NONE )   {
  240. -                   bm_free_data(i);
  241. -               }
  242. -           }
  243. -           dc_printf( "Total RAM after flush: %d bytes\n", bm_texture_ram );
  244. -       } else if ( !strcmp( Dc_arg, "ram" ))   {
  245. -           dc_get_arg(ARG_INT);
  246. -           Bm_max_ram = Dc_arg_int*1024*1024;
  247. -       } else {
  248. -           // print usage, not stats
  249. -           Dc_help = 1;
  250. -       }
  251. -   }
  252. -
  253. -   if ( Dc_help )  {
  254. -       dc_printf( "Usage: BmpMan keyword\nWhere keyword can be in the following forms:\n" );
  255. -       dc_printf( "BmpMan flush    Unloads all bitmaps.\n" );
  256. -       dc_printf( "BmpMan ram x    Sets max mem usage to x MB. (Set to 0 to have no limit.)\n" );
  257. -       dc_printf( "\nUse '? BmpMan' to see status of Bitmap manager.\n" );
  258. -       Dc_status = 0;  // don't print status if help is printed.  Too messy.
  259. +   if ( dc_optional_string_either("help", "--help"))   {
  260. +       dc_printf( "Usage: BmpMan [arg]\nWhere arg can be any of the following:\n" );
  261. +       dc_printf( "\tflush    Unloads all bitmaps.\n" );
  262. +       dc_printf( "\tram [x]  Sets max mem usage to x MB. (Set to 0 to have no limit.)\n" );
  263. +       dc_printf( "\t?        Displays status of Bitmap manager.\n" );
  264. +       return;
  265.     }
  266.  
  267. -   if ( Dc_status )    {
  268. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  269.         dc_printf( "Total RAM usage: %d bytes\n", bm_texture_ram );
  270.  
  271. -
  272. -       if ( Bm_max_ram > 1024*1024 )
  273. -           dc_printf( "Max RAM allowed: %.1f MB\n", i2fl(Bm_max_ram)/(1024.0f*1024.0f) );
  274. -       else if ( Bm_max_ram > 1024 )
  275. -           dc_printf( "Max RAM allowed: %.1f KB\n", i2fl(Bm_max_ram)/(1024.0f) );
  276. -       else if ( Bm_max_ram > 0 )
  277. -           dc_printf( "Max RAM allowed: %d bytes\n", Bm_max_ram );
  278. -       else
  279. -           dc_printf( "No RAM limit\n" );
  280. +       if (Bm_max_ram > 1024*1024) {
  281. +           dc_printf( "\tMax RAM allowed: %.1f MB\n", i2fl(Bm_max_ram)/(1024.0f*1024.0f) );
  282. +       } else if ( Bm_max_ram > 1024 ) {
  283. +           dc_printf( "\tMax RAM allowed: %.1f KB\n", i2fl(Bm_max_ram)/(1024.0f) );
  284. +       } else if ( Bm_max_ram > 0 ) {
  285. +           dc_printf( "\tMax RAM allowed: %d bytes\n", Bm_max_ram );
  286. +       } else {
  287. +           dc_printf( "\tNo RAM limit\n" );
  288. +       }
  289. +       return;
  290. +   }
  291.  
  292.  
  293. +   if (dc_optional_string("flush")) {
  294. +       dc_printf( "Total RAM usage before flush: %d bytes\n", bm_texture_ram );
  295. +       int i;
  296. +       for (i = 0; i < MAX_BITMAPS; i++)   {
  297. +           if ( bm_bitmaps[i].type != BM_TYPE_NONE )   {
  298. +               bm_free_data(i);
  299. +           }
  300. +       }
  301. +       dc_printf( "Total RAM after flush: %d bytes\n", bm_texture_ram );
  302. +   } else if (dc_optional_string("ram")) {
  303. +       dc_stuff_int(&Bm_max_ram);
  304. +
  305. +       if (Bm_max_ram > 0) {
  306. +           dc_printf("BmpMan limited to %i, MB's\n", Bm_max_ram);
  307. +           Bm_max_ram *= 1024 * 1024;
  308. +       } else if (Bm_max_ram == 0) {
  309. +           dc_printf("!!BmpMan memory is unlimited!!\n");
  310. +       } else {
  311. +           dc_printf("Illegal value. Must be non-negative.");
  312. +       }
  313. +   } else {
  314. +       dc_printf("<BmpMan> No argument given\n");
  315.     }
  316.  }
  317.  
  318. diff --git a/code/controlconfig/controlsconfig.cpp b/code/controlconfig/controlsconfig.cpp
  319. index 6db4073..442f885 100644
  320. --- a/code/controlconfig/controlsconfig.cpp
  321. +++ b/code/controlconfig/controlsconfig.cpp
  322. @@ -29,6 +29,7 @@
  323.  #include "network/multi_pmsg.h"
  324.  #include "network/multiutil.h"
  325.  #include "parse/scripting.h"
  326. +#include "debugconsole/console.h"
  327.  
  328.  
  329.  #ifndef NDEBUG
  330. @@ -348,7 +349,7 @@ int Config_allowed[] = {
  331.  #ifndef NDEBUG
  332.  int Show_controls_info = 0;
  333.  
  334. -DCF_BOOL(show_controls_info, Show_controls_info)
  335. +DCF_BOOL(show_controls_info, Show_controls_info);
  336.  #endif
  337.  
  338.  static int Axes_origin[JOY_NUM_AXES];
  339. diff --git a/code/debugconsole/console.cpp b/code/debugconsole/console.cpp
  340. index fcf34f5..72eaf40 100644
  341. --- a/code/debugconsole/console.cpp
  342. +++ b/code/debugconsole/console.cpp
  343. @@ -8,601 +8,489 @@
  344.  */
  345.  
  346.  
  347. -
  348. -#include <stdlib.h>
  349. -#include <stdio.h>
  350. -#include <stdarg.h>
  351. -#include <setjmp.h>
  352. -#include <string.h>
  353. -
  354. +#include "debugconsole/console.h"
  355. +#include "debugconsole/consoleparse.h"
  356. +#include "globalincs/alphacolors.h"
  357.  #include "globalincs/pstypes.h"
  358. +#include "globalincs/version.h"
  359. +#include "globalincs/vmallocator.h"
  360.  #include "graphics/font.h"
  361.  #include "io/timer.h"
  362.  #include "io/key.h"
  363. -#include "globalincs/alphacolors.h"
  364.  #include "osapi/osapi.h"
  365.  
  366. -
  367. -#define MAX_COMMANDS 300
  368. -
  369. -static int Num_debug_commands = 0;
  370. -static debug_command *Debug_command[MAX_COMMANDS];
  371. -
  372. -
  373. -debug_command::debug_command(char *_name, char *_help, void (*_func)() )
  374. +#include <algorithm>
  375. +#include <cmath>
  376. +
  377. +// ========================= GLOBALS =========================
  378. +bool Dc_debug_on;      //!< Flag used to print console and command debugging strings
  379. +
  380. +// Commands and History
  381. +SCP_string dc_command_str;     //!< The entered command line, arguments and all.
  382. +                               //!< Is progressively culled from the left as commands, arguments are parsed in DCF's
  383. +
  384. +// Misc
  385. +bool debug_inited = FALSE;
  386. +uint lastline = 0;  // Number of lines written to the console since the last command was processed
  387. +
  388. +
  389. +// ========================= LOCALS ==========================
  390. +// Text Buffer
  391. +uint DBROWS = 80;   // # of buffer rows
  392. +uint DBCOLS = 80;   // # of buffer columns
  393. +uint lastwhite = 0; // Last whitespace character encountered, used by putc for 'true' word wrapping
  394. +ubyte DTABS = 4;    //!< Tab size in spaces
  395. +
  396. +
  397. +SCP_deque<SCP_string> dc_buffer;
  398. +
  399. +// Display Window
  400. +uint DROWS = 25;
  401. +uint DCOLS = 80;
  402. +const uint DROWS_MIN = 25;
  403. +const uint DCOLS_MIN = 80;
  404. +uint dc_scroll_x;   // X scroll position (Leftmost character)
  405. +uint dc_scroll_y;   // Y scroll position (Topmost character)
  406. +int row_height;     // Row/Line height, in pixels
  407. +int col_width;      // Col/Character width, in pixels
  408. +int dc_font = FONT1;
  409. +
  410. +SCP_string dc_title;
  411. +
  412. +#define SCROLL_X_MAX (DBCOLS - DCOLS)
  413. +#define SCROLL_Y_MAX (DBROWS - DROWS)
  414. +
  415. +// Commands and History
  416. +uint DCMDS = 40;           // Max number of commands to remember
  417. +const uint DCMDS_MIN = 3;
  418. +
  419. +SCP_deque<SCP_string> dc_history;
  420. +SCP_deque<SCP_string>::iterator last_oldcommand;       // Iterator to the last old command. Is reset to the start every new command push.
  421. +
  422. +const char dc_prompt[]= "> ";  // The prompt c_str
  423. +SCP_string dc_command_buf;     // The command line as shown in the console. Essentially an input buffer for dc_command_str
  424. +
  425. +// Local functions
  426. +/**
  427. + * @brief Initializes the debug console.
  428. + */
  429. +void dc_init(void);
  430. +
  431. +/**
  432. + * @brief Process the entered command string
  433. + */
  434. +void dc_do_command(SCP_string *cmd_str);
  435. +
  436. +/**
  437. + * @brief Draws the in-game console.
  438. + */
  439. +void dc_draw(bool show_prompt);
  440. +
  441. +/**
  442. + * Draws the cursor
  443. + * @param [in] cmd_string  The formatted command string displayed by dc_draw_window
  444. + * @param [in] x, y            The x and y screen position of the command string
  445. + */
  446. +void dc_draw_cursor( SCP_string &cmd_string, int x, int y );
  447. +
  448. +/**
  449. + * Draws the window text
  450. + */
  451. +void dc_draw_window(bool show_prompt);
  452. +
  453. +/**
  454. + * @brief   Stuffs the given character into the output buffer.
  455. + * @details Also handles tab alignment, newlines, and maintains the target.
  456. + */
  457. +void dc_putc(char c);
  458. +
  459. +/**
  460. + * @brief Predicate function used to sort debug_commands
  461. + */
  462. +bool dcmd_less(debug_command *first, debug_command *second);
  463. +
  464. +// ============================== IMPLEMENTATIONS =============================
  465. +void dc_do_command(SCP_string *cmd_str)
  466.  {
  467. -   int i;
  468. -
  469. -   if ( Num_debug_commands >= MAX_COMMANDS ) {
  470. -       Int3();         // Too many debug console commands!! Increase MAX_COMMANDS!!
  471. +   /**
  472. +    * Grab the first word from the cmd_str
  473. +    *  If it is not a literal, ignore it "Invalid keyword: %s"
  474. +    *  Search for the command...
  475. +    *      Compare the word against valid commands
  476. +    *      If command not found, ignore it "Invalid or unknown command: %s"\
  477. +    *  Process the command...
  478. +    *      Call the function to process the command (the rest of the command line is in the parser)
  479. +    *          Function takes care of long_help and status depending on the mode.
  480. +    */
  481. +   SCP_string command;
  482. +   extern SCP_vector<debug_command*> dc_commands;  // z64: I don't like this extern here, at all. Nope nope nope.
  483. +
  484. +   if (cmd_str->empty()) {
  485.         return;
  486.     }
  487.  
  488. -   for (i=0; i<Num_debug_commands; i++ ) {
  489. -       int ret  = stricmp( Debug_command[i]->name, _name );
  490. -
  491. -       if ( ret == 0) {
  492. -           Int3();     // This debug console command already exists!!!!
  493. -           return;
  494. -       } else if ( ret > 0 ) {
  495. -           break;      // Insert it here
  496. -
  497. -       } else if ( ret < 0 ) {
  498. -           // do nothing
  499. -       }
  500. -   }
  501. -
  502. -   if ( i < Num_debug_commands ) {
  503. -       // Insert it at element i
  504. -       int j;
  505. -       for (j=Num_debug_commands; j>i; j-- ) {
  506. -           Debug_command[j] = Debug_command[j-1];
  507. -       }
  508. -       Debug_command[i] = this;
  509. -       Num_debug_commands++;
  510. -   } else {
  511. -       Debug_command[Num_debug_commands] = this;
  512. -       Num_debug_commands++;
  513. -   }
  514. -
  515. -   name = _name;
  516. -   help = _help;
  517. -   func = _func;
  518. -}
  519. -
  520. -// some global variables
  521. -int Dc_command;            // If this is set, then process the command
  522. -int Dc_help;           // If this is set, then print out the help text in the form, "usage: ... \nLong description\n" );
  523. -int Dc_status;         // If this is set, then print out the current status of the command.
  524. -char *Dc_arg;          // The (lowercased) string value of the argument retrieved from dc_arg
  525. -char *Dc_arg_org;      // Dc_arg before it got converted to lowercase
  526. -uint Dc_arg_type;      // The type of dc_arg.
  527. -char *Dc_command_line; // The rest of the command line, from the end of the last processed arg on.
  528. -int Dc_arg_int;            // If Dc_arg_type & ARG_INT is set, then this is the value
  529. -ubyte Dc_arg_ubyte;        // If Dc_arg_type & ARG_UBYTE is set, then this is the value
  530. -float Dc_arg_float;        // If Dc_arg_type & ARG_FLOAT is set, then this is the value
  531. -
  532. -int scroll_times = 0;  // incremented each time display scrolls
  533. -
  534. -int debug_inited = 0;
  535. -
  536. -#define DROWS 25
  537. -#define DCOLS 80
  538. -
  539. -int debug_x=0, debug_y=0;
  540. -char debug_text[DROWS][DCOLS];
  541. -
  542. -
  543. -static char command_line[1024];
  544. -static int command_line_pos = 0;
  545. -#define DEBUG_HISTORY 16
  546. -static char oldcommand_line[DEBUG_HISTORY][1024];
  547. -int last_oldcommand=-1;
  548. -int command_scroll = 0;
  549. +   dc_parse_init(*cmd_str);
  550.  
  551. -///=========================== SCANNER =======================
  552. -typedef enum {
  553. -   LETTER, QUOTE, SPECIAL, EOF_CODE, DIGIT
  554. -} CHAR_CODE;
  555. +   dc_stuff_string_white(command);     // Grab the first token, presumably this is a command
  556.  
  557. -typedef enum {
  558. -   NO_TOKEN, IDENTIFIER, NUMBER, STRING
  559. -} TOKEN_CODE;
  560. +   SCP_vector<debug_command*>::iterator it = find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(command.c_str()));
  561.  
  562. -
  563. -#define MAX_TOKEN_STRING_LENGTH 128
  564. -
  565. -char       scanner_ch;
  566. -TOKEN_CODE scanner_token;
  567. -
  568. -char scanner_token_string[MAX_TOKEN_STRING_LENGTH];
  569. -char scanner_word_string[MAX_TOKEN_STRING_LENGTH];
  570. -char * scanner_bufferp = "";
  571. -char * scanner_tokenp = scanner_token_string;
  572. -
  573. -CHAR_CODE scanner_char_table[256];
  574. -
  575. -#define scanner_char_code(x) scanner_char_table[x]
  576. -
  577. -void scanner_get_char()
  578. -{
  579. -   if ( *scanner_bufferp == '\0' ) {
  580. -       scanner_ch = 0;
  581. +   if (it == dc_commands.end()) {
  582. +       dc_printf("Command not found: '%s'\n", command.c_str());
  583.         return;
  584. -   }
  585. -   scanner_ch = *scanner_bufferp++;
  586. -}
  587. -
  588. -void scanner_init()
  589. -{
  590. -   int ch;
  591. -   for (ch=0; ch<256; ++ch) scanner_char_table[ch] = SPECIAL;
  592. -   for (ch='0'; ch<='9'; ++ch) scanner_char_table[ch] = DIGIT;
  593. -   for (ch='A'; ch<='Z'; ++ch) scanner_char_table[ch] = LETTER;
  594. -   for (ch='a'; ch<='z'; ++ch) scanner_char_table[ch] = LETTER;
  595. -
  596. -   scanner_char_table['.'] = DIGIT;
  597. -   scanner_char_table['-'] = DIGIT;
  598. -   scanner_char_table['+'] = DIGIT;
  599. -
  600. -   scanner_char_table['_'] = LETTER;
  601. -   scanner_char_table[34] = QUOTE;
  602. -   scanner_char_table[0] = EOF_CODE;
  603. -
  604. -   scanner_char_table[':'] = LETTER;
  605. -   scanner_char_table['\\'] = LETTER;
  606. +   } // Else, we found our command
  607.  
  608. -   scanner_ch = 0;
  609. -}
  610. -
  611. -void scanner_skip_blanks()
  612. -{
  613. -   while( (scanner_ch ==' ') || (scanner_ch =='\t') )
  614. -       scanner_get_char();
  615. -}
  616. -
  617. -void scanner_downshift_word()
  618. -{
  619. -   int offset = 'a' - 'A';
  620. -   char * tp;
  621. +   try {
  622. +       (*it)->func();  // Run the command!
  623. +  
  624. +   } catch (errParseString err) {
  625. +       dc_printf("Require string(s) not found: \n");
  626. +       for (int i = 0; i < err.expected_tokens.size(); ++i) {
  627. +           dc_printf("%i: %s\n", err.expected_tokens[i].c_str());
  628. +       }
  629.  
  630. -   strcpy_s( scanner_word_string, scanner_token_string );
  631. +       dc_printf("Found '%s' instead\n", err.found_token.c_str());
  632.    
  633. -   tp = scanner_word_string;
  634. -   do {
  635. -       *tp = (char)((*tp>='A') && (*tp <='Z') ? *tp + offset : *tp) ;
  636. -       tp++;
  637. -   } while (*tp != '\0' );
  638. -}
  639. +   } catch (errParse err) {
  640. +       dc_printf("Invalid argument. Expected %s, found '%s'\n", token_str[err.expected_type], err.found_token.c_str());
  641.  
  642. -void scanner_get_word()
  643. -{
  644. -   while( (scanner_char_code(scanner_ch)==LETTER) || (scanner_char_code(scanner_ch)==DIGIT) ) {
  645. -       *scanner_tokenp++ = scanner_ch;
  646. -       scanner_get_char();
  647.     }
  648. -   *scanner_tokenp = '\0';
  649. -
  650. -   scanner_token = IDENTIFIER;
  651. -}
  652. -
  653. -void scanner_get_string()
  654. -{
  655. -   *scanner_tokenp++ = 34;
  656. -   scanner_get_char();
  657.  
  658. -   while(scanner_ch != 34 ) {
  659. -       *scanner_tokenp++ = scanner_ch;
  660. -       scanner_get_char();
  661. +   // dc_maybe_stuff_string is vulnerable to overflow. Once the errParseOverflow throw class (or w/e) gets
  662. +   // implemented, this last command should be put into its own try{} catch{} block.
  663. +   if (dc_maybe_stuff_string(command)) {
  664. +       dc_printf( "Ignoring the unused command line tail '%s'\n", command.c_str() );
  665.     }
  666. -   scanner_get_char();
  667. -   *scanner_tokenp++ = 34;
  668. -   *scanner_tokenp = '\0';
  669. -   scanner_token = STRING;
  670.  }
  671.  
  672. -void scanner_get_token()
  673. +void dc_draw(bool show_prompt = FALSE)
  674.  {
  675. -   scanner_skip_blanks();
  676. -   scanner_tokenp = scanner_token_string;
  677. -   *scanner_tokenp = 0;
  678. -
  679. -   switch( scanner_char_code(scanner_ch) ) {
  680. -   case QUOTE: scanner_get_string(); break;
  681. -   case EOF_CODE: scanner_token = NO_TOKEN; break;
  682. -   case DIGIT:
  683. -   case LETTER: scanner_get_word(); break;
  684. -   default:
  685. -       *scanner_tokenp++ = scanner_ch;
  686. -       *scanner_tokenp = '\0';
  687. -       scanner_get_char();
  688. -       scanner_token = IDENTIFIER;
  689. -       break;
  690. -   }
  691. +   gr_clear();
  692. +   gr_set_font(dc_font);
  693. +   gr_set_color_fast( &Color_bright );
  694. +   gr_string( 0x8000, 3, dc_title.c_str(), false );
  695.  
  696. -   scanner_downshift_word();
  697. -}
  698. +   gr_set_color_fast( &Color_normal );
  699.  
  700. -void scanner_start_command( char * s )
  701. -{
  702. -   scanner_bufferp = s;
  703. -   scanner_get_char();
  704. -}
  705. +   dc_draw_window(show_prompt);
  706.  
  707. -int Dc_debug_on = 0;
  708. -jmp_buf dc_bad_arg;
  709. +   gr_flip();
  710. +}
  711.  
  712. -void dc_get_arg(uint type)
  713. +void dc_draw_cursor( SCP_string &cmd_string, int x, int y )
  714.  {
  715. -   scanner_get_token();
  716. +   int t;
  717. +   int w, h;   // gr_string width and height
  718.  
  719. -   Dc_command_line = scanner_bufferp;
  720. -   Dc_arg_org = scanner_token_string;
  721. -   Dc_arg = scanner_word_string;
  722. +   t = timer_get_fixed_seconds() / (F1_0/3);
  723. +   if ( t & 1 ) {
  724. +       gr_get_string_size( &w, &h, cmd_string.c_str() );
  725.  
  726. -   if (Dc_debug_on) {
  727. -       dc_printf( "next arg is '%s', was originally '%s'\n", Dc_arg, Dc_arg_org );
  728. -       dc_printf( "Rest of the command line is '%s'\n", Dc_command_line );
  729. +       w %= (DCOLS * Current_font->w);
  730. +       //gr_string( w, debug_y*16, "_" );
  731. +       gr_rect((x + (w + 1)), (y + (h + 1)), 2, Current_font->h, false);
  732.     }
  733. +}
  734.  
  735. -   if ( scanner_token == NO_TOKEN ) {
  736. -       Dc_arg_type = ARG_NONE;
  737. -   } else if ( scanner_token == IDENTIFIER ) {
  738. -       Dc_arg_type = ARG_STRING;
  739. -   } else if ( scanner_token == STRING ) {
  740. -       Dc_arg_type = ARG_QUOTE;
  741. +void dc_draw_window(bool show_prompt)
  742. +{
  743. +   uint cmd_lines;                 // Number of lines for the command string
  744. +   uint buffer_lines;              // Number of lines from the buffer to draw
  745. +   uint i;                         // The current row we're drawing
  746. +   uint j;                         // The current row of the command string we're drawing
  747. +   SCP_string out_str;             // The command string + prompt character
  748. +   SCP_string::iterator str_it;    // Iterator to out_str
  749. +
  750. +   out_str = dc_prompt + dc_command_buf;
  751. +   cmd_lines = (out_str.size() / DCOLS) + 1;
  752. +   if (show_prompt) {
  753. +       buffer_lines = DROWS - cmd_lines;
  754.     } else {
  755. -       Dc_arg_type = ARG_STRING;
  756. +       buffer_lines = DROWS;
  757.     }
  758.  
  759. -   if ( Dc_arg_type & ARG_STRING ) {
  760. -       int i, num_digits, len;
  761. -
  762. -       len = strlen(Dc_arg);
  763. -       num_digits = 0;
  764. -
  765. -       for (i=0; i<len; i++) {
  766. -           if ( scanner_char_table[Dc_arg[i]] == DIGIT ) {
  767. -               num_digits++;
  768. -           }
  769. -
  770. -           if ( num_digits==len ) {
  771. -               Dc_arg_type |= ARG_FLOAT;
  772. -               Dc_arg_float = (float)atof(Dc_arg);
  773. -               if ( !strchr( Dc_arg, '.' )) {
  774. -                   Dc_arg_type |= ARG_INT;
  775. -                   Dc_arg_int = atoi(Dc_arg);
  776. -                   Dc_arg_type |= ARG_UBYTE;
  777. -                   Dc_arg_ubyte = (ubyte)atoi(Dc_arg);
  778. -               }
  779. -           } else {
  780. -               if ( (Dc_arg[0] == '0') && (Dc_arg[1] == 'x') ) {
  781. -                   char *p;
  782. -                   int n;
  783. -                   n = strtol(Dc_arg,&p,0);
  784. -                   if ( *p == 0 ) {
  785. -                       Dc_arg_type |= ARG_INT|ARG_HEX;
  786. -                       Dc_arg_int = n;
  787. -                   }
  788. -               }
  789. -           }
  790. -       }
  791. -
  792. -       if (Dc_debug_on) {
  793. -           if ( Dc_arg_type & ARG_FLOAT ) {
  794. -               dc_printf( "Found float number! %f\n", Dc_arg_float );
  795. -           }
  796. -
  797. -           if ( Dc_arg_type & ARG_INT ) {
  798. -               dc_printf( "Found int number! %d\n", Dc_arg_int );
  799. -           }
  800. -
  801. -           if ( Dc_arg_type & ARG_UBYTE ) {
  802. -               dc_printf( "Found ubyte number! %d\n", Dc_arg_ubyte );
  803. -           }
  804. -
  805. -           if ( Dc_arg_type & ARG_HEX ) {
  806. -               dc_printf( "Found hex number! 0x%x\n", Dc_arg_int );
  807. -           }
  808. -       }
  809. -
  810. -       if ( !stricmp( Dc_arg, "on" ) ) {
  811. -           Dc_arg_type |= ARG_TRUE;
  812. -       }
  813. -       if ( !stricmp( Dc_arg, "true" ) ) {
  814. -           Dc_arg_type |= ARG_TRUE;
  815. -       }
  816. -       if ( !stricmp( Dc_arg, "off" ) ) {
  817. -           Dc_arg_type |= ARG_FALSE;
  818. -       }
  819. -       if ( !stricmp( Dc_arg, "false" ) ) {
  820. -           Dc_arg_type |= ARG_FALSE;
  821. -       }
  822. +   // Ensure the window is not bigger than the buffer
  823. +   CLAMP(DROWS, DROWS_MIN, DBROWS);
  824. +   CLAMP(DCOLS, DCOLS_MIN, DBCOLS);
  825.  
  826. -       if ( !stricmp( Dc_arg, "+" ) ) {
  827. -           Dc_arg_type |= ARG_PLUS;
  828. -       }
  829. -
  830. -       if ( !stricmp( Dc_arg, "-" ) ) {
  831. -           Dc_arg_type |= ARG_MINUS;
  832. -       }
  833. -
  834. -       if ( !stricmp( Dc_arg, "," ) ) {
  835. -           Dc_arg_type |= ARG_COMMA;
  836. -       }
  837. +   // Ensure we don't scroll too far
  838. +   CLAMP(dc_scroll_x, 0, (DBCOLS - DCOLS));
  839. +   if (dc_buffer.size() >= buffer_lines) {
  840. +       CLAMP(dc_scroll_y, 0, (dc_buffer.size() - buffer_lines));
  841. +   } else {
  842. +       dc_scroll_y = 0;    // Disallow vscroll until the buffer is larger than the window
  843.     }
  844.  
  845. -   if ( Dc_arg_type & ARG_INT) {
  846. -       if ( Dc_arg_int ) {
  847. -           Dc_arg_type |= ARG_TRUE;
  848. -       } else {
  849. -           Dc_arg_type |= ARG_FALSE;
  850. +   // Draw the buffer strings
  851. +   for (i = 0; i < buffer_lines; ++i) {
  852. +       if ((i + dc_scroll_y) < dc_buffer.size()) {
  853. +           gr_string(0, ((i * row_height) + row_height), dc_buffer[i + dc_scroll_y].substr(dc_scroll_x).c_str(), false);
  854.         }
  855.     }
  856.  
  857. -   if ( Dc_arg_type & ARG_UBYTE) {
  858. -       if ( Dc_arg_ubyte ) {
  859. -           Dc_arg_type |= ARG_TRUE;
  860. -       } else {
  861. -           Dc_arg_type |= ARG_FALSE;
  862. +   // Draw the command string w/ padding only if the prompt is active.
  863. +   if (show_prompt) {
  864. +       i += 1;     // 1 line between the output and the input text
  865. +       j = 0;
  866. +       gr_set_color_fast(&Color_bright);
  867. +       for (str_it = out_str.begin(); str_it < out_str.end(); ++str_it) {
  868. +           if (j == (DCOLS - 1)) {
  869. +               // Insert a newline char at every place the string needs to return the 'carriage'
  870. +               str_it = out_str.insert(str_it, '\n');
  871. +               j = 0;
  872. +           } else {
  873. +               ++j;
  874. +           }
  875.         }
  876. -   }
  877. +       gr_string(0, ((i * row_height) + row_height), out_str.c_str(), false);
  878.  
  879. -   if ( !(Dc_arg_type&type) ) {
  880. -       if ( (Dc_arg_type & ARG_NONE) && !(type & ARG_NONE) ) {
  881. -           dc_printf( "Error: Not enough parameters.\n" );
  882. -       } else {
  883. -           dc_printf( "Error: '%s' invalid type\n", Dc_arg );
  884. -           longjmp(dc_bad_arg,1);
  885. -       }
  886. +       dc_draw_cursor(out_str, 0, ((i * row_height)));
  887. +       gr_set_color_fast(&Color_normal);
  888.     }
  889.  }
  890.  
  891. -void debug_help();
  892. -
  893. -void debug_do_command(char * command)
  894. +void dc_init(void)
  895.  {
  896. +   extern SCP_vector<debug_command*> dc_commands;
  897.  
  898. -   int i;
  899. -   int mode = 0;
  900. -
  901. -   if ( strlen(command) < 1 ) {
  902. +   if (debug_inited) {
  903.         return;
  904.     }
  905.  
  906. -   Dc_debug_on = 0;
  907. -   Dc_command_line = command;
  908. -   scanner_start_command(command);
  909. +   debug_inited = TRUE;
  910.  
  911. -   if (setjmp(dc_bad_arg) ) {
  912. -       return;
  913. -   }
  914. +   // Sort debug_commands
  915. +   std::sort(dc_commands.begin(), dc_commands.end(), dcmd_less);
  916.  
  917. -   dc_get_arg( ARG_ANY );
  918. +   // Init window settings
  919. +   dc_font = FONT1;
  920. +   row_height = (Current_font->h) * 1.5;   // Row/Line height, in pixels
  921. +   col_width = Current_font->w;            // Col/Character width, in pixels
  922. +   dc_scroll_x = 0;
  923. +   dc_scroll_y = 0;
  924. +   DCOLS = (gr_screen.max_w / col_width) - 1;  // Subtract as needed. Windowed mode has some quirks with the resolution
  925. +   DROWS = (gr_screen.max_h / row_height) - 2;
  926. +   DBCOLS = DCOLS;
  927. +   DBROWS = 2 * DROWS;
  928.  
  929. -   if ( !strcmp( Dc_arg, "debug" ) ) {
  930. -       Dc_debug_on = 1;
  931. -       dc_printf( "Command line: '%s'\n", Dc_command_line );
  932. -       dc_get_arg( ARG_ANY );
  933. -   }
  934. +   // Init History
  935. +   dc_history.clear();
  936. +   dc_history.push_back("");
  937. +   last_oldcommand = dc_history.begin();
  938.  
  939. -   if ( !stricmp( Dc_arg, "xyzzy" ) ) {
  940. -       dc_printf("Nothing happens.\n");
  941. -       return;
  942. -   }
  943. -
  944. -   if ( !strcmp( Dc_arg, "?" ) ) {
  945. -       mode = 1;
  946. -       dc_get_arg( ARG_ANY );
  947. +   // Init buffers
  948. +   dc_buffer.clear();
  949. +   dc_buffer.push_back("");
  950. +  
  951. +   dc_command_buf.reserve(MAX_CLI_LEN);
  952. +   dc_command_buf.clear();
  953.  
  954. -       if ( Dc_arg_type&ARG_NONE ) {
  955. -           debug_help();
  956. -           return;
  957. -       }
  958. -   }
  959. +   sprintf(dc_title, "FreeSpace Open v%i.%i.%i", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD);
  960. +   dc_printf("Debug console started.\n" );
  961. +}
  962.  
  963. -   if ( !strcmp( Dc_arg, "help" ) || !strcmp( Dc_arg, "man" ) ) {
  964. -       mode = 2;
  965. -       dc_get_arg( ARG_ANY );
  966. -       if ( Dc_arg_type&ARG_NONE ) {
  967. -           debug_help();
  968. -           return;
  969. -       }
  970. -   }
  971. +bool dc_pause_output(void)
  972. +{
  973. +   dc_printf("More to follow. Press any key to continue. ESC halts output...");
  974.  
  975. -   if ( strstr( Dc_command_line, "?" ) ) {
  976. -       mode = 2;
  977. -   }
  978. +   int key;
  979. +   bool loop;
  980. +   do {
  981. +       loop = true;
  982.  
  983. -   if ( !(Dc_arg_type&ARG_STRING) ) {
  984. -       dc_printf( "Invalid keyword '%s'\n", Dc_arg );
  985. -       return;
  986. -   }
  987. +       os_poll();
  988.  
  989. +       dc_draw(FALSE);
  990.  
  991. -   if (Dc_debug_on) {
  992. -       dc_printf( "Searching for command '%s'\n", Dc_arg );
  993. -   }
  994. +       key = key_inkey();
  995. +       switch (key) {
  996. +       case KEY_ESC:
  997. +           return true;
  998. +           break;
  999.  
  1000. -   for (i=0; i<Num_debug_commands; i++ ) {
  1001. -       if ( !stricmp( Debug_command[i]->name, Dc_arg ) ) {
  1002. -      
  1003. -           if (mode==0) {
  1004. -               if (Dc_debug_on) {
  1005. -                   dc_printf( "Calling function '%s'\n", Dc_arg );
  1006. -               }
  1007. -               Dc_command = 1;
  1008. -               Dc_help = 0;
  1009. -               Dc_status = 1;
  1010. -           } else if (mode==1) {
  1011. -               if (Dc_debug_on) {
  1012. -                   dc_printf( "Checking status for '%s'\n", Dc_arg );
  1013. -               }
  1014. -               Dc_command = 0;
  1015. -               Dc_help = 0;
  1016. -               Dc_status = 1;
  1017. -           } else {
  1018. -               if (Dc_debug_on) {
  1019. -                   dc_printf( "Doing help for '%s'\n", Dc_arg );
  1020. -               }
  1021. -               Dc_command = 0;
  1022. -               Dc_help = 1;
  1023. -               Dc_status = 0;
  1024. +       case KEY_PAGEUP:
  1025. +           if (dc_scroll_y > 1) {
  1026. +               dc_scroll_y--;
  1027.             }
  1028. +           break;
  1029.  
  1030. -           (*Debug_command[i]->func)();
  1031. -
  1032. -           if (mode==0) {
  1033. -               dc_get_arg(ARG_ANY);
  1034. -               if (!(Dc_arg_type&ARG_NONE)) {
  1035. -                   dc_printf( "Ignoring the unused command line tail '%s %s'\n", Dc_arg_org, Dc_command_line );
  1036. -               }
  1037. +       case KEY_PAGEDOWN:
  1038. +           if (dc_scroll_y < DBROWS) {
  1039. +               dc_scroll_y++;
  1040. +           } else {
  1041. +               dc_scroll_y = DBROWS;
  1042.             }
  1043. +           break;
  1044.  
  1045. -           return;
  1046. +       case KEY_LEFT:
  1047. +           // TODO: Scroll Left
  1048. +           break;
  1049. +       case KEY_RIGHT:
  1050. +           // TODO: Scroll Right
  1051. +           break;
  1052. +       case 0:
  1053. +           // No key pressed
  1054. +           break;
  1055. +       default:
  1056. +           // Non-control key pressed, break.
  1057. +           loop = false;
  1058.         }
  1059. -   }
  1060. +   } while (loop);
  1061.  
  1062. -   dc_printf( "Unknown command '%s'\n", Dc_arg );
  1063. -}
  1064. +   dc_printf("\n");
  1065. +   return false;
  1066. +};
  1067.  
  1068. -void debug_draw()
  1069. +void dc_printf(const char *format, ...)
  1070.  {
  1071. -   int i;
  1072. -
  1073. -   gr_clear();
  1074. -   gr_set_font(FONT1);
  1075. -   gr_set_color_fast( &Color_bright );
  1076. -   gr_string( 0x8000, 3, "Debug Console" );
  1077. -
  1078. -   gr_set_color_fast( &Color_normal );
  1079. -
  1080. -   for (i=0; i<DROWS; i++ ) {
  1081. -       gr_string( 0, i*16+16, debug_text[i] );
  1082. -   }
  1083. -
  1084. -   int t = timer_get_fixed_seconds() / (F1_0/3);
  1085. -   if ( t & 1 ) {
  1086. -       int w,h;
  1087. -       char c;
  1088. -
  1089. -       c = debug_text[debug_y][command_line_pos+1];
  1090. -       debug_text[debug_y][command_line_pos+1] = 0;
  1091. -
  1092. -       gr_get_string_size( &w, &h, debug_text[debug_y] );
  1093. +   SCP_string tmp;
  1094. +   va_list args;
  1095. +   SCP_string::iterator tmp_it;
  1096.  
  1097. -       //gr_string( w, debug_y*16, "_" );
  1098. -       gr_rect(w+1,debug_y*16+1+16,2,14);
  1099. +   va_start(args, format);
  1100. +   vsprintf(tmp, format, args);
  1101. +   va_end(args);
  1102.  
  1103. -       debug_text[debug_y][command_line_pos+1] = c;
  1104. +   for (tmp_it = tmp.begin(); tmp_it != tmp.end(); ++tmp_it) {
  1105. +       dc_putc(*tmp_it);
  1106.     }
  1107. -
  1108. -   gr_flip();
  1109.  }
  1110.  
  1111. -
  1112. -void debug_output( char c )
  1113. +void dc_putc(char c)
  1114.  {
  1115. -   if ( c == '\t' ) {
  1116. -       int next_tab = ((debug_x/28)+1)*28;
  1117. -
  1118. -       if ( next_tab >= DCOLS-1 ) {
  1119. -           debug_x=0;
  1120. -           debug_y++;
  1121. -           scroll_times++;
  1122. -           if ( debug_y >= DROWS ) {
  1123. -               int i;
  1124. -               for (i=1; i<DROWS; i++ ) {
  1125. -                   strcpy_s( debug_text[i-1], debug_text[i] );
  1126. -               }
  1127. -               debug_y = DROWS-1;
  1128. -               debug_x = 0;
  1129. -               debug_text[debug_y][debug_x] = 0;
  1130. -           }
  1131. -           debug_text[debug_y][debug_x] = 0;
  1132. +   SCP_string* line_str = &(dc_buffer.back());
  1133. +   SCP_string temp_str;
  1134. +   int i;
  1135. +   int w;
  1136. +
  1137. +   if (c == ' ') {
  1138. +       /**
  1139. +        * Push c onto the temp_str and get its gr_string width
  1140. +        *
  1141. +        * If we run out of room on the line, or
  1142. +        * If we run out of room on the screen, change c to a '\n' and let subsequent block handle it,
  1143. +        * Else, push the space onto the line and bail
  1144. +        */
  1145. +       temp_str = *line_str;
  1146. +       temp_str.push_back(c);
  1147. +       gr_get_string_size(&w, NULL, temp_str.c_str());
  1148. +
  1149. +       if ((temp_str.size() >= DBCOLS) || (w > gr_screen.max_w)) {
  1150. +           c = '\n';
  1151. +      
  1152. +       } else {
  1153. +           lastwhite = temp_str.size();
  1154. +           *line_str = temp_str;
  1155.             return;
  1156.         }
  1157. -  
  1158. -       for ( ; debug_x < next_tab; ) {
  1159. -           debug_text[debug_y][debug_x++] = ' ';
  1160. -       }
  1161. -       debug_text[debug_y][debug_x] = 0;
  1162. -       return;
  1163.     }
  1164.  
  1165. -   if ( (c == '\n') || (debug_x >= DCOLS-1) ) {
  1166. -       debug_x=0;
  1167. -       debug_y++;
  1168. -       scroll_times++;
  1169. -       if ( debug_y >= DROWS ) {
  1170. -           int i;
  1171. -           for (i=1; i<DROWS; i++ ) {
  1172. -               strcpy_s( debug_text[i-1], debug_text[i] );
  1173. -           }
  1174. -           debug_y = DROWS-1;
  1175. -           debug_x = 0;
  1176. -           debug_text[debug_y][debug_x] = 0;
  1177. -       }
  1178. -       debug_text[debug_y][debug_x] = 0;
  1179. -       if ( c == '\n' ) {
  1180. +   if (c == '\t') {
  1181. +       /**
  1182. +        * Calculate how many spaces to put in to align tabs,
  1183. +        * Append temp_str with the spaces and get its gr_string width
  1184. +        *
  1185. +        * If we run out of room on the line, or
  1186. +        * If we run out of room on the screen, change c to a '\n' and let subsequent block handle it,
  1187. +        * Else, copy temp_str onto the line, update the lastwhite index, and bail
  1188. +        */
  1189. +       i = DTABS - (line_str->size() % DTABS);
  1190. +       temp_str = *line_str;
  1191. +       temp_str.append(i, ' ');
  1192. +       gr_get_string_size(&w, NULL, temp_str.c_str());
  1193. +
  1194. +       if ((temp_str.size() >= DBCOLS) || (w > gr_screen.max_w)) {
  1195. +           c = '\n';
  1196. +
  1197. +       } else {
  1198. +           lastwhite = temp_str.size();
  1199. +           *line_str = temp_str;
  1200.             return;
  1201.         }
  1202.     }
  1203.  
  1204. -   debug_text[debug_y][debug_x++] = c;
  1205. -   debug_text[debug_y][debug_x] = 0;
  1206. -}
  1207. -
  1208. -void dc_printf(char *format, ...)
  1209. -{
  1210. -   char tmp[DCOLS*DROWS];
  1211. -   va_list args;
  1212. +   if (c == '\n') {
  1213. +       /**
  1214. +        * Trash whatever char happens to be past (DBCOLS - 1),
  1215. +        * Push a blank line onto the dc_buffer from the bottom,
  1216. +        * Increment the scroller, if needed,
  1217. +        * Trash the topmost line(s) in the buffer,
  1218. +        * Reset the lastwhite index,
  1219. +        * Increment the lastline counter, and finally
  1220. +        * bail
  1221. +        */
  1222. +       if (line_str->size() > DBCOLS) {
  1223. +           line_str->resize(DBCOLS);
  1224. +       }
  1225. +       dc_buffer.push_back("");
  1226.  
  1227. -   va_start(args, format);
  1228. -   vsprintf(tmp, format, args);
  1229. -   va_end(args);
  1230. +       if ((dc_buffer.size() > DROWS) && (dc_scroll_y < SCROLL_Y_MAX)) {
  1231. +           dc_scroll_y++;
  1232. +       }
  1233.  
  1234. -   char *p = tmp;
  1235. -   while( *p != '\0' ) {
  1236. -       debug_output(*p);
  1237. -       p++;
  1238. -   }
  1239. -}
  1240. +       while (dc_buffer.size() > DBROWS) {
  1241. +           dc_buffer.pop_front();
  1242. +       }
  1243.  
  1244. -void debug_init()
  1245. -{
  1246. -   int i;
  1247. -   if ( debug_inited ) {
  1248. +       lastwhite = 0;
  1249. +       lastline++;
  1250.         return;
  1251.     }
  1252.  
  1253. -   debug_inited = 1;
  1254. +   // By this point, c is probably a writable character
  1255. +   temp_str = *line_str;
  1256. +   temp_str.push_back(c);
  1257. +   gr_get_string_size(&w, NULL, temp_str.c_str());
  1258. +
  1259. +   if ((temp_str.size() >= DBCOLS) || (w > gr_screen.max_w)) {
  1260. +       /**
  1261. +        * Word wrapping
  1262. +        * Save the word, clear the line of the word, push new line with the word on it
  1263. +        * Update scroll_y, if needed,
  1264. +        * Pop off old lines, and finally
  1265. +        * Push new character onto the new line
  1266. +        */
  1267. +       temp_str = line_str->substr(lastwhite);
  1268. +       line_str->resize(lastwhite);
  1269. +       dc_buffer.push_back(temp_str);
  1270. +       line_str = &dc_buffer.back();
  1271. +
  1272. +       if ((dc_buffer.size() > DROWS) && (dc_scroll_y < SCROLL_Y_MAX)) {
  1273. +           dc_scroll_y++;
  1274. +       }
  1275.  
  1276. -   debug_x=0;
  1277. -   debug_y=0;
  1278. +       while (dc_buffer.size() > DBROWS) {
  1279. +           dc_buffer.pop_front();
  1280. +       }
  1281.  
  1282. -   for (i=0; i<DROWS; i++ ) {
  1283. -       debug_text[i][0] = 0;
  1284. +       lastwhite = 0;
  1285. +       lastline++;
  1286. +       line_str->push_back(c);
  1287. +       return;
  1288.     }
  1289.  
  1290. -   dc_printf("Debug console started.\n" );
  1291. +   // Else, just push the char onto the line
  1292. +   line_str->push_back(c);
  1293.  }
  1294.  
  1295. -void debug_console( void (*_func)() )
  1296. +bool dcmd_less(debug_command *first, debug_command *second)
  1297.  {
  1298. -   int done = 0;
  1299. +   return (strcmp(first->name, second->name) < 0);
  1300. +}
  1301.  
  1302. -   scanner_init();
  1303. +void debug_console(void (*_func)(void))
  1304. +{
  1305. +   int done = 0;
  1306.  
  1307.     while( key_inkey() ) {
  1308.         os_poll();
  1309.     }
  1310.  
  1311.     if ( !debug_inited ) {
  1312. -       debug_init();
  1313. +       dc_init();
  1314.     }
  1315.  
  1316. -   debug_draw();
  1317. +   dc_draw(TRUE);
  1318.  
  1319.     while (!done) {
  1320.         // poll the os
  1321. @@ -613,135 +501,98 @@ void debug_console( void (*_func)() )
  1322.  
  1323.         case KEY_SHIFTED+KEY_ENTER:
  1324.         case KEY_ESC:
  1325. -           done=1; break;
  1326. +           done = TRUE;
  1327. +           break;
  1328.  
  1329.         case KEY_BACKSP:
  1330. -           if ( command_line_pos > 0 ) {
  1331. -               command_line[--command_line_pos] = 0;
  1332. +           if (!dc_command_buf.empty()) {
  1333. +               dc_command_buf.erase(dc_command_buf.end() - 1);
  1334.             }
  1335.             break;
  1336.  
  1337.         case KEY_F3:
  1338. -           if ( last_oldcommand > -1 ) {
  1339. -               strcpy_s( command_line, oldcommand_line[last_oldcommand] );
  1340. -               command_line_pos = strlen(command_line);
  1341. -               command_line[command_line_pos] = 0;
  1342. -           }
  1343. -           break;
  1344. -
  1345.         case KEY_UP:
  1346. -           command_scroll--;
  1347. -           if (command_scroll<0) {
  1348. -               command_scroll = last_oldcommand;
  1349. +           if (last_oldcommand < (dc_history.end() - 1)) {
  1350. +               ++last_oldcommand;
  1351.             }
  1352.  
  1353. -           if ( command_scroll > -1 ) {
  1354. -               strcpy_s( command_line, oldcommand_line[command_scroll] );
  1355. -               command_line_pos = strlen(command_line);
  1356. -               command_line[command_line_pos] = 0;
  1357. -           }
  1358. +           dc_command_buf = *last_oldcommand;
  1359.             break;
  1360.  
  1361.         case KEY_DOWN:
  1362. -           command_scroll++;
  1363. -           if (command_scroll>last_oldcommand) {
  1364. -               command_scroll = 0;
  1365. -           }
  1366. -           if (command_scroll>last_oldcommand) {
  1367. -               command_scroll = -1;
  1368. +           if (last_oldcommand > dc_history.begin()) {
  1369. +               --last_oldcommand;
  1370.             }
  1371. -           if ( command_scroll > -1 ) {
  1372. -               strcpy_s( command_line, oldcommand_line[command_scroll] );
  1373. -               command_line_pos = strlen(command_line);
  1374. -               command_line[command_line_pos] = 0;
  1375. -           }
  1376. -           break;
  1377.  
  1378. -       case KEY_ENTER: {
  1379. -           debug_output( '\n' );
  1380. -           debug_draw();
  1381. -
  1382. -           debug_do_command(command_line);
  1383. +           dc_command_buf = *last_oldcommand;
  1384. +           break;
  1385.  
  1386. -           int i, found = 0;
  1387. -           for (i=0; i<=last_oldcommand; i++ ) {
  1388. -               if (!stricmp( oldcommand_line[i], command_line )) {
  1389. -                   found = 1;
  1390. -               }
  1391. -           }
  1392. -           if ( !found ) {
  1393. -               if ( last_oldcommand < DEBUG_HISTORY-1 ) {
  1394. -                   last_oldcommand++;
  1395. -                   strcpy_s( oldcommand_line[last_oldcommand], command_line);
  1396. -               } else {
  1397. -                   int iLoop;
  1398. -                   for (iLoop=0; iLoop<last_oldcommand; iLoop++ ) {
  1399. -                       strcpy_s( oldcommand_line[iLoop], oldcommand_line[iLoop+1] );
  1400. -                   }
  1401. -                   strcpy_s( oldcommand_line[last_oldcommand], command_line);
  1402. -               }
  1403. +       case KEY_PAGEUP:
  1404. +           if (dc_scroll_y > 1) {
  1405. +               dc_scroll_y--;
  1406.             }
  1407. +           break;
  1408.  
  1409. -           debug_output( '\n' );
  1410. -           command_line_pos = 0;
  1411. -           command_line[command_line_pos] = 0;
  1412. +       case KEY_PAGEDOWN:
  1413. +           if (dc_scroll_y < (DBROWS - DROWS)) {
  1414. +               dc_scroll_y++;
  1415. +           } else {
  1416. +               dc_scroll_y = (DBROWS - DROWS);
  1417. +           }
  1418. +           break;
  1419.  
  1420. -           command_scroll = 0;
  1421. +       case KEY_ENTER:
  1422. +           dc_scroll_y = (DBROWS - DROWS);         // Set the scroll to look at the bottom
  1423. +           last_oldcommand = dc_history.begin();   // Reset the last oldcommand
  1424. +           lastline = 0;   // Reset the line counter
  1425. +
  1426. +           // Clear the command line on the window, but don't print the prompt until the command has processed
  1427. +           // Stuff a copy of the command line onto the history
  1428. +           // Search for the command
  1429. +               // If not found:
  1430. +               //   abort,
  1431. +               //   dc_printf("Error: Invalid or Missing command %s", cmd.c_str()), and
  1432. +               //   dc_printf(dc_prompt) when ready for input
  1433. +           // Call the function for that command, and strip the cmd token from the command line string
  1434. +           if (dc_command_buf.empty()) {
  1435. +               dc_printf("No command given.\n");
  1436. +               break;
  1437. +           } // Else, continue to process the cmd_line
  1438. +
  1439. +           // z64: Thread Note: Maybe lock a mutex here to allow a previous DCF to finish/abort before starting a new one
  1440. +           // z64: We'll just assume we won't be here unless a command has finished...
  1441. +           dc_history.push_front(dc_command_buf);  // Push the command onto the history queue
  1442. +           last_oldcommand = dc_history.begin();   // Reset oldcommand
  1443. +
  1444. +           while (dc_history.size() > DCMDS) {
  1445. +               dc_history.pop_back();          // Keep the commands less than or equal to DCMDS
  1446. +           }
  1447.  
  1448. -           }
  1449. +           dc_command_str = dc_command_buf;    // Xfer to the command string for processing
  1450. +           dc_command_buf.resize(0);           // Nullify the buffer
  1451. +           dc_printf("%s%s\n", dc_prompt, dc_command_str.c_str()); // Print the command w/ prompt.
  1452. +           dc_draw(FALSE);                 // Redraw the console without the command line.
  1453. +           dc_do_command(&dc_command_str); // Try to do the command
  1454.             break;
  1455. -       default: {
  1456. -               ubyte c = (ubyte)key_to_ascii(k);
  1457. -               if ( c != 255 ) {
  1458. -                   command_line[command_line_pos++] = c;
  1459. -                   command_line[command_line_pos] = 0;
  1460. -               }
  1461. +
  1462. +       default:
  1463. +           // Not any of the control key codes, so it's probably a letter or number.
  1464. +           ubyte c = (ubyte)key_to_ascii(k);
  1465. +           if ((c != 255) && (dc_command_buf.size() < MAX_CLI_LEN)) {
  1466. +               dc_command_buf.push_back(c);
  1467.             }
  1468.         }
  1469.  
  1470. -       strcpy_s( debug_text[debug_y], ">" );
  1471. -       strcat_s( debug_text[debug_y], command_line );
  1472. -       debug_draw();
  1473. -
  1474. +       // Do the passed function
  1475.         if ( _func ) {
  1476.             _func();
  1477.         }
  1478. +
  1479. +       // All done, and ready for new entry
  1480. +       dc_draw(TRUE);
  1481.     }
  1482.  
  1483.     while( key_inkey() ) {
  1484.         os_poll();
  1485.     }
  1486.  }
  1487. -
  1488. -void debug_help()
  1489. -{
  1490. -   int s, i;
  1491. -
  1492. -   dc_printf( "Available functions:\n\n" );
  1493. -
  1494. -   s = scroll_times;
  1495. -   for (i=0; i<Num_debug_commands; i++ ) {
  1496. -       dc_printf( " %s - %s\n", Debug_command[i]->name, Debug_command[i]->help );
  1497. -
  1498. -       if ( scroll_times - s > DROWS - 3 ) {
  1499. -           int k;
  1500. -           dc_printf( "       Press a key...B for back\n" );
  1501. -           debug_draw();
  1502. -           k = key_getch();
  1503. -           s = scroll_times;
  1504. -           if ( k == KEY_B ) {
  1505. -               i -= ((DROWS-3)*2);
  1506. -               if ( i <= 0 ) {
  1507. -                   i = -1;
  1508. -               }
  1509. -           }
  1510. -       }
  1511. -       debug_draw();
  1512. -   }
  1513. -   dc_printf( "\n" );
  1514. -
  1515. -   dc_printf( "Typing '? function_name' will give the current status.\n" );
  1516. -   dc_printf( "Typing 'function_name ?' will give help on the function.\n" );
  1517. -   dc_printf( "Typing ? or help will give you help.\n");
  1518. -   dc_printf( "F3 selects last command line.\n" );
  1519. -}
  1520. diff --git a/code/debugconsole/console.h b/code/debugconsole/console.h
  1521. new file mode 100644
  1522. index 0000000..c16246e
  1523. --- /dev/null
  1524. +++ b/code/debugconsole/console.h
  1525. @@ -0,0 +1,268 @@
  1526. +#ifndef _CONSOLE_H
  1527. +#define _CONSOLE_H
  1528. +/*
  1529. + * z64555's debug console, created for the FreeSpace Source Code project
  1530. + *
  1531. + * Portions of this source code are based on works by Volition, Inc. circa 1999. You may not sell or otherwise
  1532. + * commercially exploit the source or things you created based on the source.
  1533. + */
  1534. +
  1535. +/**
  1536. + * @file console.h
  1537. + * @brief An overhauled/updated debug console to allow monitoring, testing, and general debugging of new features.
  1538. + *
  1539. + * @details
  1540. + * Of key interest is Volition's DCF macro, which adds the function argument to the available command list in the
  1541. + * debug console. These functions may be defined in the .cpp file that they are related to, but it is recommended
  1542. + * that they be in their own .cpp if they have multiple sub-arguments (ex: Git has its sub-arguments delimited by
  1543. + * a pair of -'s, or --)
  1544. + */
  1545. +
  1546. +#include "debugconsole/consoleparse.h"
  1547. +#include "globalincs/pstypes.h"
  1548. +#include "globalincs/vmallocator.h"
  1549. +
  1550. +class debug_command;
  1551. +
  1552. +/**
  1553. + * @def DCF
  1554. + *
  1555. + * @brief The potent DCF macro, used to define new debug commands for the console.
  1556. + *
  1557. + * @param function_name[in] The name of the function, as shown in the debug console
  1558. + * @param help_txt[in] The short-help text, as shown as listed from the 'help' command
  1559. + *
  1560. + * @details
  1561. + * Each DCF is responsible for getting data from the debug console's command line. The parsing functions for the
  1562. + * command line have been set up to have similar syntax and usage as the parselo commands. (see consoleparse.h)
  1563. + * Most, if not all, argument and subcommand strings should be parsed by the dc_optional_string functions.
  1564. + * Usage example:
  1565. + * DCF(toggle_it, "description")
  1566. + * {
  1567. + *     if (dc_optional_string_either("help", "--help")) {
  1568. + *         dc_printf("Usage: sample. Toggles This_var on/off\n");
  1569. + *
  1570. + *     } else if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  1571. + *         dc_printf("This_var is %s\n", (This_var ? "ON" : "OFF"));
  1572. + *
  1573. + *     } else {
  1574. + *         This_var = !This_var;
  1575. + *
  1576. + *     }
  1577. + * }
  1578. + *
  1579. + *  In the console, the command would be listed as 'toggle_it', and dcf_help would display it as:
  1580. + *      toggle_it  - Usage: sample. Toggles This_var on/off.
  1581. + *  Note: The only allowed function type is a void fn( void )
  1582. + */
  1583. +#define DCF(function_name, help_text)  \
  1584. +       void dcf_##function_name(); \
  1585. +       debug_command dcmd_##function_name(#function_name, help_text, dcf_##function_name); \
  1586. +       void dcf_##function_name()
  1587. +
  1588. +/**
  1589. + *  @def Shortcut for debug commands that toggle a bool, such as Show_lightning
  1590. + *  
  1591. + *  @param [in] function_name Name of the function, as shown in the debug console
  1592. + *  @param [in] bool_variable Name of the variable to allow toggling.
  1593. + */
  1594. +#define DCF_BOOL(function_name, bool_variable) \
  1595. +   void dcf_##function_name();     \
  1596. +   debug_command dcmd_##function_name(#function_name, "Sets or toggles the boolean: "#bool_variable, dcf_##function_name );    \
  1597. +   void dcf_##function_name() {    \
  1598. +       bool bool_tmp = (bool) bool_variable;   \
  1599. +       if (dc_optional_string_either("help", "--help")) {  \
  1600. +               dc_printf( "Usage: %s [bool]\nSets %s to true or false.  If nothing passed, then toggles it.\n", #function_name, #bool_variable );  \
  1601. +               return;     \
  1602. +       }   \
  1603. +       if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
  1604. +           dc_printf("%s = %s\n", #bool_variable, (bool_variable ? "TRUE" : "FALSE"));     \
  1605. +           return;     \
  1606. +       }   \
  1607. +       if (!dc_maybe_stuff_boolean(&bool_tmp)) {   \
  1608. +           bool_variable ? (bool_variable = 0) : (bool_variable = 1);  \
  1609. +       } else { \
  1610. +           bool_tmp ? (bool_variable = 1) : (bool_variable = 0);   \
  1611. +       }   \
  1612. +       dc_printf("%s set to %\ns", #bool_variable, (bool_variable ? "TRUE" : "FALSE"));    \
  1613. +   }
  1614. +
  1615. +
  1616. +/**
  1617. + *  @def Same as DCF_BOOL, but with custom help strings
  1618. + *  
  1619. + *  @param [in] function_name Name of the function, as shown in the debug console
  1620. + *  @param [in] bool_variable Name of the variable to allow toggling.
  1621. + */
  1622. +#define DCF_BOOL2(function_name, bool_variable, short_help, long_help) \
  1623. +   void dcf_##function_name();     \
  1624. +   debug_command dcmd_##function_name(#function_name, short_help, dcf_##function_name );   \
  1625. +   void dcf_##function_name() {    \
  1626. +       if (dc_optional_string_either("help", "--help")) {  \
  1627. +           dc_printf( #long_help );    \
  1628. +               return;     \
  1629. +       }   \
  1630. +       if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
  1631. +           dc_printf("%s = %s\n", #function_name, (bool_variable ? "TRUE" : "FALSE"));     \
  1632. +           return;     \
  1633. +       }   \
  1634. +       if (!dc_maybe_stuff_boolean(&bool_variable)) {  \
  1635. +           bool_variable = !bool_variable; \
  1636. +       }   \
  1637. +   }
  1638. +
  1639. + /**
  1640. +  * @def Shortcut for single-variable setters/monitors
  1641. +  *
  1642. +  * @param [in] function_name
  1643. +  * @param [in] float_variable
  1644. +  * @param [in] short_help
  1645. +  */
  1646. + #define DCF_FLOAT(function_name, float_variable, short_help)  \
  1647. +   void dcf_##function_name();     \
  1648. +   debug_command dcmd_##function_name(#function_name, short_help, dcf_##function_name );   \
  1649. +   void dcf_##function_name() {    \
  1650. +       float value;    \
  1651. +       if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
  1652. +           dc_printf("%s = %f\n", #float_variable, float_variable);        \
  1653. +           return;     \
  1654. +       }   \
  1655. +       dc_stuff_float(&value); \
  1656. +       float_variable = value; \
  1657. +       dc_printf("%s set to %f\n", #float_variable, float_variable);   \
  1658. +   }
  1659. +
  1660. + /**
  1661. +  * @def Shortcut for single-variable setters/monitors with lower/upper bounds clamping
  1662. +  *
  1663. +  * @param [in] function_name
  1664. +  * @param [in] float_variable
  1665. +  * @param [in] lower_bounds
  1666. +  * @param [in] upper_bounds
  1667. +  * @param [in] short_help
  1668. +  */
  1669. + #define DCF_FLOAT2(function_name, float_variable, lower_bounds, upper_bounds, short_help) \
  1670. +   void dcf_##function_name();     \
  1671. +   debug_command dcmd_##function_name(#function_name, short_help, dcf_##function_name );   \
  1672. +   void dcf_##function_name() {    \
  1673. +       float value;    \
  1674. +       if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
  1675. +           dc_printf("%s = %f\n", #float_variable, float_variable);        \
  1676. +           return;     \
  1677. +       }   \
  1678. +       dc_stuff_float(&value); \
  1679. +       CLAMP(float_variable, lower_bounds, upper_bounds);  \
  1680. +       float_variable = value; \
  1681. +       dc_printf("%s set to %f\n", #float_variable, float_variable);   \
  1682. +   }
  1683. +
  1684. + /**
  1685. +  * @def Shortcut for single-variable setters/monitors
  1686. +  *
  1687. +  * @param [in] function_name
  1688. +  * @param [in] int_variable
  1689. +  * @param [in] short_help
  1690. +  */
  1691. + #define DCF_INT(function_name, int_variable, short_help)  \
  1692. +   void dcf_##function_name();     \
  1693. +   debug_command dcmd_##function_name(#function_name, short_help, dcf_##function_name );   \
  1694. +   void dcf_##function_name() {    \
  1695. +       int value;  \
  1696. +       if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
  1697. +           dc_printf("%s = %i\n", #int_variable, int_variable);        \
  1698. +           return;     \
  1699. +       }   \
  1700. +       dc_stuff_int(&value);   \
  1701. +       int_variable = value;   \
  1702. +       dc_printf("%s set to %i\n", #int_variable, int_variable);   \
  1703. +   }
  1704. +
  1705. + /**
  1706. +  * @def Shortcut for single-variable setters/monitors with lower/upper bounds clamping
  1707. +  *
  1708. +  * @param [in] function_name
  1709. +  * @param [in] int_variable
  1710. +  * @param [in] lower_bounds
  1711. +  * @param [in] upper_bounds
  1712. +  * @param [in] short_help
  1713. +  */
  1714. + #define DCF_INT2(function_name, int_variable, lower_bounds, upper_bounds, short_help) \
  1715. +   void dcf_##function_name();     \
  1716. +   debug_command dcmd_##function_name(#function_name, short_help, dcf_##function_name );   \
  1717. +   void dcf_##function_name() {    \
  1718. +       int value;  \
  1719. +       if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
  1720. +           dc_printf("%s = %i\n", #int_variable, int_variable);        \
  1721. +           return;     \
  1722. +       }   \
  1723. +       dc_stuff_int(&value);   \
  1724. +       CLAMP(int_variable, lower_bounds, upper_bounds);    \
  1725. +       int_variable = value;   \
  1726. +       dc_printf("%s set to %i\n", #int_variable, int_variable);   \
  1727. +   }
  1728. +
  1729. +/**
  1730. + *  @class debug_command
  1731. + *  @brief Class to aggregate a debug command with its name (as shown in the console) and short help.
  1732. + *  
  1733. + *  @details
  1734. + *  Note: Long help, as evoked by '<command> help', should be handled by the function itself. It is recommended
  1735. + *  that arguments that have sub-arguments be in their own function, so as to aide in organization and to keep the
  1736. + *  size of the command function down.
  1737. + */
  1738. +class debug_command {
  1739. +public:
  1740. +   const char *name;       //!< The name of the command, as shown in the debug console
  1741. +   const char *help;       //!< The short help string, as shown by 'help <command>'
  1742. +   void (*func)(); //!< Pointer to the function that to run when this command is evoked
  1743. +
  1744. +   /**
  1745. +   * @brief Adds a debug command to the debug_commands map, if it isn't in there already.
  1746. +   *
  1747. +   * @details The DCF macro more or less guarantees that a command won't be duplicated on compile time. But no harm in
  1748. +   *   some extra caution.
  1749. +   */
  1750. +   debug_command(const char *name, const char *help, void (*func)());
  1751. +};
  1752. +
  1753. +/**
  1754. + * @class is_dcmd
  1755. + * @brief Predicate class used to search for a dcmd by name
  1756. + */
  1757. +class is_dcmd {
  1758. +public:
  1759. +   const char *name;
  1760. +
  1761. +   is_dcmd(const char *_name) : name(_name) {};
  1762. +
  1763. +   bool operator() (debug_command* dcmd)
  1764. +   {
  1765. +       return (strcmp(name, dcmd->name) == 0);
  1766. +   }
  1767. +};
  1768. +
  1769. +extern bool Dc_debug_on;
  1770. +extern uint lastline;
  1771. +extern SCP_string dc_command_str;  // The rest of the command line, from the end of the last processed arg on.
  1772. +
  1773. +/**
  1774. + * @brief   Pauses the output of a command and allows user to scroll through the output history.
  1775. + *
  1776. + * @details Returns true if user has pressed Esc, returns false otherwise. Use this in your function to (safely?) break
  1777. + *     out of the loop it's presumably in.
  1778. + */
  1779. +bool dc_pause_output(void);
  1780. +
  1781. +/**
  1782. + * @brieft Prints the given char string to the debug console
  1783. + * @details See the doc for std::printf() for formating and more details
  1784. + */
  1785. +void dc_printf(const char *format, ...);
  1786. +
  1787. +/**
  1788. + * @brief Opens and processes the debug console. (Blocking call)
  1789. + * @details TODO: Make this a non-blocking call so that the game can still run while the debug console is open.
  1790. + */
  1791. +void debug_console(void (*func)(void) = NULL);
  1792. +
  1793. +#endif // _CONSOLE_H
  1794. \ No newline at end of file
  1795. diff --git a/code/debugconsole/consolecmds.cpp b/code/debugconsole/consolecmds.cpp
  1796. new file mode 100644
  1797. index 0000000..25dd8c7
  1798. --- /dev/null
  1799. +++ b/code/debugconsole/consolecmds.cpp
  1800. @@ -0,0 +1,123 @@
  1801. +/*
  1802. + * z64555's debug console
  1803. + * Created for the FreeSpace Source Code project
  1804. + *
  1805. + * Portions of this source code are based on works by Volition, Inc. circa
  1806. + * 1999. You may not sell or otherwise commercially exploit the source or things you
  1807. + * created based on the source
  1808. + */
  1809. +
  1810. +/**
  1811. + *  @file consolecmds.cpp
  1812. + *  
  1813. + *  @brief This file contains the "built-in" commands for the debug console, and is listed by the 'help' and '?' commands
  1814. + *  
  1815. + *  @details
  1816. + *  All other debug commands should be in their respective files and added to the console with the DCF macro. For
  1817. + *  further documentation, please see console.h
  1818. + */
  1819. +
  1820. +#include "debugconsole/console.h"
  1821. +#include "debugconsole/consoleparse.h"
  1822. +#include "globalincs/pstypes.h"
  1823. +#include "globalincs/vmallocator.h"
  1824. +#include "io/key.h"
  1825. +
  1826. +#include <algorithm>
  1827. +
  1828. +// ========================= GLOBALS =========================
  1829. +SCP_vector<debug_command*> dc_commands;
  1830. +typedef SCP_vector<debug_command*>::iterator dc_commands_it;
  1831. +
  1832. +// ========================= LOCALS ==========================
  1833. +// dcf_shell commands
  1834. +void dc_shell_font( void );
  1835. +void dc_shell_resize( void );
  1836. +void dc_shell_resize_buf( void );
  1837. +
  1838. +// =================== class debug_command ===================
  1839. +debug_command::debug_command(const char *_name, const char *_help, void (*_func)())
  1840. +   : name(_name), help(_help), func(_func)
  1841. +{
  1842. +   dc_commands_it it = std::find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(_name));
  1843. +  
  1844. +   if (it != dc_commands.end()) {
  1845. +       Int3();     // Command already exists! Somebody didn't use the DCF macro as they should've...
  1846. +   }
  1847. +
  1848. +   dc_commands.push_back(this);
  1849. +}
  1850. +
  1851. +// ============================== IMPLEMENTATIONS =============================
  1852. +
  1853. +DCF(debug, "Runs a command in debug mode.")
  1854. +{
  1855. +   SCP_string command = "";
  1856. +   Dc_debug_on = true;
  1857. +
  1858. +   dc_stuff_string_white(command);
  1859. +
  1860. +   if (command == "") {
  1861. +       dc_printf("<debug> No command given\n");
  1862. +       return;
  1863. +   } // Else, command is present.
  1864. +
  1865. +   dc_commands_it it = std::find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(command.c_str()));
  1866. +
  1867. +   if (it == dc_commands.end()) {
  1868. +       dc_printf("<debug> Command not found: '%s'\n", command.c_str());
  1869. +       return;
  1870. +   } // Else, command exists. Run it.
  1871. +
  1872. +   dc_printf("<debug> Executing command: '%s'\n", command.c_str());
  1873. +   // try {
  1874. +   (*it)->func();
  1875. +   // } catch {
  1876. +   // }
  1877. +
  1878. +   Dc_debug_on = false;
  1879. +}
  1880. +
  1881. +DCF(help, "Displays the help list." )
  1882. +{
  1883. +   extern uint DBROWS;
  1884. +
  1885. +   SCP_string command = "";
  1886. +
  1887. +   dc_maybe_stuff_string_white(command);
  1888. +   if ((command == "help") || (command == "man"))
  1889. +   {
  1890. +       // Moron filter :D
  1891. +       dc_printf("GTVA Command: Sorry pilot. You're on your own.\n");
  1892. +       return;
  1893. +
  1894. +   } else if (command != "") {
  1895. +       dc_commands_it it = find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(command.c_str()));
  1896. +
  1897. +       if (it == dc_commands.end()) {
  1898. +           dc_printf("Command not found: '%s'\n", command.c_str());
  1899. +           return;
  1900. +       }
  1901. +
  1902. +       dc_printf("%s\n", (*it)->help);
  1903. +       return;
  1904. +   } // Else, command line is empty, print out the help list
  1905. +
  1906. +   dc_printf("FreeSpace Open Debug Console\n");
  1907. +   dc_printf(" These commands are defined internally.\n");
  1908. +   dc_printf(" Typing 'help function_name' will give the short help on the function.\n");
  1909. +   dc_printf(" Some functions may have detailed help, try passing \"help\" or \"--help\" to them.");
  1910. +   dc_printf(" F3 selects last command line. Up and Down arrow keys scroll through the command history\n");
  1911. +   dc_printf("\n");
  1912. +
  1913. +   dc_printf(" Available commands:\n");
  1914. +   for (dc_commands_it it = dc_commands.begin(); it != dc_commands.end(); ++it) {
  1915. +       if (((lastline % DBROWS) == 0) && (lastline != 0)) {
  1916. +           dc_pause_output();
  1917. +       }
  1918. +
  1919. +       dc_printf(" %s - %s\n", (*it)->name, (*it)->help);
  1920. +   }
  1921. +}
  1922. +
  1923. +debug_command dc_man("man", "Also displays the help list", dcf_help);
  1924. diff --git a/code/debugconsole/consoleparse.cpp b/code/debugconsole/consoleparse.cpp
  1925. new file mode 100644
  1926. index 0000000..7ab5c18
  1927. --- /dev/null
  1928. +++ b/code/debugconsole/consoleparse.cpp
  1929. @@ -0,0 +1,1460 @@
  1930. +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1931. +// Command-line parsing functions for z64555's debug console, created for the FreeSpace Source Code project
  1932. +//
  1933. +// Portions of this source code are based on works by Volition, Inc. circa 1999. You may not sell or otherwise
  1934. +// commercially exploit the source or things you created based on the source.
  1935. +//
  1936. +// This file contains documentation on locally referenced functions. For documentation on globally referenced
  1937. +// functions, see consoleparse.h
  1938. +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1939. +
  1940. +/////////////////
  1941. +// Testing Goals
  1942. +// Breakpoints are set at places that need testing:
  1943. +// * the value of endptr strtol and strtoul needs to investigated, according to cplusplus.com, *endptr = end of the string that was successfully converted
  1944. +// TODO: Make a fast version of the parse_long, parse_ulong, etc. That just checks the first 1-3 characters. The fast version will be used in retail builds while the slow/safe version will be in debug's
  1945. +////////////////
  1946. +#include "debugconsole/consoleparse.h"
  1947. +
  1948. +#include "debugconsole/console.h"
  1949. +#include "globalincs/pstypes.h"
  1950. +#include "parse/parselo.h"
  1951. +
  1952. +#include <algorithm>
  1953. +#include <cmath>
  1954. +#include <cstdarg>
  1955. +#include <cstring>
  1956. +#include <limits.h>
  1957. +
  1958. +
  1959. +// ========================= LOCALS =========================
  1960. +char Command_string[MAX_CLI_LEN];   //!< Command string buffer.
  1961. +char *Cp = NULL;    //!< Pointer to the commant string
  1962. +
  1963. +enum state_int {
  1964. +   si_start   = 0,
  1965. +   si_end     = 1,
  1966. +   si_invalid,
  1967. +   si_sign,        //!< Sign character, '-' '+'
  1968. +   si_prefix,      //!< prefix character sequence, 0b, 0o, or 0x
  1969. +   si_numeral,     //!< Numeral state, 0 - 9
  1970. +   si_numeral_bin,     //!< Numeral altstate, 0, 1
  1971. +   si_numeral_octal,   //!< Numeral altstate, 0 - 7
  1972. +   si_numeral_hex      //!< Numeral altstate, 0 - 9 and 'a' - 'f'
  1973. +};
  1974. +
  1975. +enum state_float {
  1976. +   sf_start = 0,
  1977. +   sf_end = 1,
  1978. +   sf_invalid,
  1979. +   sf_sign,        //!< Sign character for mantessa
  1980. +   sf_whole,       //!< Whole value numeral
  1981. +   sf_decimal,     //!< Decimal character
  1982. +   sf_fraction,    //!< Fractional value numeral
  1983. +   sf_expprefix,   //!< Exponent prefix, 'e', 'E'
  1984. +   sf_expsign,     //!< Exponent sign
  1985. +   sf_exponent     //!< Exponent value numeral
  1986. +};
  1987. +
  1988. +bool ch_is_sign(char ch);
  1989. +bool ch_is_numeral(char ch);
  1990. +bool ch_is_decimal(char ch);
  1991. +bool ch_is_binary(char ch);
  1992. +bool ch_is_octal(char ch);
  1993. +bool ch_is_hex(char ch);
  1994. +
  1995. +bool ch_is_prefix(char ch);
  1996. +bool ch_is_binary_prefix(char ch);
  1997. +bool ch_is_octal_prefix(char ch);
  1998. +bool ch_is_hex_prefix(char ch);
  1999. +bool ch_is_exp_prefix(char ch);
  2000. +
  2001. +/**
  2002. + * @brief Returns/Advances past a single token
  2003. + *
  2004. + * @details Similar in operation to dc_stuff_string_white, but won't throw any error messages and will only grab the
  2005. + *   first word. (dc_stuff_string_white may grab quoted strings)
  2006. + */
  2007. +void dc_get_token(SCP_string &out_str);
  2008. +
  2009. +/**
  2010. + * @brief Returns a single token, but does not advances Cp
  2011. + *
  2012. + * @details Similar in operation to dc_stuff_string_white, but won't throw any error messages and will only grab the
  2013. + *   first word. (dc_stuff_string_white may grab quoted strings).
  2014. + */
  2015. +void dc_get_token_no_advance(SCP_string &out_str);
  2016. +
  2017. +/**
  2018. + * @brief Parses a double-precision floating point type. Supports, Whole, Fractional, and Mixed numbers, and supports
  2019. + *   scientific notation (exponent prefixed by 'e' or 'E').
  2020. + *
  2021. + * @param[in] ch   Points to the start of the string to parse
  2022. + * @param[in] type The expected type. is thrown along with ch when an unexpected/malformed float is found
  2023. + *
  2024. + * @ret The value of the parsed token
  2025. + * @details
  2026. + *   The returned double may be cast to a single-precision float, but be sure to check it before doing so!
  2027. + */
  2028. +double dc_parse_double(const char *ch, dc_token type);
  2029. +
  2030. +/**
  2031. + * @brief Parses a long integral type. Supports decimal, binary, octal, and hexidecimal strings.
  2032. + *
  2033. + * @param[in] ch    Points to the start of the string to parse.
  2034. + * @param[in] type  The expected type. Is thrown along with ch when an unexpected/malformed integral is found
  2035. + *
  2036. + * @details
  2037. + * ! Non-decimal values must be prefixed by their corresponding sequence. Binary: "0b", Octal: "0o", Hex: "0x"
  2038. + *
  2039. + *   The returned long may be cast to a smaller integral, but be sure to check it before doing so!
  2040. + *
  2041. + *   The only thing left making this function specific to the DC is the expected type. So, if you want to use this
  2042. + *   for parsing something other than the debug CL, you'll have to make a set of errParse classes that take a
  2043. + *   different expected type.
  2044. + */
  2045. +long   dc_parse_long(const char *ch, dc_token type);
  2046. +
  2047. +/**
  2048. + * @brief Parses an unsigned long integral type. Supports decimal, binary, octal, and hexidecimal strings.
  2049. + *
  2050. + * @param[in] ch    Points to the start of the string to parse.
  2051. + * @param[in] type  The expected type. Is thrown along with ch when an unexpected/malformed integral is found
  2052. + *
  2053. + * @details
  2054. + * ! Non-decimal values must be delimited by their corresponding sequence. Binary: "0b", Octal: "0o", Hex: "0x"
  2055. + *   The returned long may be cast to a smaller integral, but be sure to check it before doing so!
  2056. + *   The only thing left making this function specific to the DC is the expected type. So, if you want to use this
  2057. + *   for parsing something other than the debug CL, you'll have to make a set of errParse classes that take a
  2058. + *   different expected type.
  2059. + */
  2060. +ulong  dc_parse_ulong(const char *ch, dc_token type);
  2061. +
  2062. +// State processes for dc_parse_double
  2063. +state_float dc_parse_double_sign(const char* &ch_ptr, SCP_string &buffer_str);
  2064. +state_float dc_parse_double_whole(const char* &ch_ptr, SCP_string &buffer_str);
  2065. +state_float dc_parse_double_decimal(const char* &ch_ptr, SCP_string &buffer_str);
  2066. +state_float dc_parse_double_fraction(const char* &ch_ptr, SCP_string &buffer_str);
  2067. +state_float dc_parse_double_expprefix(const char* &ch_ptr, SCP_string &buffer_str);
  2068. +state_float dc_parse_double_expsign(const char* &ch_ptr, SCP_string &buffer_str);
  2069. +state_float dc_parse_double_exponent(const char* &ch_ptr, SCP_string &buffer_str);
  2070. +
  2071. +// State processes for dc_parse_long and dc_parse_ulong.
  2072. +state_int dc_parse_long_prefix(const char* &ch_ptr, SCP_string &buffer_str, int &base);
  2073. +state_int dc_parse_long_sign(const char* &ch_ptr, SCP_string &buffer_str);
  2074. +state_int dc_parse_long_numeral(const char* &ch_ptr, SCP_string &buffer_str);
  2075. +state_int dc_parse_long_numeral_bin(const char* &ch_ptr, SCP_string &buffer_str);
  2076. +state_int dc_parse_long_numeral_hex(const char* &ch_ptr, SCP_string &buffer_str);
  2077. +state_int dc_parse_long_numeral_octal(const char* &ch_ptr, SCP_string &buffer_str);
  2078. +
  2079. +
  2080. +// ============================== IMPLEMENTATIONS =============================
  2081. +inline
  2082. +bool ch_is_sign(char ch)
  2083. +{
  2084. +   return ((ch == '-') || (ch == '+'));
  2085. +}
  2086. +
  2087. +inline
  2088. +bool ch_is_numeral(char ch)
  2089. +{
  2090. +   return ((ch >= '0') && (ch <= '9'));
  2091. +}
  2092. +
  2093. +inline
  2094. +bool ch_is_decimal(char ch)
  2095. +{
  2096. +   return (ch == '.');
  2097. +}
  2098. +
  2099. +inline
  2100. +bool ch_is_binary(char ch)
  2101. +{
  2102. +   return ((ch == '0') || (ch == '1'));
  2103. +}
  2104. +
  2105. +inline
  2106. +bool ch_is_octal(char ch)
  2107. +{
  2108. +   return ((ch >= '0') && (ch <= '7'));
  2109. +}
  2110. +
  2111. +inline
  2112. +bool ch_is_hex(char ch)
  2113. +{
  2114. +   return (((ch >= '0') && (ch <= '9')) || ((ch >= 'a') && (ch <= 'f')) || ((ch >= 'A') && (ch <= 'F')));
  2115. +};
  2116. +
  2117. +inline
  2118. +bool ch_is_prefix(char ch)
  2119. +{
  2120. +   return (ch == '0');
  2121. +}
  2122. +
  2123. +inline
  2124. +bool ch_is_binary_prefix(char ch)
  2125. +{
  2126. +   return ((ch == 'b') || (ch == 'B'));
  2127. +}
  2128. +
  2129. +inline
  2130. +bool ch_is_octal_prefix(char ch)
  2131. +{
  2132. +   return ((ch == 'o') || (ch == 'O'));
  2133. +}
  2134. +
  2135. +inline
  2136. +bool ch_is_hex_prefix(char ch)
  2137. +{
  2138. +   return ((ch == 'x') || (ch == 'X'));
  2139. +}
  2140. +
  2141. +inline
  2142. +bool ch_is_exp_prefix(char ch)
  2143. +{
  2144. +   return ((ch == 'e') || (ch == 'E'));
  2145. +}
  2146. +
  2147. +void dc_get_token(SCP_string &out_str) {
  2148. +   size_t count = 0;
  2149. +   char *c_ptr;
  2150. +
  2151. +   Assert(Cp);
  2152. +
  2153. +   dc_ignore_gray_space();
  2154. +
  2155. +   out_str = "";
  2156. +   // Bail if we're at the terminator
  2157. +   if (*Cp == '\0') {
  2158. +       return;
  2159. +   }
  2160. +
  2161. +   // Scan the string, stopping at grayspace, null terminator, or before we go over MAX_TOKEN_LENGTH
  2162. +   c_ptr = Cp;
  2163. +   while (!is_gray_space(*c_ptr) && (*c_ptr != '\0') && (count < MAX_TOKEN_LENGTH)) {
  2164. +       count++;
  2165. +       c_ptr++;
  2166. +   }
  2167. +
  2168. +   // Copy string into out_str
  2169. +   out_str.assign(Cp, count);
  2170. +  
  2171. +   // Advance the parser pointer past what we copied
  2172. +   Cp = c_ptr;
  2173. +}
  2174. +
  2175. +void dc_get_token_no_advance(SCP_string &out_str) {
  2176. +   size_t count = 0;
  2177. +   char *c_ptr;
  2178. +
  2179. +   Assert(Cp);
  2180. +
  2181. +   dc_ignore_gray_space();
  2182. +
  2183. +   out_str = "";
  2184. +   // Bail if we're at the terminator
  2185. +   if (*Cp == '\0') {
  2186. +       return;
  2187. +   }
  2188. +
  2189. +   // Scan the string, stopping at grayspace, null terminator, or before we go over MAX_TOKEN_LENGTH
  2190. +   c_ptr = Cp;
  2191. +   while (!is_gray_space(*c_ptr) && (*c_ptr != '\0') && (count < MAX_TOKEN_LENGTH)) {
  2192. +       count++;
  2193. +       c_ptr++;
  2194. +   }
  2195. +
  2196. +   // Copy string into out_str
  2197. +   out_str.assign(Cp, count);
  2198. +}
  2199. +
  2200. +void dc_ignore_white_space(void) {
  2201. +   while (is_white_space(*Cp) && (*Cp != '\0')) {
  2202. +       Cp++;
  2203. +   }
  2204. +}
  2205. +
  2206. +void dc_ignore_gray_space(void) {
  2207. +   while (is_gray_space(*Cp) && (*Cp != '\0')) {
  2208. +       Cp++;
  2209. +   }
  2210. +}
  2211. +
  2212. +bool dc_maybe_stuff_float(float *f)
  2213. +{
  2214. +   dc_ignore_gray_space();
  2215. +
  2216. +   if (*Cp != '\0') {
  2217. +       dc_stuff_float(f);
  2218. +       return true;
  2219. +  
  2220. +   } else {
  2221. +       *f = 0;
  2222. +       return false;
  2223. +   }
  2224. +}
  2225. +
  2226. +bool dc_maybe_stuff_int(int *i)
  2227. +{
  2228. +   dc_ignore_gray_space();
  2229. +
  2230. +   if (*Cp != '\0') {
  2231. +       dc_stuff_int(i);
  2232. +       return true;
  2233. +   } else {
  2234. +       *i = 0;
  2235. +       return false;
  2236. +   }
  2237. +}
  2238. +
  2239. +bool dc_maybe_stuff_uint(uint *i)
  2240. +{
  2241. +   dc_ignore_gray_space();
  2242. +
  2243. +   if (*Cp != '\0') {
  2244. +       dc_stuff_uint(i);
  2245. +       return true;
  2246. +   } else {
  2247. +       *i = 0;
  2248. +       return false;
  2249. +   }
  2250. +}
  2251. +
  2252. +bool dc_maybe_stuff_ubyte(ubyte *i)
  2253. +{
  2254. +   dc_ignore_gray_space();
  2255. +
  2256. +   if (*Cp != '\0') {
  2257. +       dc_stuff_ubyte(i);
  2258. +       return true;
  2259. +   } else {
  2260. +       *i = 0;
  2261. +       return false;
  2262. +   }
  2263. +}
  2264. +
  2265. +bool dc_maybe_stuff_boolean(bool *b)
  2266. +{
  2267. +   dc_ignore_gray_space();
  2268. +
  2269. +   if (*Cp != '\0') {
  2270. +       dc_stuff_boolean(b);
  2271. +       return true;
  2272. +   } else {
  2273. +       *b = false;
  2274. +       return false;
  2275. +   }
  2276. +}
  2277. +
  2278. +bool dc_maybe_stuff_boolean(int *i)
  2279. +{
  2280. +   dc_ignore_gray_space();
  2281. +
  2282. +   if (*Cp != '\0') {
  2283. +       dc_stuff_boolean(i);
  2284. +       return true;
  2285. +   } else {
  2286. +       *i = 0;
  2287. +       return false;
  2288. +   }
  2289. +}
  2290. +
  2291. +bool dc_maybe_stuff_string(char *out_str, size_t maxlen)
  2292. +{
  2293. +   size_t count = 0;
  2294. +   char *c_ptr = Cp;
  2295. +
  2296. +   Assert(Cp);
  2297. +   Assert(out_str);
  2298. +
  2299. +   // Advance past grayspace, stopping at null terminator
  2300. +   while (is_gray_space(*c_ptr) && (*c_ptr != '\0')) {
  2301. +       c_ptr++;
  2302. +   }
  2303. +
  2304. +   // Bail if we're at the terminator
  2305. +   if (*c_ptr == '\0') {
  2306. +       return false;
  2307. +   }
  2308. +
  2309. +   // Scan the string, stopping at null terminator, or before we overflow
  2310. +   while ((*c_ptr != '\0') && (count < maxlen)) {
  2311. +       count++;
  2312. +       c_ptr++;
  2313. +   }
  2314. +
  2315. +   // Bail if overflow
  2316. +   if (count == maxlen) {
  2317. +       throw errParse("", DCT_STRING);
  2318. +   }
  2319. +
  2320. +   // Copy string into out_str
  2321. +   strncpy(out_str, Cp, count);
  2322. +  
  2323. +   // Advance the parser pointer past what we copied
  2324. +   Cp = c_ptr;
  2325. +
  2326. +   return true;
  2327. +}
  2328. +
  2329. +bool dc_maybe_stuff_string(SCP_string &out_str)
  2330. +{
  2331. +   size_t count = 0;
  2332. +   char *c_ptr = Cp;
  2333. +
  2334. +   Assert(Cp);
  2335. +
  2336. +   // Advance past grayspace, stopping at null terminator
  2337. +   while (is_gray_space(*c_ptr) && (*c_ptr != '\0')) {
  2338. +       c_ptr++;
  2339. +   }
  2340. +
  2341. +   // Bail if we're at the terminator
  2342. +   if (*c_ptr == '\0') {
  2343. +       return false;
  2344. +   }
  2345. +
  2346. +   // Scan the string, stopping at null terminator, or before we overflow
  2347. +   while ((*c_ptr != '\0') && (count < out_str.max_size())) {
  2348. +       count++;
  2349. +       c_ptr++;
  2350. +   }
  2351. +
  2352. +   // Bail if overflow
  2353. +   if (count == out_str.max_size()) {
  2354. +       return false;
  2355. +   }
  2356. +
  2357. +   // Copy string into out_str
  2358. +   out_str.assign(Cp, count);
  2359. +  
  2360. +   // Advance the parser pointer past what we copied
  2361. +   Cp = c_ptr;
  2362. +
  2363. +   return true;
  2364. +}
  2365. +
  2366. +bool dc_maybe_stuff_string_white(char *str, size_t len)
  2367. +{
  2368. +   dc_ignore_gray_space();
  2369. +
  2370. +   if (*Cp != '\0') {
  2371. +       dc_stuff_string_white(str, len);
  2372. +       return true;
  2373. +   } else {
  2374. +       *str = '\0';
  2375. +       return false;
  2376. +   }
  2377. +}
  2378. +
  2379. +bool dc_maybe_stuff_string_white(SCP_string &str)
  2380. +{
  2381. +   dc_ignore_gray_space();
  2382. +
  2383. +   if (*Cp != '\0') {
  2384. +       dc_stuff_string_white(str);
  2385. +       return true;
  2386. +   } else {
  2387. +       str = "";
  2388. +       return false;
  2389. +   }
  2390. +}
  2391. +
  2392. +void dc_required_string(char *pstr)
  2393. +{
  2394. +   char *str_found = NULL;
  2395. +
  2396. +   dc_ignore_gray_space();
  2397. +
  2398. +   if (strnicmp(pstr, Cp, strlen(pstr))) {
  2399. +       str_found = pstr;
  2400. +   }
  2401. +
  2402. +   if (str_found != NULL) {
  2403. +       // Found a required string
  2404. +       if (Dc_debug_on) {
  2405. +           dc_printf("<debug> Found required string [%s]\n", str_found);
  2406. +       }
  2407. +
  2408. +       Cp += strlen(str_found);
  2409. +   } else {
  2410. +       // Didn't find a required string.
  2411. +       SCP_string token;
  2412. +       dc_get_token_no_advance(token);
  2413. +       throw errParseString(token.c_str(), pstr);
  2414. +   }
  2415. +}
  2416. +
  2417. +int dc_required_string_either(char *str1, char *str2)
  2418. +{
  2419. +   char *str_found = NULL;
  2420. +   int i = -1;
  2421. +
  2422. +   dc_ignore_gray_space();
  2423. +
  2424. +   if (strncmp(str1, Cp, strlen(str1) == 0)) {
  2425. +       str_found = str1;
  2426. +       i = 0;
  2427. +   } else if (strncmp(str2, Cp, strlen(str2) == 0)) {
  2428. +       str_found = str2;
  2429. +       i = 1;
  2430. +   }
  2431. +
  2432. +   if (i > -1) {
  2433. +       // Found a required string
  2434. +       if (Dc_debug_on) {
  2435. +           dc_printf("<debug> Found required string [%s]\n", str_found);
  2436. +       }
  2437. +
  2438. +       Cp += strlen(str_found);
  2439. +   } else {
  2440. +       // Didn't find a required string.
  2441. +       SCP_string token;
  2442. +       dc_get_token_no_advance(token);
  2443. +       throw errParseString(token.c_str(), str1, str2);
  2444. +   }
  2445. +
  2446. +   return i;
  2447. +}
  2448. +
  2449. +int dc_required_string_any(const uint n, ...)
  2450. +{
  2451. +   va_list vl;
  2452. +   SCP_vector<SCP_string> strings;
  2453. +   const char *str_found = NULL;
  2454. +   int i;
  2455. +
  2456. +   dc_ignore_gray_space();
  2457. +
  2458. +   // Populate the vector.
  2459. +   va_start(vl, n);
  2460. +   for (i = 0; i < n; ++i) {
  2461. +       strings.push_back(va_arg(vl, char *));
  2462. +   }
  2463. +   va_end(vl);
  2464. +
  2465. +   // Search for the required string. If found, i = index of the string passed
  2466. +   for (i = 0; i < n; ++i) {
  2467. +       if (strcmp(Cp, strings[i].c_str()) == 0)
  2468. +       {
  2469. +           str_found = strings[i].c_str();
  2470. +           break;
  2471. +       }
  2472. +   }
  2473. +
  2474. +   if (str_found != NULL) {
  2475. +       // Found a required string
  2476. +       if (Dc_debug_on) {
  2477. +           dc_printf("<debug> Found required string [%s}\n", str_found);
  2478. +       }
  2479. +
  2480. +       Cp += strlen(str_found);
  2481. +   } else {
  2482. +       // Didn't find a required string.
  2483. +       SCP_string token;
  2484. +       dc_get_token_no_advance(token);
  2485. +       throw errParseString(token.c_str(), strings);
  2486. +   }
  2487. +
  2488. +   return i;
  2489. +}
  2490. +
  2491. +bool dc_optional_string(const char *pstr)
  2492. +{
  2493. +   dc_ignore_gray_space();
  2494. +
  2495. +   if (strncmp(pstr, Cp, strlen(pstr) != 0)) {
  2496. +       return false;
  2497. +   } // Else, optional string was found
  2498. +
  2499. +   if (Dc_debug_on) {
  2500. +       dc_printf("<debug> Found optional string [%s]\n", pstr);
  2501. +   }
  2502. +
  2503. +   Cp += strlen(pstr);
  2504. +   return true;
  2505. +}
  2506. +
  2507. +bool dc_optional_string_either(const char *str1, const char *str2)
  2508. +{
  2509. +   const char *str_found = NULL;
  2510. +
  2511. +   dc_ignore_gray_space();
  2512. +
  2513. +   if (strncmp(str1, Cp, strlen(str1)) == 0) {
  2514. +       str_found = str1;
  2515. +   } else if (strncmp(str2, Cp, strlen(str2)) == 0) {
  2516. +       str_found = str2;
  2517. +   } else {
  2518. +       return false;
  2519. +   }
  2520. +
  2521. +   if (Dc_debug_on) {
  2522. +       dc_printf("<debug> Found optional string [%s]\n",str_found);
  2523. +   }
  2524. +
  2525. +   Cp += strlen(str_found);
  2526. +   return true;;
  2527. +}
  2528. +
  2529. +void dc_parse_init(SCP_string &str)
  2530. +{
  2531. +   strcpy(Command_string, str.c_str());
  2532. +   Cp = Command_string;
  2533. +}
  2534. +
  2535. +double dc_parse_double(const char *ch, dc_token type) {
  2536. +   const char *ch_ptr = ch;
  2537. +   char *end_ptr;
  2538. +   double ret;
  2539. +   state_float state = sf_start;
  2540. +   SCP_string buffer_str;
  2541. +
  2542. +   while ((*ch_ptr != '\0') && is_white_space(*ch_ptr)) {
  2543. +       ch_ptr++;
  2544. +   }
  2545. +
  2546. +   if (*ch_ptr == '\0') {
  2547. +       if (Dc_debug_on) {
  2548. +           dc_printf("<debug> [parse_double] no argument found\n");
  2549. +       }
  2550. +       throw errParse("", type);
  2551. +   }
  2552. +
  2553. +   do {
  2554. +       switch (state) {
  2555. +       case sf_start:
  2556. +           if (ch_is_sign(*ch_ptr)) {
  2557. +               state = sf_sign;
  2558. +               if (*ch_ptr == '-') {
  2559. +                   buffer_str.push_back(*ch_ptr);
  2560. +               } // Else, sign is positive, and isn't needed on the buffer
  2561. +               ch_ptr++;
  2562. +
  2563. +           } else if (ch_is_numeral(*ch_ptr)) {
  2564. +               state = sf_whole;
  2565. +               buffer_str.push_back(*ch_ptr);
  2566. +               ch_ptr++;
  2567. +
  2568. +           } else if (ch_is_decimal(*ch_ptr)) {
  2569. +               state = sf_decimal;
  2570. +               buffer_str.push_back(*ch_ptr);
  2571. +               ch_ptr++;
  2572. +
  2573. +           } else {
  2574. +               if (Dc_debug_on) {
  2575. +                   dc_printf("<debug> [parse_double] Invalid character '%c' found in sf_start\n", *ch_ptr);
  2576. +               }
  2577. +               state = sf_invalid;
  2578. +
  2579. +           }
  2580. +           break;
  2581. +       case sf_end:
  2582. +           if (buffer_str == "") {
  2583. +               state = sf_invalid;
  2584. +           } // Else, we can convert the token.
  2585. +           // Do nothing, and allow the while loop exit condition to trigger
  2586. +           break;
  2587. +       case sf_sign:
  2588. +           state = dc_parse_double_sign(ch_ptr, buffer_str);
  2589. +           break;
  2590. +
  2591. +       case sf_whole:
  2592. +           state = dc_parse_double_whole(ch_ptr, buffer_str);
  2593. +           break;
  2594. +
  2595. +       case sf_decimal:
  2596. +           state = dc_parse_double_decimal(ch_ptr, buffer_str);
  2597. +           break;
  2598. +
  2599. +       case sf_fraction:
  2600. +           state = dc_parse_double_fraction(ch_ptr, buffer_str);
  2601. +           break;
  2602. +
  2603. +       case sf_expprefix:
  2604. +           state = dc_parse_double_expprefix(ch_ptr, buffer_str);
  2605. +           break;
  2606. +
  2607. +       case sf_expsign:
  2608. +           state = dc_parse_double_expsign(ch_ptr, buffer_str);
  2609. +           break;
  2610. +
  2611. +       case sf_exponent:
  2612. +           state = dc_parse_double_exponent(ch_ptr, buffer_str);
  2613. +           break;
  2614. +
  2615. +       case sf_invalid:
  2616. +       default:
  2617. +           throw errParse(ch, type);
  2618. +       }
  2619. +   } while (state != sf_end);
  2620. +
  2621. +   ret = strtod(buffer_str.c_str(), &end_ptr);
  2622. +
  2623. +   return ret;
  2624. +}
  2625. +
  2626. +state_float dc_parse_double_sign(const char* &ch_ptr, SCP_string &buffer_str)
  2627. +{
  2628. +   state_float state = sf_invalid;
  2629. +
  2630. +   if (ch_is_numeral(*ch_ptr)) {
  2631. +       state = sf_whole;
  2632. +       buffer_str.push_back(*ch_ptr);
  2633. +       ch_ptr++;
  2634. +
  2635. +   } else if (ch_is_decimal(*ch_ptr)) {
  2636. +       state = sf_decimal;
  2637. +       buffer_str.push_back(*ch_ptr);
  2638. +       ch_ptr++;
  2639. +
  2640. +   } else {
  2641. +       state = sf_invalid;
  2642. +       if (Dc_debug_on) {
  2643. +           dc_printf("<debug> [parse_double] Invalid character '%c' found in sf_sign\n", *ch_ptr);
  2644. +       }
  2645. +   }
  2646. +
  2647. +   return state;
  2648. +}
  2649. +
  2650. +state_float dc_parse_double_whole(const char* &ch_ptr, SCP_string &buffer_str)
  2651. +{
  2652. +   state_float state = sf_invalid;
  2653. +
  2654. +   if (ch_is_numeral(*ch_ptr)) {
  2655. +       state = sf_whole;
  2656. +       buffer_str.push_back(*ch_ptr);
  2657. +       ch_ptr++;
  2658. +
  2659. +   } else if (ch_is_decimal(*ch_ptr)) {
  2660. +       state = sf_decimal;
  2661. +       buffer_str.push_back(*ch_ptr);
  2662. +       ch_ptr++;
  2663. +
  2664. +   } else if (ch_is_exp_prefix(*ch_ptr)) {
  2665. +       state = sf_expprefix;
  2666. +       buffer_str.push_back(*ch_ptr);
  2667. +       ch_ptr++;
  2668. +
  2669. +   } else if ((*ch_ptr == '\0') || is_white_space(*ch_ptr)) {
  2670. +       state = sf_end;
  2671. +
  2672. +   } else {
  2673. +       state = sf_invalid;
  2674. +       if (Dc_debug_on) {
  2675. +           dc_printf("<debug> [parse_double] Invalid character '%c' found in sf_whole\n", *ch_ptr);
  2676. +       }
  2677. +   }
  2678. +
  2679. +   return state;
  2680. +}
  2681. +
  2682. +state_float dc_parse_double_decimal(const char* &ch_ptr, SCP_string &buffer_str)
  2683. +{
  2684. +   state_float state = sf_invalid;
  2685. +
  2686. +   if (ch_is_numeral(*ch_ptr)) {
  2687. +       state = sf_fraction;
  2688. +       buffer_str.push_back(*ch_ptr);
  2689. +       ch_ptr++;
  2690. +
  2691. +   } else if (ch_is_exp_prefix(*ch_ptr)) {
  2692. +       state = sf_expprefix;
  2693. +       buffer_str.push_back(*ch_ptr);
  2694. +       ch_ptr++;
  2695. +
  2696. +   } else if ((*ch_ptr == '\0') || is_white_space(*ch_ptr)) {
  2697. +       state = sf_end;
  2698. +
  2699. +   } else {
  2700. +       state = sf_invalid;
  2701. +       if (Dc_debug_on) {
  2702. +           dc_printf("<debug> [parse_double] Invalid character '%c' found in sf_decimal\n", *ch_ptr);
  2703. +       }
  2704. +   }
  2705. +
  2706. +   return state;
  2707. +}
  2708. +
  2709. +state_float dc_parse_double_fraction(const char* &ch_ptr, SCP_string &buffer_str)
  2710. +{
  2711. +   state_float state = sf_invalid;
  2712. +
  2713. +   if (ch_is_numeral(*ch_ptr)) {
  2714. +       state = sf_fraction;
  2715. +       buffer_str.push_back(*ch_ptr);
  2716. +       ch_ptr++;
  2717. +
  2718. +   } else if (ch_is_exp_prefix(*ch_ptr)) {
  2719. +       state = sf_expprefix;
  2720. +       buffer_str.push_back(*ch_ptr);
  2721. +       ch_ptr++;
  2722. +
  2723. +   } else if ((*ch_ptr == '\0') || is_white_space(*ch_ptr)) {
  2724. +       state = sf_end;
  2725. +  
  2726. +   } else {
  2727. +       state = sf_invalid;
  2728. +       if (Dc_debug_on) {
  2729. +           dc_printf("<debug> [parse_double] Invalid character '%c' found in sf_faction\n", *ch_ptr);
  2730. +       }
  2731. +   }
  2732. +
  2733. +   return state;
  2734. +}
  2735. +
  2736. +state_float dc_parse_double_expprefix(const char* &ch_ptr, SCP_string &buffer_str)
  2737. +{
  2738. +   state_float state = sf_invalid;
  2739. +
  2740. +   if (ch_is_sign(*ch_ptr)) {
  2741. +       state = sf_expsign;
  2742. +       buffer_str.push_back(*ch_ptr);
  2743. +       ch_ptr++;
  2744. +
  2745. +   } else if (ch_is_numeral(*ch_ptr)) {
  2746. +       state = sf_exponent;
  2747. +       buffer_str.push_back(*ch_ptr);
  2748. +       ch_ptr++;
  2749. +
  2750. +   } else {
  2751. +       state = sf_invalid;
  2752. +       if (Dc_debug_on) {
  2753. +           dc_printf("<debug> [parse_double] Invalid character '%c' found in sf_expprefix\n", *ch_ptr);
  2754. +       }
  2755. +   }
  2756. +
  2757. +   return state;
  2758. +}
  2759. +
  2760. +state_float dc_parse_double_expsign(const char* &ch_ptr, SCP_string &buffer_str)
  2761. +{
  2762. +   state_float state = sf_invalid;
  2763. +
  2764. +   if (ch_is_numeral(*ch_ptr)) {
  2765. +       state = sf_exponent;
  2766. +       buffer_str.push_back(*ch_ptr);
  2767. +       ch_ptr++;
  2768. +
  2769. +   } else {
  2770. +       state = sf_invalid;
  2771. +       if (Dc_debug_on) {
  2772. +           dc_printf("<debug> [parse_double] Invalid character '%c' found in sf_expsign\n", *ch_ptr);
  2773. +       }
  2774. +   }
  2775. +
  2776. +   return state;
  2777. +}
  2778. +
  2779. +state_float dc_parse_double_exponent(const char* &ch_ptr, SCP_string &buffer_str)
  2780. +{
  2781. +   state_float state = sf_invalid;
  2782. +  
  2783. +   if (ch_is_numeral(*ch_ptr)) {
  2784. +       state = sf_exponent;
  2785. +       buffer_str.push_back(*ch_ptr);
  2786. +       ch_ptr++;
  2787. +
  2788. +   } else if ((*ch_ptr == '\0') || is_white_space(*ch_ptr)) {
  2789. +       state = sf_end;
  2790. +
  2791. +   } else {
  2792. +       state = sf_invalid;
  2793. +       if (Dc_debug_on) {
  2794. +           dc_printf("<debug> [parse_double] Invalid character '%c' found in sf_exponent\n", *ch_ptr);
  2795. +       }
  2796. +   }
  2797. +
  2798. +   return state;
  2799. +}
  2800. +
  2801. +long dc_parse_long(const char *ch, dc_token type) {
  2802. +   const char *ch_ptr = ch;
  2803. +   char *end_ptr = NULL;
  2804. +   int base = 10;
  2805. +   long ret;
  2806. +   state_int state = si_start;
  2807. +   SCP_string buffer_str;
  2808. +
  2809. +   while ((*ch_ptr != '\0') && is_white_space(*ch_ptr)) {
  2810. +       ch_ptr++;
  2811. +   }
  2812. +
  2813. +   if (*ch_ptr == '\0') {
  2814. +       if (Dc_debug_on) {
  2815. +           dc_printf("<debug> [parse_long] no argument found\n");
  2816. +       }
  2817. +       throw errParse("", type);
  2818. +   }
  2819. +
  2820. +   do {
  2821. +       switch (state) {
  2822. +       case si_start:
  2823. +           if (ch_is_sign(*ch_ptr)) {
  2824. +               state = si_sign;
  2825. +               if (*ch_ptr == '-') {
  2826. +                   buffer_str.push_back(*ch_ptr);
  2827. +               } // Else, it's positive. Positive sign isn't needed for conversion
  2828. +               ch_ptr++;
  2829. +
  2830. +           } else if (ch_is_prefix(*ch_ptr)) {
  2831. +               // prefixes must be checked before numeral, because they all start with a numeral zero
  2832. +               state = si_prefix;
  2833. +               ch_ptr++;
  2834. +      
  2835. +           } else if (ch_is_numeral(*ch_ptr)) {
  2836. +               state = si_numeral;
  2837. +               buffer_str.push_back(*ch_ptr);
  2838. +               ch_ptr++;
  2839. +      
  2840. +           } else {
  2841. +               if (Dc_debug_on) {
  2842. +                   dc_printf("<debug> [parse_long] Invalid character '%c' found in si_start\n", *ch_ptr);
  2843. +               }
  2844. +               state = si_invalid;
  2845. +
  2846. +           }
  2847. +           break;
  2848. +       case si_end:
  2849. +           if (buffer_str == "") {
  2850. +               state = si_invalid;
  2851. +           } // Else, we can convert the token.
  2852. +           // Do nothing, and allow the while loop exit condition to trigger
  2853. +           break;
  2854. +
  2855. +       case si_sign:
  2856. +           state = dc_parse_long_sign(ch_ptr, buffer_str);
  2857. +           break;
  2858. +
  2859. +       case si_prefix:
  2860. +           state = dc_parse_long_prefix(ch_ptr, buffer_str, base);
  2861. +           break;
  2862. +
  2863. +       case si_numeral_bin:
  2864. +           state = dc_parse_long_numeral_bin(ch_ptr, buffer_str);
  2865. +           break;
  2866. +
  2867. +       case si_numeral_octal:
  2868. +           state = dc_parse_long_numeral_octal(ch_ptr, buffer_str);
  2869. +           break;
  2870. +
  2871. +       case si_numeral_hex:
  2872. +           state = dc_parse_long_numeral_hex(ch_ptr, buffer_str);
  2873. +           break;
  2874. +
  2875. +       case si_numeral:
  2876. +           state = dc_parse_long_numeral(ch_ptr, buffer_str);
  2877. +           break;
  2878. +
  2879. +       case si_invalid:
  2880. +       default:
  2881. +           throw errParse(ch, type);
  2882. +           break;
  2883. +       }
  2884. +   } while (state != si_end);
  2885. +
  2886. +   ret = strtol(buffer_str.c_str(), &end_ptr, base);
  2887. +
  2888. +   // This last check can be omitted once I can verify the operation of strtol in this sense
  2889. +   if (*end_ptr != '\0') {
  2890. +       dc_printf("Error: Could not convert all of the buffer '%s'.\n", buffer_str.c_str());
  2891. +       if (Dc_debug_on) {
  2892. +           dc_printf("<debug> Buffer value: %s\n", buffer_str.c_str());
  2893. +           dc_printf("<debug> Return value: %i", ret);
  2894. +       }
  2895. +       throw errParse(ch, type);
  2896. +   }
  2897. +
  2898. +   return ret;
  2899. +}
  2900. +
  2901. +ulong dc_parse_ulong(const char *ch, dc_token type) {
  2902. +   const char *ch_ptr = ch;
  2903. +   char *end_ptr;
  2904. +   int base = 10;
  2905. +   ulong ret;
  2906. +   state_int state = si_start;
  2907. +   SCP_string buffer_str;
  2908. +
  2909. +   while ((*ch_ptr != '\0') && is_white_space(*ch_ptr)) {
  2910. +       ch_ptr++;
  2911. +   }
  2912. +
  2913. +   if (*ch_ptr == '\0') {
  2914. +       if (Dc_debug_on) {
  2915. +           dc_printf("<debug> [parse_long] no argument found\n");
  2916. +       }
  2917. +       throw errParse("", type);
  2918. +   }
  2919. +
  2920. +   do {
  2921. +       switch (state) {
  2922. +       case si_start:
  2923. +           if (ch_is_prefix(*ch_ptr)) {
  2924. +               // prefixes must be checked before numeral, because they all start with a numeral zero
  2925. +               state = si_prefix;
  2926. +               ch_ptr++;
  2927. +      
  2928. +           } else if (ch_is_numeral(*ch_ptr)) {
  2929. +               state = si_numeral;
  2930. +               buffer_str.push_back(*ch_ptr);
  2931. +               ch_ptr++;
  2932. +      
  2933. +           } else {
  2934. +               if (Dc_debug_on) {
  2935. +                   dc_printf("<debug> [parse_long] Invalid character '%c' found in si_start\n", *ch_ptr);
  2936. +               }
  2937. +               state = si_invalid;
  2938. +
  2939. +           }
  2940. +           break;
  2941. +       case si_end:
  2942. +           if (buffer_str == "")
  2943. +           {
  2944. +               state = si_invalid;
  2945. +           } // Else, we can convert the token.
  2946. +           // Do nothing, and allow the while loop exit condition to trigger
  2947. +           break;
  2948. +
  2949. +       case si_prefix:
  2950. +           state = dc_parse_long_prefix(ch_ptr, buffer_str, base);
  2951. +           break;
  2952. +
  2953. +       case si_numeral_bin:
  2954. +           state = dc_parse_long_numeral_bin(ch_ptr, buffer_str);
  2955. +           break;
  2956. +
  2957. +       case si_numeral_octal:
  2958. +           state = dc_parse_long_numeral_octal(ch_ptr, buffer_str);
  2959. +           break;
  2960. +
  2961. +       case si_numeral_hex:
  2962. +           state = dc_parse_long_numeral_hex(ch_ptr, buffer_str);
  2963. +           break;
  2964. +
  2965. +       case si_numeral:
  2966. +           state = dc_parse_long_numeral(ch_ptr, buffer_str);
  2967. +           break;
  2968. +
  2969. +       case si_invalid:
  2970. +       default:
  2971. +           throw errParse(ch, type);
  2972. +       }
  2973. +   } while (state != si_end);
  2974. +
  2975. +   ret = strtoul(buffer_str.c_str(), &end_ptr, base);
  2976. +
  2977. +   // This last check can be omitted once I can verify the operation of strtol in this sense
  2978. +   if (end_ptr != ch_ptr) {
  2979. +       dc_printf("Error: Could not convert all of the buffer '%s'.\n", buffer_str.c_str());
  2980. +       if (Dc_debug_on) {
  2981. +           dc_printf("<debug> Buffer value: %s\n", buffer_str.c_str());
  2982. +           dc_printf("<debug> Return value: %i", ret);
  2983. +       }
  2984. +       throw errParse(ch, type);
  2985. +   }
  2986. +
  2987. +   return ret;
  2988. +}
  2989. +
  2990. +void dc_stuff_float(float *f)
  2991. +{
  2992. +   double value_d;
  2993. +   SCP_string token;
  2994. +
  2995. +   dc_ignore_gray_space();
  2996. +
  2997. +   dc_get_token(token);    // Grab the token
  2998. +   value_d = dc_parse_double(token.c_str(), DCT_FLOAT);    // Parse and convert
  2999. +  
  3000. +   // Stuff value if within bounds
  3001. +   if ((abs(value_d) < FLT_MAX) && (abs(value_d) > FLT_MIN)) {
  3002. +       *f = value_d;
  3003. +   } else {
  3004. +       throw errParse(token.c_str(), DCT_FLOAT);
  3005. +   }
  3006. +}
  3007. +
  3008. +void dc_stuff_int(int *i)
  3009. +{
  3010. +   long value_l;
  3011. +   SCP_string token;
  3012. +
  3013. +   dc_ignore_gray_space();
  3014. +
  3015. +   dc_get_token(token);
  3016. +   value_l = dc_parse_long(token.c_str(), DCT_INT);
  3017. +
  3018. +   if ((value_l < INT_MAX) && (value_l > INT_MIN)) {
  3019. +       *i = value_l;
  3020. +
  3021. +   } else {
  3022. +       throw errParse(token.c_str(), DCT_INT);
  3023. +   }
  3024. +}
  3025. +
  3026. +void dc_stuff_uint(uint *i)
  3027. +{
  3028. +   ulong value_l;
  3029. +   SCP_string token;
  3030. +
  3031. +   dc_ignore_gray_space();
  3032. +
  3033. +   dc_get_token(token);
  3034. +   value_l = dc_parse_long(Cp, DCT_INT);
  3035. +
  3036. +   if (value_l < UINT_MAX) {
  3037. +       *i = value_l;
  3038. +
  3039. +   } else {
  3040. +       throw errParse(token.c_str(), DCT_INT);
  3041. +   }
  3042. +}
  3043. +
  3044. +void dc_stuff_ubyte(ubyte *i)
  3045. +{
  3046. +   ulong value_ul;
  3047. +   SCP_string token;
  3048. +
  3049. +   dc_ignore_gray_space();
  3050. +
  3051. +   dc_get_token(token);
  3052. +   value_ul = dc_parse_ulong(Cp, DCT_UBYTE);
  3053. +
  3054. +   // Since some system's chars may be greater than 1 byte, we can't use UCHAR_MAX for a UBYTE
  3055. +   if ((value_ul <= 255) && (value_ul >= 0)) {
  3056. +       *i = value_ul;
  3057. +
  3058. +   } else {
  3059. +       throw errParse(token.c_str(), DCT_UBYTE);
  3060. +   }
  3061. +}
  3062. +
  3063. +void dc_stuff_boolean(bool *b)
  3064. +{
  3065. +   SCP_string token;
  3066. +
  3067. +   dc_get_token(token);
  3068. +
  3069. +   if ((token == "yes")
  3070. +       || (token == "true")
  3071. +       || (token == "ja")          // German
  3072. +       || (token == "Oui")         // French
  3073. +       || (token == "si")          // Spanish
  3074. +//     || (token == "ita vero")    // Latin, not supported
  3075. +       || (token == "HIja") || (token == "HISLaH")     // Klingon
  3076. +       || (token == "1"))
  3077. +   {
  3078. +       *b = true;
  3079. +
  3080. +   } else if ((token == "no")
  3081. +       || (token == "false")
  3082. +       || (token == "nein")    // German
  3083. +       || (token == "Non")     // French
  3084. +//     || (token == "no")      // Spanish, redundant with English "no"
  3085. +//     || (token == "minime")  // Latin, not supported
  3086. +       || (token == "ghobe'")  // Klingon
  3087. +       || (token == "0"))
  3088. +   {
  3089. +       *b = false;
  3090. +
  3091. +   } else {
  3092. +       throw errParse(token.c_str(), DCT_BOOL);
  3093. +   }
  3094. +}
  3095. +
  3096. +void dc_stuff_boolean(int *i)
  3097. +{
  3098. +   bool value_b;
  3099. +
  3100. +   dc_stuff_boolean(&value_b);
  3101. +
  3102. +   value_b ? *i = 1 : *i = 0;
  3103. +}
  3104. +
  3105. +void dc_stuff_string(char *out_str, size_t maxlen = MAX_TOKEN_LENGTH)
  3106. +{
  3107. +   size_t count = 0;
  3108. +   char *c_ptr = Cp;
  3109. +   SCP_string token;
  3110. +
  3111. +   Assert(Cp);
  3112. +   Assert(out_str);
  3113. +
  3114. +   dc_ignore_gray_space();
  3115. +
  3116. +   // Bail if we're at the terminator
  3117. +   if (*Cp == '\0') {
  3118. +       throw errParse("Nothing!", DCT_STRING);
  3119. +   }
  3120. +
  3121. +   // Scan the string, stopping at null terminator, or before we overflow
  3122. +   c_ptr = Cp;
  3123. +   while ((*c_ptr != '\0') && (count < maxlen)) {
  3124. +       count++;
  3125. +       c_ptr++;
  3126. +   }
  3127. +
  3128. +   // Bail if overflow
  3129. +   if (count == maxlen) {
  3130. +       token.assign(Cp, maxlen);
  3131. +       throw errParseOverflow(token.c_str(), maxlen);
  3132. +   }
  3133. +
  3134. +   // Copy string into out_str
  3135. +   strncpy(out_str, Cp, count);
  3136. +  
  3137. +   // Advance the parser pointer past what we copied
  3138. +   Cp = c_ptr;
  3139. +}
  3140. +
  3141. +void dc_stuff_string(SCP_string &out_str)
  3142. +{
  3143. +   size_t count = 0;
  3144. +   char *c_ptr = Cp;
  3145. +
  3146. +   Assert(Cp);
  3147. +
  3148. +   dc_ignore_gray_space();
  3149. +
  3150. +   // Bail if we're at the terminator
  3151. +   if (*Cp == '\0') {
  3152. +       throw errParse("Nothing!", DCT_STRING);
  3153. +   }
  3154. +
  3155. +   // Scan the string, stopping at null terminator, or before we overflow
  3156. +   c_ptr = Cp;
  3157. +   while ((*c_ptr != '\0') && (count < out_str.max_size())) {
  3158. +       count++;
  3159. +       c_ptr++;
  3160. +   }
  3161. +
  3162. +   // Bail if overflow
  3163. +   if ((count == out_str.max_size()) && (c_ptr != '\0')) {
  3164. +       throw errParse("SCP_string overflow!", DCT_STRING);
  3165. +   }
  3166. +
  3167. +   // Copy string into out_str
  3168. +   out_str.assign(Cp, count);
  3169. +  
  3170. +   // Advance the parser pointer past what we copied
  3171. +   Cp = c_ptr;
  3172. +}
  3173. +
  3174. +void dc_stuff_string_white(char *out_str, size_t maxlen)
  3175. +{
  3176. +   size_t count = 0;
  3177. +   char *c_ptr = Cp;
  3178. +
  3179. +   Assert(Cp);
  3180. +   Assert(out_str);
  3181. +
  3182. +   dc_ignore_gray_space();
  3183. +
  3184. +   // Bail if we're at the terminator
  3185. +   if (*Cp == '\0') {
  3186. +       throw errParse("Nothing!", DCT_STRING);
  3187. +   }
  3188. +
  3189. +   // Scan the string, stopping at grayspace, null terminator, or before we overflow
  3190. +   c_ptr = Cp;
  3191. +   while (!is_gray_space(*c_ptr) && (*c_ptr != '\0') && (count < maxlen)) {
  3192. +       count++;
  3193. +       c_ptr++;
  3194. +   }
  3195. +
  3196. +   // Bail if overflow
  3197. +   if (count == maxlen) {
  3198. +       throw errParse("", DCT_STRING);
  3199. +   }
  3200. +
  3201. +   // Copy string into out_str
  3202. +   strncpy(out_str, Cp, count);
  3203. +  
  3204. +   // Advance the parser pointer past what we copied
  3205. +   Cp = c_ptr;
  3206. +}
  3207. +
  3208. +void dc_stuff_string_white(SCP_string &out_str)
  3209. +{
  3210. +   size_t count = 0;
  3211. +   char *c_ptr;
  3212. +
  3213. +   Assert(Cp);
  3214. +
  3215. +   dc_ignore_gray_space();
  3216. +
  3217. +   // Bail if we're at the terminator
  3218. +   if (*Cp == '\0') {
  3219. +       throw errParse("Nothing!", DCT_STRING);
  3220. +   }
  3221. +
  3222. +   // Scan the string, stopping at grayspace, null terminator, or before we overflow
  3223. +   c_ptr = Cp;
  3224. +   while (!is_gray_space(*c_ptr) && (*c_ptr != '\0') && (count < out_str.max_size())) {
  3225. +       count++;
  3226. +       c_ptr++;
  3227. +   }
  3228. +
  3229. +   // Bail if overflow
  3230. +   if (count == out_str.max_size()) {
  3231. +       throw errParse("", DCT_STRING);
  3232. +   }
  3233. +
  3234. +   // Copy string into out_str
  3235. +   out_str.assign(Cp, count);
  3236. +  
  3237. +   // Advance the parser pointer past what we copied
  3238. +   Cp = c_ptr;
  3239. +}
  3240. +
  3241. +inline
  3242. +state_int dc_parse_long_prefix(const char* &ch_ptr, SCP_string &buffer_str, int &base) {
  3243. +   state_int state = si_invalid;
  3244. +
  3245. +   if (ch_is_binary_prefix(*ch_ptr)) {
  3246. +       state = si_numeral_bin;
  3247. +       base = 2;
  3248. +       ch_ptr++;
  3249. +  
  3250. +   } else if (ch_is_octal_prefix(*ch_ptr)) {
  3251. +       state = si_numeral_octal;
  3252. +       base = 8;
  3253. +       ch_ptr++;
  3254. +  
  3255. +   } else if (ch_is_hex_prefix(*ch_ptr)) {
  3256. +       state = si_numeral_hex;
  3257. +       base = 16;
  3258. +       ch_ptr++;
  3259. +
  3260. +   } else if (ch_is_numeral(*ch_ptr)) {
  3261. +       // User passed something like 0123
  3262. +       // Just ignore the first 0, if the user passed something like 00001 then state si_numeral can handle it
  3263. +       state = si_numeral;
  3264. +       ch_ptr++;
  3265. +  
  3266. +   } else if ((*ch_ptr == '\0') || is_white_space(*ch_ptr)) {
  3267. +       // Just a 0 was passed.
  3268. +       buffer_str.push_back('0');
  3269. +       state = si_end;
  3270. +
  3271. +   } else {
  3272. +       if (Dc_debug_on) {
  3273. +           dc_printf("<debug> [parse_long] Invalid character '%c' found in si_prefix\n", *ch_ptr);
  3274. +       }
  3275. +       state = si_invalid;
  3276. +
  3277. +   }
  3278. +   return state;
  3279. +}
  3280. +
  3281. +inline
  3282. +state_int dc_parse_long_sign(const char* &ch_ptr, SCP_string &buffer_str) {
  3283. +   state_int state;
  3284. +   if (ch_is_numeral(*ch_ptr)) {
  3285. +       state = si_numeral;
  3286. +       buffer_str.push_back(*ch_ptr);
  3287. +       ch_ptr++;
  3288. +
  3289. +   } else if (ch_is_prefix(*ch_ptr)) {
  3290. +       state = si_prefix;
  3291. +       ch_ptr++;
  3292. +
  3293. +   } else if ((*ch_ptr == '\0') || is_white_space(*ch_ptr)) {
  3294. +       // Error, no value found
  3295. +       state = si_invalid;
  3296. +
  3297. +   } else {
  3298. +       if (Dc_debug_on) {
  3299. +           dc_printf("<debug> [parse_long] Invalid character '%c' found in si_sign\n", *ch_ptr);
  3300. +       }
  3301. +       state = si_invalid;
  3302. +
  3303. +   }
  3304. +   return state;
  3305. +}
  3306. +
  3307. +inline
  3308. +state_int dc_parse_long_numeral(const char* &ch_ptr, SCP_string &buffer_str) {
  3309. +   state_int state = si_numeral;
  3310. +
  3311. +   if (ch_is_numeral(*ch_ptr)) {
  3312. +       buffer_str.push_back(*ch_ptr);
  3313. +       ch_ptr++;
  3314. +  
  3315. +   } else if ((*ch_ptr == '\0') || is_white_space(*ch_ptr)) {
  3316. +       state = si_end;
  3317. +  
  3318. +   } else {
  3319. +       // Invalid character, throw and bail
  3320. +       if (Dc_debug_on) {
  3321. +           dc_printf("<debug> [parse_long] Invalid character '%c' found in si_numeral\n", *ch_ptr);
  3322. +       }
  3323. +       state = si_invalid;
  3324. +
  3325. +   }
  3326. +   return state;
  3327. +}
  3328. +
  3329. +inline
  3330. +state_int dc_parse_long_numeral_bin(const char* &ch_ptr, SCP_string &buffer_str) {
  3331. +   state_int state = si_numeral_bin;
  3332. +
  3333. +   if (ch_is_binary(*ch_ptr)) {
  3334. +       buffer_str.push_back(*ch_ptr);
  3335. +       ch_ptr++;
  3336. +  
  3337. +   } else if ((*ch_ptr == '\0') || is_white_space(*ch_ptr)) {
  3338. +       state = si_end;
  3339. +  
  3340. +   } else {
  3341. +       if (Dc_debug_on) {
  3342. +           dc_printf("<debug> [parse_long] Invalid character '%c' found in si_numeral_bin\n", *ch_ptr);
  3343. +       }
  3344. +       state = si_invalid;
  3345. +
  3346. +   }
  3347. +   return state;
  3348. +}
  3349. +
  3350. +inline
  3351. +state_int dc_parse_long_numeral_hex(const char* &ch_ptr, SCP_string &buffer_str) {
  3352. +   state_int state = si_numeral_hex;
  3353. +
  3354. +   if (ch_is_hex(*ch_ptr)) {
  3355. +       buffer_str.push_back(*ch_ptr);
  3356. +       ch_ptr++;
  3357. +  
  3358. +   } else if ((*ch_ptr == '\0') || is_white_space(*ch_ptr)) {
  3359. +       state = si_end;
  3360. +  
  3361. +   } else {
  3362. +       if (Dc_debug_on) {
  3363. +           dc_printf("<debug> [parse_long] Invalid character '%c' found in si_numeral_hex\n", *ch_ptr);
  3364. +       }
  3365. +       state = si_invalid;
  3366. +   }
  3367. +   return state;
  3368. +}
  3369. +
  3370. +inline
  3371. +state_int dc_parse_long_numeral_octal(const char* &ch_ptr, SCP_string &buffer_str) {
  3372. +   state_int state = si_numeral_octal;
  3373. +
  3374. +   if (ch_is_octal(*ch_ptr)) {
  3375. +       buffer_str.push_back(*ch_ptr);
  3376. +       ch_ptr++;
  3377. +  
  3378. +   } else if ((*ch_ptr == '\0') || is_white_space(*ch_ptr)) {
  3379. +       state = si_end;
  3380. +  
  3381. +   } else {
  3382. +       // Invalid character, throw and bail
  3383. +       if (Dc_debug_on) {
  3384. +           dc_printf("<debug> [parse_long] Invalid character '%c' found in si_numeral_octal\n", *ch_ptr);
  3385. +       }
  3386. +       state = si_invalid;
  3387. +   }
  3388. +   return state;
  3389. +}
  3390. diff --git a/code/debugconsole/consoleparse.h b/code/debugconsole/consoleparse.h
  3391. new file mode 100644
  3392. index 0000000..57885b1
  3393. --- /dev/null
  3394. +++ b/code/debugconsole/consoleparse.h
  3395. @@ -0,0 +1,477 @@
  3396. +#ifndef _CONSOLEPARSE_H
  3397. +#define _CONSOLEPARSE_H
  3398. +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3399. +// Command-line parsing functions for z64555's debug console, created for the FreeSpace Source Code project
  3400. +//
  3401. +// Portions of this source code are based on works by Volition, Inc. circa 1999. You may not sell or otherwise
  3402. +// commercially exploit the source or things you created based on the source.
  3403. +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3404. +
  3405. +/**
  3406. + * @file consoleparse.h
  3407. + * @brief Parsing functions for the command line. Previously known as the command line scanner
  3408. + *
  3409. + * @details A lot of functions here are blatently copied from parselo.h :D
  3410. +  */
  3411. +
  3412. +#include "globalincs/pstypes.h"
  3413. +
  3414. +#include <cstdarg>
  3415. +
  3416. +#define MAX_CLI_LEN 512
  3417. +#define MAX_TOKEN_LENGTH 255
  3418. +
  3419. +enum dc_token {
  3420. +   DCT_NONE = 0,   //!< No token
  3421. +   DCT_STRING,     //!< String
  3422. +   DCT_FLOAT,      //!< Floating point
  3423. +   DCT_INT,        //!< Integral
  3424. +   DCT_UINT,       //!< Unsigned Integral
  3425. +   DCT_BYTE,       //!< Integral with values between -128 and 127
  3426. +   DCT_UBYTE,      //!< Integral with values between 0 and 255
  3427. +   DCT_BOOL,       //!< Integral or string evaluated as a boolean
  3428. +
  3429. +   DCT_MAX_ITEMS   //!< Maximum number of dc_token elements. Primarily used as an end value in loops
  3430. +};
  3431. +
  3432. +/**
  3433. + * Human readable versions of the dc_token's. Primarily used in error diagnosis
  3434. + */
  3435. +static
  3436. +const char *token_str[DCT_MAX_ITEMS] =
  3437. +{
  3438. +   "nothing",
  3439. +   "string",
  3440. +   "float",
  3441. +   "integer",
  3442. +   "unsigned integer",
  3443. +   "byte",
  3444. +   "unsigned byte",
  3445. +   "boolean"
  3446. +};
  3447. +
  3448. +/**
  3449. + * @class errParse
  3450. + *
  3451. + * @brief Class thrown when a required token is not found
  3452. + *
  3453. + *  @details This is a basic parser error, it contains the token (a single word) that was found, and the expected token
  3454. + *      type. Some DCT's, such as the DCT_STRING's, have their own specific requirements for error handling, and as
  3455. + *      such get their own class derived from errParse. The catching routines should be able to catch the derived error
  3456. + *      objects, but if not, they can be caught by a routine looking for the base class and then be casted to their
  3457. + *      proper type.
  3458. + */
  3459. +class errParse {
  3460. +public:
  3461. +   SCP_string found_token;
  3462. +   dc_token expected_type;
  3463. +
  3464. +   /**
  3465. +   *  @brief Invalid/Unexpected token constructor
  3466. +   *  @param [in] found_str The token that was found
  3467. +   *  @param [in] expected_dct The token type that was expected
  3468. +   */
  3469. +   errParse(const char *found_str, dc_token expected_dct)
  3470. +       : found_token(found_str), expected_type(expected_dct)
  3471. +   {
  3472. +   }
  3473. +};
  3474. +
  3475. +/**
  3476. + * @class errParseString
  3477. + *
  3478. + * @brief Class thrown when an expected string was not found. Can/should contain all of the expected strings.
  3479. + */
  3480. +class errParseString : public errParse
  3481. +{
  3482. +public:
  3483. +   SCP_vector<SCP_string> expected_tokens;
  3484. +
  3485. +   /**
  3486. +    *  @brief Invalid/Unexpected token constructor.
  3487. +    *  
  3488. +    *  @param [in] found_str The string that was found
  3489. +    *  @param [in] str The token that was expected
  3490. +    */
  3491. +   errParseString(const char *found_str, char *str)
  3492. +       : errParse(found_str, DCT_STRING)
  3493. +   {
  3494. +       expected_tokens.push_back(str);
  3495. +   }
  3496. +
  3497. +   /**
  3498. +    *  @brief Invalid/Unexpected token constructor.
  3499. +    *  
  3500. +    *  @param [in] found_str The string that was found
  3501. +    *  @param [in] str1 The first token that was expected
  3502. +    *  @param [in] str2 The second token that was expected
  3503. +    */
  3504. +   errParseString(const char *found_str, char *str1, char *str2)
  3505. +       : errParse(found_str, DCT_STRING)
  3506. +   {
  3507. +       expected_tokens.push_back(str1);
  3508. +       expected_tokens.push_back(str2);
  3509. +   }
  3510. +
  3511. +   /**
  3512. +    *  @brief Invalid/Unexpected token constructor.
  3513. +    *  
  3514. +    *  @param [in] found_str The string that was found
  3515. +    *  @param [in] n The number of strings that were expected
  3516. +    *  @param [in] ... The strings that were expected
  3517. +    */
  3518. +   errParseString(const char *found_str, SCP_vector<SCP_string> &strings)
  3519. +       : errParse(found_str, DCT_STRING), expected_tokens(strings)
  3520. +   {
  3521. +   }
  3522. +};
  3523. +
  3524. +/**
  3525. + * @class errParseOverflow
  3526. + *
  3527. + * @brief Class thrown when the parsed string or token could not be stuffed into the smaller destination container
  3528. + *
  3529. + * @var found_str Contains the first 'len' valid characters.
  3530. + */
  3531. +class errParseOverflow : public errParse
  3532. +{
  3533. +public:
  3534. +   size_t len;     //!< The size of the destination container
  3535. +
  3536. +   errParseOverflow(const char *found_str, size_t _len)
  3537. +       : errParse(found_str, DCT_STRING), len(_len)
  3538. +   {
  3539. +   }
  3540. +};
  3541. +
  3542. +/**
  3543. + * @brief Initializes the DC command line parser
  3544. + */
  3545. +void dc_parse_init(SCP_string &str);
  3546. +
  3547. +/**
  3548. + * @brief Advances the parser past whitespace characters
  3549. + */
  3550. +void dc_ignore_white_space(void);
  3551. +
  3552. +/**
  3553. + * @brief Advances the parser past grayspace characters
  3554. + */
  3555. +void dc_ignore_gray_space(void);
  3556. +
  3557. +// Required/Optional Token
  3558. +/**
  3559. + * @brief Searches for a specified required string, throwing an errParse if not found.
  3560. + *
  3561. + * @param[in] pstr The string to search for
  3562. + *
  3563. + * @throws errParseString with the required string
  3564. + */
  3565. +void dc_required_string(char *pstr);
  3566. +
  3567. +/**
  3568. + * @brief Searchs for either of the specified required strings, throwing an errParse if neither are found
  3569. + *
  3570. + * @param[in] str1 The first string to search for
  3571. + * @param[in] str2 The second string to search for
  3572. + *
  3573. + * @retval 0 if str1 was found, or
  3574. + * @retval 1 if str2 was found
  3575. + *
  3576. + * @throws errParseString with the required strings
  3577. + */
  3578. +int dc_required_string_either(char *str1, char *str2);
  3579. +
  3580. +/**
  3581. + * @brief Searches for specified required strings
  3582. + *
  3583. + * @param[in] n The number of char[] or c_str's given
  3584. + * @param[in] ... A comma delimited list of one or more required strings.
  3585. + *
  3586. + * @returns The index of the specified required strings (as if they were an array)
  3587. + *
  3588. + * @throws errParseString with the required strings
  3589. + */
  3590. +int dc_required_string_any(const uint n, ...);
  3591. +
  3592. +/**
  3593. + * @brief Searches for an optional string
  3594. + *
  3595. + * @param[in] pstr The char[] to look for
  3596. + *
  3597. + * @retval true if the string was found,
  3598. + * @retval false otherwise
  3599. + */
  3600. +bool dc_optional_string(const char *pstr);
  3601. +
  3602. +/**
  3603. + * @brief Searches for an optional string and it's alias
  3604. + *
  3605. + * @param[in] str1 The char[] to look for
  3606. + * @param[in] str2 The alternative char[] to look for
  3607. + *
  3608. + * @retval true if the string was found,
  3609. + * @retval false otherwise
  3610. + */
  3611. +bool dc_optional_string_either(const char *str1, const char *str2);
  3612. +
  3613. +
  3614. +// ==========================
  3615. +// Stuffers
  3616. +// ==========================
  3617. +
  3618. +/**
  3619. + * @brief Stuffs a float to the given variable.
  3620. + *
  3621. + * @param[in] f  The float variable to stuff to
  3622. + *
  3623. + * @throws errParse if an unexpected or otherwise malformed float string is found.
  3624. + * @throws errParse if nothing was found
  3625. + */
  3626. +void dc_stuff_float(float *f);
  3627. +
  3628. +/**
  3629. + * @brief Stuffs an int to the given variable. Supports binary (0b), hexadecimal (0x), and octal (0o) formats
  3630. + *
  3631. + * @param[in] i  The int variable to stuff to
  3632. + *
  3633. + * @details The binary, hexadecimal, and octal formats must be prefixed by their associated string.
  3634. + *   Ex: "0xDEADBEEF" would be parsed properly while "DEADBEEF" would throw an error
  3635. + *
  3636. + * @throws errParse if an unexpected or otherwise malformed float string is found.
  3637. + * @throws errParse if nothing was found
  3638. + */
  3639. +void dc_stuff_int(int *i);
  3640. +
  3641. +/**
  3642. + * @brief Stuffs an unsigned int to the given variable. Supports binary (0b), hexadecimal (0x), and octal (0o) formats
  3643. + *
  3644. + * @param[in] i  The unsigned int variable to stuff to
  3645. + *
  3646. + * @details The binary, hexadecimal, and octal formats must be prefixed by their associated string.
  3647. + *   Ex: "0xDEADBEEF" would be parsed properly while "DEADBEEF" would throw an error
  3648. + *
  3649. + * @throws errParse if an unexpected or otherwise malformed float string is found.
  3650. + * @throws errParse if nothing was found
  3651. + */
  3652. +void dc_stuff_uint(uint *i);
  3653. +
  3654. +/**
  3655. + * @brief Stuffs an unsigned byte to the given variable. Supports binary (0b), hexadecimal (0x), and octal (0o) formats
  3656. + *
  3657. + * @param[in] i  The ubyte variable to stuff to
  3658. + *
  3659. + * @details The binary, hexadecimal, and octal formats must be prefixed by their associated string.
  3660. + *   Ex: "0x0F" would be parsed properly while "0F" would throw an error
  3661. + *
  3662. + * @throws errParse if an unexpected or otherwise malformed float string is found.
  3663. + * @throws errParse if nothing was found
  3664. + */
  3665. +void dc_stuff_ubyte(ubyte *i);
  3666. +
  3667. +/**
  3668. + * @brief stuffs a boolean evaluated integer or string into the given variable.
  3669. + *
  3670. + * @param[in] b The bool variable to stuff to
  3671. + *
  3672. + * @details Supports a number of literal strings as true and false, including "true", "false", "yes", "no" and the
  3673. + *   yes/no equivalents in other languages supported in localization.
  3674. + *   TODO: Make a static string map to handle this instead of being hard-coded
  3675. + *
  3676. + * @throws errParse if an unexpected or otherwise malformed float string is found.
  3677. + * @throws errParse if nothing was found
  3678. + */
  3679. +void dc_stuff_boolean(bool *b);
  3680. +
  3681. +/**
  3682. + * @brief stuffs a boolean evaluated integer or string into the given variable.
  3683. + *
  3684. + * @param[in] i The int variable to stuff to. 0 is false, 1 is true
  3685. + *
  3686. + * @details Supports a number of literal strings as true and false, including "true", "false", "yes", "no" and the
  3687. + *   yes/no equivalents in other languages supported in localization.
  3688. + *   TODO: Make a static string map to handle this instead of being hard-coded
  3689. + *
  3690. + * @throws errParse if an unexpected or otherwise malformed float string is found.
  3691. + * @throws errParse if nothing was found
  3692. + */
  3693. +void dc_stuff_boolean(int *i);
  3694. +
  3695. +/**
  3696. + * @brief Stuffs a string to out_str from the command line, stopping at the end of the command line
  3697. + *
  3698. + * @param[out] out_str  Destination string
  3699. + * @param[in]  maxlen   Maximum length to copy. (maxlen <= sizeof(str)) && (maxlen <= MAX_TOKEN_LENGTH)
  3700. + *
  3701. + * @throws errParse when nothing left was found on the command line
  3702. + * @throws errParseOverflow when parser cannot stuff the entirety of the found string into out_str
  3703. + */
  3704. +void dc_stuff_string(char *str, size_t maxlen);
  3705. +
  3706. +/**
  3707. + * @brief Stuffs a string to out_str from the command line, stopping at the end of the command line
  3708. + *
  3709. + * @param[out] out_str  Destination string
  3710. + *
  3711. + * @throws errParse when nothing left was found on the command line
  3712. + */
  3713. +void dc_stuff_string(SCP_string &str);
  3714. +
  3715. +/**
  3716. + * @brief Stuffs a whitespace delimited string to out_str from the command line, stopping at the end of the command line
  3717. + *
  3718. + * @param[out] out_str  Destination string
  3719. + * @param[in]  maxlen   Maximum length to copy. (maxlen <= sizeof(str)) && (maxlen <= MAX_TOKEN_LENGTH)
  3720. + *
  3721. + * @throws errParse when nothing left was found on the command line
  3722. + * @throws errParseOverflow when parser cannot stuff the entirety of the found string into out_str
  3723. + */
  3724. +void dc_stuff_string_white(char *str, size_t len);
  3725. +
  3726. +/**
  3727. + * @brief Stuffs a whitespace delimited string to out_str from the command line, stopping at the end of the command line
  3728. + *
  3729. + * @param[out] out_str  Destination string
  3730. + * @param[in]  maxlen   Maximum length to copy. (maxlen <= sizeof(str)) && (maxlen <= MAX_TOKEN_LENGTH)
  3731. + *
  3732. + * @throws errParse when nothing left was found on the command line
  3733. + */
  3734. +void dc_stuff_string_white(SCP_string &str);
  3735. +
  3736. +/**
  3737. + * @brief Tries to stuff a float from the Command_string.
  3738. + *
  3739. + * @param[in] f  The float variable to maybe stuff.
  3740. + *
  3741. + * @details
  3742. + *   If there's nothing on the command line, *f = 0 and false is returned
  3743. + *
  3744. + *   If there's something on the command line, and we're able to convert it, *f = the converted value, true is
  3745. + *     returned, and the parser is advanced past the token
  3746. + *
  3747. + *   If there's something on command line, but we can't convert it, an errParse is thrown
  3748. + */
  3749. +bool dc_maybe_stuff_float(float *f);
  3750. +
  3751. +/**
  3752. + * @brief Tries to stuff an int from the Command_string.
  3753. + *
  3754. + * @param[in] i  The int variable to maybe stuff.
  3755. + *
  3756. + * @details
  3757. + *   If there's nothing on the command line, *i = 0 and false is returned
  3758. + *
  3759. + *   If there's something on the command line, and we're able to convert it, *i = the converted value, true is
  3760. + *     returned, and the parser is advanced past the token
  3761. + *
  3762. + *   If there's something on command line, but we can't convert it, an errParse is thrown
  3763. + */
  3764. +bool dc_maybe_stuff_int(int *i);
  3765. +
  3766. +/**
  3767. + * @brief Tries to stuff an uint from the Command_string.
  3768. + *
  3769. + * @param[in] i  The uint variable to maybe stuff.
  3770. + *
  3771. + * @details
  3772. + *   If there's nothing on the command line, *i = 0 and false is returned
  3773. + *
  3774. + *   If there's something on the command line, and we're able to convert it, *i = the converted value, true is
  3775. + *     returned, and the parser is advanced past the token
  3776. + *
  3777. + *   If there's something on command line, but we can't convert it, an errParse is thrown
  3778. + */
  3779. +bool dc_maybe_stuff_uint(uint *i);
  3780. +
  3781. +/**
  3782. + * @brief Tries to stuff an ubyte from the Command_string.
  3783. + *
  3784. + * @param[in] i  The ubyte variable to maybe stuff.
  3785. + *
  3786. + * @details
  3787. + *   If there's nothing on the command line, *i = 0 and false is returned
  3788. + *
  3789. + *   If there's something on the command line, and we're able to convert it, *i = the converted value, true is
  3790. + *     returned, and the parser is advanced past the token
  3791. + *
  3792. + *   If there's something on command line, but we can't convert it, an errParse is thrown
  3793. + */
  3794. +bool dc_maybe_stuff_ubyte(ubyte *i);
  3795. +
  3796. +/**
  3797. + * @brief Tries to stuff a bool from the Command_string.
  3798. + *
  3799. + * @param[in] b  The bool variable to maybe stuff.
  3800. + *
  3801. + * @details
  3802. + *   If there's nothing on the command line, *b = false and false is returned
  3803. + *
  3804. + *   If there's something on the command line, and we're able to convert it, *b = the converted value, true is
  3805. + *     returned, and the parser is advanced past the token
  3806. + *
  3807. + *   If there's something on command line, but we can't convert it, an errParse is thrown
  3808. + */
  3809. +bool dc_maybe_stuff_boolean(bool *b);
  3810. +
  3811. +/**
  3812. + * @brief Tries to stuff an int with a bool value from the Command_string.
  3813. + *
  3814. + * @param[in] i  The int variable to maybe stuff.
  3815. + *
  3816. + * @details
  3817. + *   If there's nothing on the command line, *i = 0 and false is returned
  3818. + *
  3819. + *   If there's something on the command line, and we're able to convert it, *i = the converted value, true is
  3820. + *     returned, and the parser is advanced past the token
  3821. + *
  3822. + *   If there's something on command line, but we can't convert it, an errParse is thrown
  3823. + */
  3824. +bool dc_maybe_stuff_boolean(int *i);
  3825. +
  3826. +/**
  3827. + * @brief Tries to stuff a string to out_str from the command line, stopping at the end of the command line
  3828. + *
  3829. + * @param[out] out_str  Destination string. If nothing was found, out_str = ""
  3830. + * @param[in]  len   Maximum length to copy. (maxlen <= sizeof(str)) && (maxlen <= MAX_TOKEN_LENGTH)
  3831. + *
  3832. + * @retval true if the operation was successful,
  3833. + * @retval false otherwise
  3834. + *
  3835. + * @throws errParseOverflow when parser cannot stuff the entirety of the found string into out_str
  3836. + */
  3837. +bool dc_maybe_stuff_string(char *str, size_t len);
  3838. +
  3839. +/**
  3840. + * @brief Tries to stuff a string to out_str from the command line, stopping at the end of the command line
  3841. + *
  3842. + * @param[out] out_str  Destination string. If nothing was found, out_str = ""
  3843. + *
  3844. + * @retval true if the operation was successful,
  3845. + * @retval false otherwise
  3846. + */
  3847. +bool dc_maybe_stuff_string(SCP_string &str);
  3848. +
  3849. +/**
  3850. + * @brief Tries to stuff a whitespace delimited string to out_str from the command line, stopping at the end of the command line
  3851. + *
  3852. + * @param[out] out_str  Destination string. If nothing was found, out_str = ""
  3853. + * @param[in]  len   Maximum length to copy. (maxlen <= sizeof(str)) && (maxlen <= MAX_TOKEN_LENGTH)
  3854. + *
  3855. + * @retval true if the operation was successful,
  3856. + * @retval false otherwise
  3857. + *
  3858. + * @throws errParseOverflow when parser cannot stuff the entirety of the found string into out_str
  3859. + */
  3860. +bool dc_maybe_stuff_string_white(char *str, size_t len);
  3861. +
  3862. +/**
  3863. + * @brief Tries to stuff a whitespace delimited string to out_str from the command line, stopping at the end of the command line
  3864. + *
  3865. + * @param[out] out_str  Destination string. If nothing was found, out_str = ""
  3866. + *
  3867. + * @retval true if the operation was successful,
  3868. + * @retval false otherwise
  3869. + */
  3870. +bool dc_maybe_stuff_string_white(SCP_string &str);
  3871. +
  3872. +#endif // _CONSOLEPARSE_H
  3873. \ No newline at end of file
  3874. diff --git a/code/freespace2/freespace.cpp b/code/freespace2/freespace.cpp
  3875. index 7f9c686..dd533de 100644
  3876. --- a/code/freespace2/freespace.cpp
  3877. +++ b/code/freespace2/freespace.cpp
  3878. @@ -33,6 +33,7 @@
  3879.  #include "cutscene/cutscenes.h"
  3880.  #include "cutscene/movie.h"
  3881.  #include "debris/debris.h"
  3882. +#include "debugconsole/console.h"
  3883.  #include "exceptionhandler/exceptionhandler.h"
  3884.  #include "external_dll/trackirpublic.h" // header file for the TrackIR routines (Swifty)
  3885.  #include "fireball/fireballs.h"
  3886. @@ -665,10 +666,9 @@ void big_explosion_flash(float flash)
  3887.  int Sun_drew = 0;
  3888.  
  3889.  float sn_glare_scale = 1.7f;
  3890. -DCF(sn_glare, "")
  3891. +DCF(sn_glare, "Sets the sun glare scale (Default is 1.7)")
  3892.  {
  3893. -   dc_get_arg(ARG_FLOAT);
  3894. -   sn_glare_scale = Dc_arg_float;
  3895. +   dc_stuff_float(&sn_glare_scale);
  3896.  }
  3897.  
  3898.  float Supernova_last_glare = 0.0f;
  3899. @@ -1499,80 +1499,101 @@ DCF_BOOL(i_framerate, Interface_framerate )
  3900.  
  3901.  DCF(warp, "Tests warpin effect")
  3902.  {
  3903. -   if ( Dc_command )   {
  3904. -       bool warpin = true;
  3905. -       int idx = -1;
  3906. +   if (dc_optional_string_either("help", "--help")) {
  3907. +       dc_printf( "Params: bool warpin, string Target = ""\n  Warps in if true, out if false. Player is target unless specific ship is specified\n" );
  3908. +       return;
  3909. +   } // Else, process command
  3910.  
  3911. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
  3912. -       if( Dc_arg_type & ARG_TRUE) warpin = true;
  3913. -       else if(Dc_arg_type & ARG_FALSE) warpin = false;
  3914. +   // TODO: Provide status flag
  3915.  
  3916. -       if(!(Dc_arg_type & ARG_NONE))
  3917. -       {
  3918. -           dc_get_arg(ARG_STRING|ARG_NONE);
  3919. -           if(Dc_arg_type & ARG_STRING)
  3920. -           {
  3921. -               idx = ship_name_lookup(Dc_arg);
  3922. -               if(idx > -1)
  3923. -               {
  3924. -                   if(warpin)
  3925. -                       shipfx_warpin_start(&Objects[Ships[idx].objnum]);
  3926. -                   else
  3927. -                       shipfx_warpout_start(&Objects[Ships[idx].objnum]);
  3928. -               }
  3929. +   bool warpin;
  3930. +   char target[MAX_NAME_LEN];
  3931. +   int idx = -1;
  3932. +
  3933. +   dc_stuff_boolean(&warpin);
  3934. +   if (dc_maybe_stuff_string_white(target, MAX_NAME_LEN)) {
  3935. +       idx = ship_name_lookup(target);
  3936. +   }   // Else, default target to player
  3937. +  
  3938. +   if (idx < 0) {
  3939. +       // Player is target
  3940. +       if (Player_ai->target_objnum > -1) {
  3941. +           if(warpin) {
  3942. +               shipfx_warpin_start(&Objects[Player_ai->target_objnum]);
  3943. +           } else {
  3944. +               shipfx_warpout_start(&Objects[Player_ai->target_objnum]);
  3945.             }
  3946.         }
  3947. -      
  3948. -       if(idx < 0)
  3949. -       {
  3950. -           if(Player_ai->target_objnum > -1)
  3951. -           {
  3952. -               if(warpin)
  3953. -                   shipfx_warpin_start(&Objects[Player_ai->target_objnum]);
  3954. -               else
  3955. -                   shipfx_warpout_start(&Objects[Player_ai->target_objnum]);
  3956. -           }
  3957. +   } else {
  3958. +       // Non-player is targer
  3959. +       if (warpin) {
  3960. +           shipfx_warpin_start(&Objects[Ships[idx].objnum]);
  3961. +       } else {
  3962. +           shipfx_warpout_start(&Objects[Ships[idx].objnum]);
  3963.         }
  3964. -   }  
  3965. -   if ( Dc_help )  dc_printf( "Usage: Show_mem\nWarps in if true, out if false, player target unless specific ship is specified\n" )
  3966. +   }
  3967. +  
  3968.  }
  3969.  
  3970.  DCF(show_mem,"Toggles showing mem usage")
  3971.  {
  3972. -   if ( Dc_command )   {  
  3973. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  3974. -       if ( Dc_arg_type & ARG_TRUE )   Show_mem = 1;  
  3975. -       else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;  
  3976. -       else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;  
  3977. +   bool process = true;
  3978.  
  3979. -       if ( Show_mem ) {
  3980. -           Show_cpu = 0;
  3981. -       }
  3982. -   }  
  3983. -   if ( Dc_help )  dc_printf( "Usage: Show_mem\nSets show_mem to true or false.  If nothing passed, then toggles it.\n" );
  3984. -   if ( Dc_status )    {
  3985. -       dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
  3986. -       dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
  3987. +   if (dc_optional_string_either("help", "--help")) {
  3988. +       dc_printf( "Usage: (optional) bool Show_mem\n If true, Show_mem is set and Show_cpu is cleared.  If false, then Show_mem is cleared.  If nothing passed, then toggle.\n" );
  3989. +       process = false;
  3990. +   }
  3991. +  
  3992. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  3993. +       dc_printf("Show_mem is %s\n", (Show_mem ? "TRUE" : "FALSE"));
  3994. +       dc_printf("Show_cpu is %s\n", (Show_cpu ? "TRUE" : "FALSE"));
  3995. +       process = false;
  3996. +   }
  3997. +  
  3998. +   if (!process) {
  3999. +       // Help and/or status was given, so don't process the command
  4000. +       return;
  4001. +   } // Else, process the command
  4002. +
  4003. +   if (!dc_maybe_stuff_boolean(&Show_mem)) {
  4004. +       // Nothing passed, so toggle
  4005. +       Show_mem = !Show_mem;
  4006. +   }   // Else, value was set/cleared by user
  4007. +
  4008. +   // Can't show mem and cpu at same time
  4009. +   if (Show_mem) {
  4010. +       Show_cpu = false;
  4011.     }
  4012.  }
  4013.  
  4014.  DCF(show_cpu,"Toggles showing cpu usage")
  4015.  {
  4016. -   if ( Dc_command )   {  
  4017. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  4018. -       if ( Dc_arg_type & ARG_TRUE )   Show_cpu = 1;  
  4019. -       else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;  
  4020. -       else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;  
  4021. +   bool process = true;
  4022.  
  4023. -       if ( Show_cpu ) {
  4024. -           Show_mem = 0;
  4025. -       }
  4026. -   }  
  4027. -   if ( Dc_help )  dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false.  If nothing passed, then toggles it.\n" );
  4028. -   if ( Dc_status )    {
  4029. -       dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
  4030. -       dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
  4031. +   if (dc_optional_string_either("help", "--help")) {
  4032. +       dc_printf( "Usage: (optional) bool Show_cpu\n If true, Show_cpu is set and Show_mem is cleared.  If false, then Show_cpu is cleared.  If nothing passed, then toggle.\n" );
  4033. +       process = false;
  4034. +   }
  4035. +  
  4036. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4037. +       dc_printf("Show_cpu is %s\n", (Show_cpu ? "TRUE" : "FALSE"));
  4038. +       dc_printf("Show_mem is %s\n", (Show_mem ? "TRUE" : "FALSE"));
  4039. +       process = false;
  4040. +   }
  4041.  
  4042. +   if (!process) {
  4043. +       // Help and/or status was given, so don't process the command
  4044. +       return;
  4045. +   } // Else, process the command
  4046. +
  4047. +   if (!dc_maybe_stuff_boolean(&Show_cpu)) {
  4048. +       // Nothing passed, so toggle
  4049. +       Show_cpu = !Show_cpu;
  4050. +   }   // Else, value was set/cleared by user
  4051. +
  4052. +   // Can't show mem and cpu at same time
  4053. +   if (Show_cpu) {
  4054. +       Show_mem = false;
  4055.     }
  4056.  }
  4057.  
  4058. @@ -1582,42 +1603,56 @@ DCF(show_cpu,"Toggles showing cpu usage")
  4059.  
  4060.  DCF(use_joy_mouse,"Makes joystick move mouse cursor")
  4061.  {
  4062. -   if ( Dc_command )   {  
  4063. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  4064. -       if ( Dc_arg_type & ARG_TRUE )   Use_joy_mouse = 1
  4065. -       else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0
  4066. -       else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1
  4067. -   }  
  4068. -   if ( Dc_help )  dc_printf( "Usage: use_joy_mouse [bool]\nSets use_joy_mouse to true or false.  If nothing passed, then toggles it.\n" );   
  4069. -   if ( Dc_status )    dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );  
  4070. +   bool process = true;
  4071. +
  4072. +   if (dc_optional_string_either("help", "--help")) {
  4073. +       dc_printf("Usage: use_joy_mouse [bool]\nSets use_joy_mouse to true or false.  If nothing passed, then toggles it.\n");
  4074. +       process = false;
  4075. +   }
  4076. +
  4077. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4078. +       dc_printf("use_joy_mouse is %s\n", (Use_joy_mouse ? "TRUE" : "FALSE"));
  4079. +       process = false;
  4080. +   }
  4081. +
  4082. +   if (!process) {
  4083. +       return;
  4084. +   }
  4085. +
  4086. +   if(!dc_maybe_stuff_boolean(&Use_joy_mouse)) {
  4087. +       // Nothing passed, so toggle
  4088. +       Use_joy_mouse = !Use_joy_mouse;
  4089. +   } // Else, value was set/cleared by user
  4090.  
  4091.     os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
  4092.  }
  4093.  
  4094. -DCF(palette_flash,"Toggles palette flash effect on/off")
  4095. -{
  4096. -   if ( Dc_command )   {  
  4097. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  4098. -       if ( Dc_arg_type & ARG_TRUE )   Use_palette_flash = 1
  4099. -       else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0
  4100. -       else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1
  4101. -   }  
  4102. -   if ( Dc_help )  dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false.  If nothing passed, then toggles it.\n" );   
  4103. -   if ( Dc_status )    dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );  
  4104. -}
  4105. +DCF_BOOL(palette_flash, Use_palette_flash);
  4106.  
  4107.  int Use_low_mem = 0;
  4108.  
  4109.  DCF(low_mem,"Uses low memory settings regardless of RAM")
  4110.  {
  4111. -   if ( Dc_command )   {  
  4112. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  4113. -       if ( Dc_arg_type & ARG_TRUE )   Use_low_mem = 1;   
  4114. -       else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;   
  4115. -       else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;   
  4116. -   }  
  4117. -   if ( Dc_help )  dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false.  If nothing passed, then toggles it.\n" );   
  4118. -   if ( Dc_status )    dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );  
  4119. +   bool process = true;
  4120. +
  4121. +   if (dc_optional_string_either("help", "--help")) {
  4122. +       dc_printf("Usage: low_mem [bool]\nSets low_mem to true or false.  If nothing passed, then toggles it.\n");
  4123. +       process = false;
  4124. +   }
  4125. +
  4126. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4127. +       dc_printf("low_mem is %s\n", (Use_low_mem ? "TRUE" : "FALSE"));
  4128. +       process = false;
  4129. +   }
  4130. +
  4131. +   if (!process) {
  4132. +       return;
  4133. +   }
  4134. +
  4135. +   if (!dc_maybe_stuff_boolean(&Use_low_mem)) {
  4136. +       // Nothing passed, so toggle
  4137. +       Use_low_mem = !Use_low_mem;
  4138. +   } // Else, value was set/cleared by user
  4139.  
  4140.     os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
  4141.  }
  4142. @@ -1627,14 +1662,26 @@ DCF(low_mem,"Uses low memory settings regardless of RAM")
  4143.  
  4144.  DCF(force_fullscreen, "Forces game to startup in fullscreen mode")
  4145.  {
  4146. -   if ( Dc_command )   {  
  4147. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  4148. -       if ( Dc_arg_type & ARG_TRUE )   Use_fullscreen_at_startup = 1
  4149. -       else if ( Dc_arg_type & ARG_FALSE ) Use_fullscreen_at_startup = 0
  4150. -       else if ( Dc_arg_type & ARG_NONE ) Use_fullscreen_at_startup ^= 1
  4151. -   }  
  4152. -   if ( Dc_help )  dc_printf( "Usage: force_fullscreen [bool]\nSets force_fullscreen to true or false.  If nothing passed, then toggles it.\n" )
  4153. -   if ( Dc_status )    dc_printf( "force_fullscreen is %s\n", (Use_fullscreen_at_startup?"TRUE":"FALSE") );   
  4154. +   bool process = true;
  4155. +   if (dc_optional_string_either("help", "--help")) {
  4156. +       dc_printf("Usage: low_mem [bool]\nSets low_mem to true or false.  If nothing passed, then toggles it.\n");
  4157. +       process = false;
  4158. +   }
  4159. +
  4160. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4161. +       dc_printf("low_mem is %s\n", (Use_fullscreen_at_startup ? "TRUE" : "FALSE"));
  4162. +       process = false;
  4163. +   }
  4164. +
  4165. +   if (!process) {
  4166. +       return;
  4167. +   }
  4168. +
  4169. +   if (dc_maybe_stuff_boolean(&Use_fullscreen_at_startup)) {
  4170. +       // Nothing passed, so toggle
  4171. +       Use_fullscreen_at_startup = !Use_fullscreen_at_startup;
  4172. +   } // Else, value was set/cleared by user
  4173. +
  4174.     os_config_write_uint( NULL, NOX("ForceFullscreen"), Use_fullscreen_at_startup );
  4175.  }
  4176.  #endif
  4177. @@ -1643,37 +1690,33 @@ int Framerate_delay = 0;
  4178.  
  4179.  float FreeSpace_gamma = 1.0f;
  4180.  
  4181. -DCF(gamma,"Sets Gamma factor")
  4182. +DCF(gamma,"Sets and saves Gamma Factor")
  4183.  {
  4184. -   if ( Dc_command )   {
  4185. -       dc_get_arg(ARG_FLOAT|ARG_NONE);
  4186. -       if ( Dc_arg_type & ARG_FLOAT )  {
  4187. -           FreeSpace_gamma = Dc_arg_float;
  4188. -       } else {
  4189. -           dc_printf( "Gamma reset to 1.0f\n" );
  4190. -           FreeSpace_gamma = 1.0f;
  4191. -       }
  4192. -       if ( FreeSpace_gamma < 0.1f )   {
  4193. -           FreeSpace_gamma = 0.1f;
  4194. -       } else if ( FreeSpace_gamma > 5.0f )    {
  4195. -           FreeSpace_gamma = 5.0f;
  4196. -       }
  4197. -       gr_set_gamma(FreeSpace_gamma);
  4198. -
  4199. -       char tmp_gamma_string[32];
  4200. -       sprintf( tmp_gamma_string, NOX("%.2f"), FreeSpace_gamma );
  4201. -       os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
  4202. -   }
  4203. -
  4204. -   if ( Dc_help )  {
  4205. +   if (dc_optional_string_either("help", "--help")) {
  4206.         dc_printf( "Usage: gamma <float>\n" );
  4207.         dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
  4208. -       Dc_status = 0;  // don't print status if help is printed.  Too messy.
  4209. +       return;
  4210.     }
  4211.  
  4212. -   if ( Dc_status )    {
  4213. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4214.         dc_printf( "Gamma = %.2f\n", FreeSpace_gamma );
  4215. +       return;
  4216. +   }
  4217. +
  4218. +   if (!dc_maybe_stuff_float(&FreeSpace_gamma)) {
  4219. +       dc_printf( "Gamma reset to 1.0f\n" );
  4220. +       FreeSpace_gamma = 1.0f;
  4221.     }
  4222. +   if ( FreeSpace_gamma < 0.1f )   {
  4223. +       FreeSpace_gamma = 0.1f;
  4224. +   } else if ( FreeSpace_gamma > 5.0f )    {
  4225. +       FreeSpace_gamma = 5.0f;
  4226. +   }
  4227. +   gr_set_gamma(FreeSpace_gamma);
  4228. +
  4229. +   char tmp_gamma_string[32];
  4230. +   sprintf( tmp_gamma_string, NOX("%.2f"), FreeSpace_gamma );
  4231. +   os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
  4232.  }
  4233.  
  4234.  #ifdef APPLE_APP
  4235. @@ -2399,33 +2442,54 @@ void game_show_time_left()
  4236.  
  4237.  DCF(ai_pause,"Pauses ai")
  4238.  {
  4239. -   if ( Dc_command )   {  
  4240. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  4241. -       if ( Dc_arg_type & ARG_TRUE )   ai_paused = 1
  4242. -       else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0
  4243. -       else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused; 
  4244. +   bool process = true;
  4245. +  
  4246. +   if (dc_optional_string_either("help", "--help")) {
  4247. +       dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false.  If nothing passed, then toggles it.\n" );
  4248. +       process = false;
  4249. +   }
  4250.  
  4251. -       if (ai_paused)  {  
  4252. -           obj_init_all_ships_physics();
  4253. -       }
  4254. -   }  
  4255. -   if ( Dc_help )  dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false.  If nothing passed, then toggles it.\n" );   
  4256. -   if ( Dc_status )    dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );  
  4257. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4258. +       dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
  4259. +       process = false;
  4260. +   }
  4261. +
  4262. +   if (!process) {
  4263. +       return;
  4264. +   }
  4265. +
  4266. +   if (!dc_maybe_stuff_boolean(&ai_paused)) {
  4267. +       ai_paused = !ai_paused;
  4268. +   }
  4269. +
  4270. +   if (ai_paused) {
  4271. +       obj_init_all_ships_physics();
  4272. +   }
  4273.  }
  4274.  
  4275. -DCF(single_step,"Single steps the game")
  4276. +DCF(single_step,"Enables single step mode.")
  4277.  {
  4278. -   if ( Dc_command )   {  
  4279. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  4280. -       if ( Dc_arg_type & ARG_TRUE )   game_single_step = 1;  
  4281. -       else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;  
  4282. -       else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;   
  4283. +   bool process = true;
  4284. +  
  4285. +   if (dc_optional_string_either("help", "--help")) {
  4286. +       dc_printf( "Usage: game_single_step [bool]\nEnables or disables single-step mode.  If nothing passed, then toggles it.\nSingle-step mode will freeze the game, and will advance frame by frame with each key press\n");
  4287. +       process = false;
  4288. +   }
  4289.  
  4290. -       last_single_step = 0;   // Make so single step waits a frame before stepping
  4291. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4292. +       dc_printf( "ai_paused is %s\n", (game_single_step ? "TRUE" : "FALSE") );
  4293. +       process = false;
  4294. +   }
  4295.  
  4296. -   }  
  4297. -   if ( Dc_help )  dc_printf( "Usage: single_step [bool]\nSets single_step to true or false.  If nothing passed, then toggles it.\n" );   
  4298. -   if ( Dc_status )    dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") )
  4299. +   if (!process) {
  4300. +       return;
  4301. +   }
  4302. +
  4303. +   if (!dc_maybe_stuff_boolean(&game_single_step)) {
  4304. +       game_single_step = !game_single_step;
  4305. +   }
  4306. +
  4307. +   last_single_step = 0;   // Make so single step waits a frame before stepping
  4308.  }
  4309.  
  4310.  DCF_BOOL(physics_pause, physics_paused)
  4311. @@ -2472,22 +2536,28 @@ int View_percent = 100;
  4312.  
  4313.  DCF(view, "Sets the percent of the 3d view to render.")
  4314.  {
  4315. -   if ( Dc_command ) {
  4316. -       dc_get_arg(ARG_INT);
  4317. -       if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
  4318. -           View_percent = Dc_arg_int;
  4319. -       } else {
  4320. -           dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
  4321. -           Dc_help = 1;
  4322. -       }
  4323. -   }
  4324. +   bool process = true;
  4325. +   int value;
  4326.  
  4327. -   if ( Dc_help ) {
  4328. +   if (dc_optional_string_either("help", "--help")) {
  4329.         dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
  4330. +       process = false;
  4331.     }
  4332. -  
  4333. -   if ( Dc_status ) {
  4334. +
  4335. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4336.         dc_printf("View is set to %d%%\n", View_percent );
  4337. +       process = false;
  4338. +   }
  4339. +
  4340. +   if (!process) {
  4341. +       return;
  4342. +   }
  4343. +
  4344. +   dc_stuff_int(&value);
  4345. +   if ( (value >= 5 ) && (value <= 100) ) {
  4346. +       View_percent = value;
  4347. +   } else {
  4348. +       dc_printf("Error: Outside legal range [5 - 100]");
  4349.     }
  4350.  }
  4351.  
  4352. @@ -2814,65 +2884,86 @@ void do_timing_test(float frame_time)
  4353.  DCF(dcf_fov, "Change the field of view of the main camera")
  4354.  {
  4355.     camera *cam = Main_camera.getCamera();
  4356. -   if ( Dc_command )
  4357. -   {
  4358. -       if(cam == NULL)
  4359. -           return;
  4360. +   bool process = true;
  4361. +   float value;
  4362.  
  4363. -       dc_get_arg(ARG_FLOAT|ARG_NONE);
  4364. -       if ( Dc_arg_type & ARG_NONE )   {
  4365. -           cam->set_fov(VIEWER_ZOOM_DEFAULT);
  4366. -           dc_printf( "Zoom factor reset\n" );
  4367. -       }
  4368. -       if ( Dc_arg_type & ARG_FLOAT )  {
  4369. -           if (Dc_arg_float < 0.25f) {
  4370. -               cam->set_fov(0.25f);
  4371. -               dc_printf("Zoom factor pinned at 0.25.\n");
  4372. -           } else if (Dc_arg_float > 1.25f) {
  4373. -               cam->set_fov(1.25f);
  4374. -               dc_printf("Zoom factor pinned at 1.25.\n");
  4375. -           } else {
  4376. -               cam->set_fov(Dc_arg_float);
  4377. -           }
  4378. +   if (dc_optional_string_either("help", "--help")) {
  4379. +       dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
  4380. +       process = false;
  4381. +   }
  4382. +
  4383. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4384. +       if(cam == NULL) {
  4385. +           dc_printf("Camera unavailable.");
  4386. +       } else {
  4387. +           dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)\n", cam->get_fov());
  4388.         }
  4389. +
  4390. +       process = false;
  4391.     }
  4392.  
  4393. -   if ( Dc_help ) 
  4394. -       dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
  4395. +   if ((cam == NULL) || (!process)) {
  4396. +       return;
  4397. +   }
  4398.  
  4399. -   if ( Dc_status )
  4400. -   {
  4401. -       if(cam == NULL)
  4402. -           dc_printf("Camera unavailable.");
  4403. -       else
  4404. -           dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", cam->get_fov());
  4405. +   if (!dc_maybe_stuff_float(&value)) {
  4406. +       // No value passed, use default
  4407. +       cam->set_fov(VIEWER_ZOOM_DEFAULT);
  4408. +   } else {
  4409. +       // Value passed, Clamp it to valid values
  4410. +       if (value < 0.25f) {
  4411. +           value = 0.25f;
  4412. +           dc_printf("Zoom factor clamped to 0.25\n");
  4413. +       } else if (value > 1.25f) {
  4414. +           value = 1.25f;
  4415. +           dc_printf("Zoom factor clamped to 1.25\n");
  4416. +       } else {
  4417. +           dc_printf("Zoom factor set to %6.3f\n", value);
  4418. +       }
  4419. +
  4420. +       cam->set_fov(value);
  4421.     }
  4422.  }
  4423.  
  4424.  
  4425.  DCF(framerate_cap, "Sets the framerate cap")
  4426.  {
  4427. -   if ( Dc_command ) {
  4428. -       dc_get_arg(ARG_INT);
  4429. -       if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
  4430. -           Framerate_cap = Dc_arg_int;
  4431. -       } else {
  4432. -           dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
  4433. -           Dc_help = 1;
  4434. -       }
  4435. -   }
  4436. +   bool process = true;
  4437.  
  4438. -   if ( Dc_help ) {
  4439. +   if (dc_optional_string_either("help", "--help")) {
  4440.         dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
  4441.         dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
  4442.         dc_printf("[n] must be from 1 to 120.\n");
  4443. +       process = false;
  4444.     }
  4445. -  
  4446. -   if ( Dc_status ) {
  4447. -       if ( Framerate_cap )
  4448. +
  4449. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4450. +       if ( Framerate_cap ) {
  4451.             dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
  4452. -       else
  4453. +       } else {
  4454.             dc_printf("There is no framerate cap currently active.\n");
  4455. +       }
  4456. +
  4457. +       process = false;
  4458. +   }
  4459. +
  4460. +   if (!process) {
  4461. +       return;
  4462. +   }
  4463. +
  4464. +   if (!dc_maybe_stuff_int(&Framerate_cap)) {
  4465. +       Framerate_cap = 0;
  4466. +   }
  4467. +
  4468. +   if ((Framerate_cap < 0) || (Framerate_cap > 120)) {
  4469. +       dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n");
  4470. +       Framerate_cap = 0;
  4471. +   }
  4472. +
  4473. +   if (Framerate_cap == 0) {
  4474. +       dc_printf("Framerate cap disabled");
  4475. +   } else {
  4476. +       dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
  4477.     }
  4478.  }
  4479.  
  4480. @@ -3774,87 +3865,71 @@ void john_debug_stuff(vec3d *eye_pos, matrix *eye_orient)
  4481.  #ifndef NDEBUG
  4482.  
  4483.  // function to toggle state of dumping every frame into PCX when playing the game
  4484. -DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
  4485. -{
  4486. -   if ( Dc_command )   {
  4487. -
  4488. -       if ( Debug_dump_frames == 0 )   {
  4489. -           // Turn it on
  4490. -           Debug_dump_frames = 15;
  4491. -           Debug_dump_trigger = 0;
  4492. -           gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
  4493. -           dc_printf( "Frame dumping at 15 hz is now ON\n" );
  4494. -       } else {
  4495. -           // Turn it off
  4496. -           Debug_dump_frames = 0;
  4497. -           Debug_dump_trigger = 0;
  4498. -           gr_dump_frame_stop();
  4499. -           dc_printf( "Frame dumping is now OFF\n" );
  4500. -       }
  4501. -      
  4502. +DCF(dump_frames, "Toggles On/off frame dumping at 15 hz")
  4503. +{
  4504. +   if ( Debug_dump_frames == 0 )   {
  4505. +       // Turn it on
  4506. +       Debug_dump_frames = 15;
  4507. +       Debug_dump_trigger = 0;
  4508. +       gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
  4509. +       dc_printf( "Frame dumping at 15 hz is now ON\n" );
  4510. +   } else {
  4511. +       // Turn it off
  4512. +       Debug_dump_frames = 0;
  4513. +       Debug_dump_trigger = 0;
  4514. +       gr_dump_frame_stop();
  4515. +       dc_printf( "Frame dumping is now OFF\n" );
  4516.     }
  4517.  }
  4518.  
  4519.  DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
  4520.  {
  4521. -   if ( Dc_command )   {
  4522. -
  4523. -       if ( Debug_dump_frames == 0 )   {
  4524. -           // Turn it on
  4525. -           Debug_dump_frames = 15;
  4526. -           Debug_dump_trigger = 1;
  4527. -           gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
  4528. -           dc_printf( "Frame dumping at 15 hz is now ON\n" );
  4529. -       } else {
  4530. -           // Turn it off
  4531. -           Debug_dump_frames = 0;
  4532. -           Debug_dump_trigger = 0;
  4533. -           gr_dump_frame_stop();
  4534. -           dc_printf( "Frame dumping is now OFF\n" );
  4535. -       }
  4536. -      
  4537. +   if ( Debug_dump_frames == 0 )   {
  4538. +       // Turn it on
  4539. +       Debug_dump_frames = 15;
  4540. +       Debug_dump_trigger = 1;
  4541. +       gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
  4542. +       dc_printf( "Frame dumping at 15 hz is now ON\n" );
  4543. +   } else {
  4544. +       // Turn it off
  4545. +       Debug_dump_frames = 0;
  4546. +       Debug_dump_trigger = 0;
  4547. +       gr_dump_frame_stop();
  4548. +       dc_printf( "Frame dumping is now OFF\n" );
  4549.     }
  4550.  }
  4551.  
  4552.  DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
  4553.  {
  4554. -   if ( Dc_command )   {
  4555. -
  4556. -       if ( Debug_dump_frames == 0 )   {
  4557. -           // Turn it on
  4558. -           Debug_dump_frames = 30;
  4559. -           Debug_dump_trigger = 0;
  4560. -           gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
  4561. -           dc_printf( "Frame dumping at 30 hz is now ON\n" );
  4562. -       } else {
  4563. -           // Turn it off
  4564. -           Debug_dump_frames = 0;
  4565. -           Debug_dump_trigger = 0;
  4566. -           gr_dump_frame_stop();
  4567. -           dc_printf( "Frame dumping is now OFF\n" );
  4568. -       }
  4569. -      
  4570. +   if ( Debug_dump_frames == 0 )   {
  4571. +       // Turn it on
  4572. +       Debug_dump_frames = 30;
  4573. +       Debug_dump_trigger = 0;
  4574. +       gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
  4575. +       dc_printf( "Frame dumping at 30 hz is now ON\n" );
  4576. +   } else {
  4577. +       // Turn it off
  4578. +       Debug_dump_frames = 0;
  4579. +       Debug_dump_trigger = 0;
  4580. +       gr_dump_frame_stop();
  4581. +       dc_printf( "Frame dumping is now OFF\n" );
  4582.     }
  4583.  }
  4584.  
  4585.  DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
  4586.  {
  4587. -   if ( Dc_command )   {
  4588. -
  4589. -       if ( Debug_dump_frames == 0 )   {
  4590. -           // Turn it on
  4591. -           Debug_dump_frames = 30;
  4592. -           Debug_dump_trigger = 1;
  4593. -           gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
  4594. -           dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
  4595. -       } else {
  4596. -           // Turn it off
  4597. -           Debug_dump_frames = 0;
  4598. -           Debug_dump_trigger = 0;
  4599. -           gr_dump_frame_stop();
  4600. -           dc_printf( "Triggered frame dumping is now OFF\n" );
  4601. -       }
  4602. -      
  4603. +   if ( Debug_dump_frames == 0 )   {
  4604. +       // Turn it on
  4605. +       Debug_dump_frames = 30;
  4606. +       Debug_dump_trigger = 1;
  4607. +       gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
  4608. +       dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
  4609. +   } else {
  4610. +       // Turn it off
  4611. +       Debug_dump_frames = 0;
  4612. +       Debug_dump_trigger = 0;
  4613. +       gr_dump_frame_stop();
  4614. +       dc_printf( "Triggered frame dumping is now OFF\n" );
  4615.     }
  4616.  }
  4617.  
  4618. @@ -6923,7 +6998,7 @@ void game_spew_pof_info()
  4619.     BAIL();
  4620.  }
  4621.  
  4622. -DCF(pofspew, "")
  4623. +DCF(pofspew, "Spews POF info without shutting down the game")
  4624.  {
  4625.     game_spew_pof_info();
  4626.  }
  4627. diff --git a/code/gamehelp/contexthelp.cpp b/code/gamehelp/contexthelp.cpp
  4628. index b16f2c2..9d25058 100644
  4629. --- a/code/gamehelp/contexthelp.cpp
  4630. +++ b/code/gamehelp/contexthelp.cpp
  4631. @@ -19,6 +19,7 @@
  4632.  #include "localization/localize.h"
  4633.  #include "globalincs/alphacolors.h"
  4634.  #include "globalincs/systemvars.h"
  4635. +#include "debugconsole/console.h"
  4636.  
  4637.  
  4638.  
  4639. @@ -556,20 +557,14 @@ void help_overlay_blit(int overlay_id)
  4640.  // --------------------------------------------------
  4641.  // DEBUGGING STUFF
  4642.  // --------------------------------------------------
  4643. -
  4644. +// z64: These DCF's really need a do-over.
  4645.  DCF(help_reload, "Reloads help overlay data from help.tbl")
  4646.  {
  4647. -   if (Dc_command) {
  4648. -       parse_helptbl();
  4649. -   }
  4650. -
  4651. -   if (Dc_help)    {
  4652. +   if (dc_optional_string_either("help", "--help")) {
  4653.         dc_printf( "Usage: sample\nCrashes your machine.\n" );
  4654.     }
  4655.  
  4656. -   if (Dc_status)  {
  4657. -       dc_printf( "Yes, my master." );
  4658. -   }
  4659. +   parse_helptbl();
  4660.  }
  4661.  
  4662.  int h_textnum=0, h_amt=0, h_vtx = 0;
  4663. @@ -630,150 +625,115 @@ void showplinepos(int plinenum)
  4664.  
  4665.  DCF(help_nudgetext_x, "Use to visually position overlay text.")
  4666.  {
  4667. -   if (Dc_command) {
  4668. -       dc_get_arg(ARG_INT);
  4669. -       if(Dc_arg_type & ARG_INT){
  4670. -            h_textnum = Dc_arg_int;       
  4671. -       }
  4672. -       dc_get_arg(ARG_INT);
  4673. -       if(Dc_arg_type & ARG_INT){
  4674. -            h_amt = Dc_arg_int;       
  4675. -       }
  4676. -       nudgetext_x(h_textnum, h_amt);
  4677. -   }
  4678.  
  4679. -   if (Dc_help)    {
  4680. +   if (dc_optional_string_either("help", "--help")) {
  4681.         dc_printf( "Usage: sample\nCrashes your machine.\n" );
  4682. +       return;
  4683.     }
  4684.  
  4685. -   if (Dc_status)  {
  4686. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4687.         showtextpos(h_textnum);
  4688. +       return;
  4689.     }
  4690. +
  4691. +   dc_stuff_int(&h_textnum);
  4692. +   dc_stuff_int(&h_amt);
  4693. +
  4694. +   nudgetext_x(h_textnum, h_amt);
  4695.  }
  4696.  
  4697.  DCF(help_nudgetext_y, "Use to visually position overlay text.")
  4698.  {
  4699. -   if (Dc_command) {
  4700. -       dc_get_arg(ARG_INT);
  4701. -       if(Dc_arg_type & ARG_INT){
  4702. -            h_textnum = Dc_arg_int;       
  4703. -       }
  4704. -       dc_get_arg(ARG_INT);
  4705. -       if(Dc_arg_type & ARG_INT){
  4706. -            h_amt = Dc_arg_int;       
  4707. -       }
  4708. -       nudgetext_y(h_textnum, h_amt);
  4709. -   }
  4710. -
  4711. -   if (Dc_help)    {
  4712. +   if (dc_optional_string_either("help", "--help")) {
  4713.         dc_printf( "Usage: sample\nCrashes your machine.\n" );
  4714. +       return;
  4715.     }
  4716.  
  4717. -   if (Dc_status)  {
  4718. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4719.         showtextpos(h_textnum);
  4720. +       return;
  4721.     }
  4722. +
  4723. +   dc_stuff_int(&h_textnum);
  4724. +   dc_stuff_int(&h_amt);
  4725. +  
  4726. +   nudgetext_y(h_textnum, h_amt);
  4727.  }
  4728.  
  4729.  DCF(help_nudgepline_x, "Use to visually position overlay polylines.")
  4730.  {
  4731. -   if (Dc_command) {
  4732. -       dc_get_arg(ARG_INT);
  4733. -       if(Dc_arg_type & ARG_INT){
  4734. -            h_textnum = Dc_arg_int;       
  4735. -       }
  4736. -       dc_get_arg(ARG_INT);
  4737. -       if(Dc_arg_type & ARG_INT){
  4738. -            h_vtx = Dc_arg_int;       
  4739. -       }
  4740. -       dc_get_arg(ARG_INT);
  4741. -       if(Dc_arg_type & ARG_INT){
  4742. -            h_amt = Dc_arg_int;       
  4743. -       }
  4744. -       nudgepline_x(h_textnum, h_vtx, h_amt);
  4745. -   }
  4746. -
  4747. -   if (Dc_help)    {
  4748. +       if (dc_optional_string_either("help", "--help")) {
  4749.         dc_printf( "Usage: help_nudgepline [pline_number] [vertex_number] [distance]\n" );
  4750. +       return;
  4751.     }
  4752.  
  4753. -   if (Dc_status)  {
  4754. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?"))   {
  4755.         showplinepos(h_textnum);
  4756. +       return;
  4757.     }
  4758. +
  4759. +   dc_stuff_int(&h_textnum);
  4760. +   dc_stuff_int(&h_vtx);
  4761. +   dc_stuff_int(&h_amt);
  4762. +
  4763. +   nudgepline_x(h_textnum, h_vtx, h_amt);
  4764.  }
  4765.  
  4766.  
  4767.  DCF(help_nudgepline_y, "Use to visually position overlay polylines.")
  4768.  {
  4769. -   if (Dc_command) {
  4770. -       dc_get_arg(ARG_INT);
  4771. -       if(Dc_arg_type & ARG_INT){
  4772. -            h_textnum = Dc_arg_int;       
  4773. -       }
  4774. -       dc_get_arg(ARG_INT);
  4775. -       if(Dc_arg_type & ARG_INT){
  4776. -            h_vtx = Dc_arg_int;       
  4777. -       }
  4778. -       dc_get_arg(ARG_INT);
  4779. -       if(Dc_arg_type & ARG_INT){
  4780. -            h_amt = Dc_arg_int;       
  4781. -       }
  4782. -       nudgepline_y(h_textnum, h_vtx, h_amt);
  4783. -   }
  4784. -
  4785. -   if (Dc_help)    {
  4786. +   if (dc_optional_string_either("help", "--help")) {
  4787.         dc_printf( "Usage: help_nudgepline [pline_number] [vertex_number] [distance]\n" );
  4788. +       return;
  4789.     }
  4790.  
  4791. -   if (Dc_status)  {
  4792. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?"))   {
  4793.         showplinepos(h_textnum);
  4794. +       return;
  4795.     }
  4796. +
  4797. +   dc_stuff_int(&h_textnum);
  4798. +   dc_stuff_int(&h_vtx);
  4799. +   dc_stuff_int(&h_amt);
  4800. +
  4801. +   nudgepline_y(h_textnum, h_vtx, h_amt);
  4802.  }
  4803.  
  4804.  
  4805.  DCF(help_nudgerbracket_x, "Use to visually position overlay right bracket.")
  4806.  {
  4807. -   if (Dc_command) {
  4808. -       dc_get_arg(ARG_INT);
  4809. -       if(Dc_arg_type & ARG_INT){
  4810. -            h_textnum = Dc_arg_int;       
  4811. -       }
  4812. -       dc_get_arg(ARG_INT);
  4813. -       if(Dc_arg_type & ARG_INT){
  4814. -            h_amt = Dc_arg_int;       
  4815. -       }
  4816. -       nudgerbracket_x(h_textnum, h_amt);
  4817. -   }
  4818. -
  4819. -   if (Dc_help)    {
  4820. +   if (dc_optional_string_either("help", "--help")) {
  4821.         dc_printf( "Usage: help_nudgerbracket_x [num] [amount]\n" );
  4822. +       return;
  4823.     }
  4824.  
  4825. -   if (Dc_status)  {
  4826. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?"))   {
  4827.         showrbracketpos(h_textnum);
  4828. +       return;
  4829.     }
  4830. +
  4831. +   dc_stuff_int(&h_textnum);
  4832. +   dc_stuff_int(&h_amt);
  4833. +
  4834. +   nudgerbracket_x(h_textnum, h_amt);
  4835.  }
  4836.  
  4837.  DCF(help_nudgerbracket_y, "Use to visually position overlay right bracket.")
  4838.  {
  4839. -   if (Dc_command) {
  4840. -       dc_get_arg(ARG_INT);
  4841. -       if(Dc_arg_type & ARG_INT){
  4842. -            h_textnum = Dc_arg_int;       
  4843. -       }
  4844. -       dc_get_arg(ARG_INT);
  4845. -       if(Dc_arg_type & ARG_INT){
  4846. -            h_amt = Dc_arg_int;       
  4847. -       }
  4848. -       nudgerbracket_y(h_textnum, h_amt);
  4849. -   }
  4850. -
  4851. -   if (Dc_help)    {
  4852. +   if (dc_optional_string_either("help", "--help")) {
  4853.         dc_printf( "Usage: help_nudgerbracket_y [num] [amount]\n" );
  4854. +       return;
  4855.     }
  4856.  
  4857. -   if (Dc_status)  {
  4858. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?"))   {
  4859.         showrbracketpos(h_textnum);
  4860. +       return;
  4861.     }
  4862. +
  4863. +   dc_stuff_int(&h_textnum);
  4864. +   dc_stuff_int(&h_amt);
  4865. +  
  4866. +   nudgerbracket_y(h_textnum, h_amt);
  4867.  }
  4868.  
  4869.  
  4870. @@ -781,46 +741,37 @@ DCF(help_nudgerbracket_y, "Use to visually position overlay right bracket.")
  4871.  
  4872.  DCF(help_nudgelbracket_x, "Use to visually position overlay left bracket.")
  4873.  {
  4874. -   if (Dc_command) {
  4875. -       dc_get_arg(ARG_INT);
  4876. -       if(Dc_arg_type & ARG_INT){
  4877. -            h_textnum = Dc_arg_int;       
  4878. -       }
  4879. -       dc_get_arg(ARG_INT);
  4880. -       if(Dc_arg_type & ARG_INT){
  4881. -            h_amt = Dc_arg_int;       
  4882. -       }
  4883. -       nudgelbracket_x(h_textnum, h_amt);
  4884. -   }
  4885.  
  4886. -   if (Dc_help)    {
  4887. +   if (dc_optional_string_either("help", "--help")) {
  4888.         dc_printf( "Usage: help_nudgelbracket_x [num] [amount]\n" );
  4889. +       return;
  4890.     }
  4891.  
  4892. -   if (Dc_status)  {
  4893. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  4894.         showlbracketpos(h_textnum);
  4895. +       return;
  4896.     }
  4897. +
  4898. +   dc_stuff_int(&h_textnum);
  4899. +   dc_stuff_int(&h_amt);
  4900. +
  4901. +   nudgelbracket_x(h_textnum, h_amt);
  4902.  }
  4903.  
  4904.  DCF(help_nudgelbracket_y, "Use to visually position overlay left bracket.")
  4905.  {
  4906. -   if (Dc_command) {
  4907. -       dc_get_arg(ARG_INT);
  4908. -       if(Dc_arg_type & ARG_INT){
  4909. -            h_textnum = Dc_arg_int;       
  4910. -       }
  4911. -       dc_get_arg(ARG_INT);
  4912. -       if(Dc_arg_type & ARG_INT){
  4913. -            h_amt = Dc_arg_int;       
  4914. -       }
  4915. -       nudgelbracket_y(h_textnum, h_amt);
  4916. -   }
  4917. -
  4918. -   if (Dc_help)    {
  4919. +   if (dc_optional_string_either("help", "--help")) {
  4920.         dc_printf( "Usage: help_nudgelbracket_y [num] [amount]\n" );
  4921. +       return;
  4922.     }
  4923.  
  4924. -   if (Dc_status)  {
  4925. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?"))   {
  4926.         showlbracketpos(h_textnum);
  4927. +       return;
  4928.     }
  4929. +
  4930. +   dc_stuff_int(&h_textnum);
  4931. +   dc_stuff_int(&h_amt);
  4932. +
  4933. +   nudgelbracket_y(h_textnum, h_amt);
  4934.  }
  4935. diff --git a/code/globalincs/pstypes.h b/code/globalincs/pstypes.h
  4936. index 998e9f8..8e79d55 100644
  4937. --- a/code/globalincs/pstypes.h
  4938. +++ b/code/globalincs/pstypes.h
  4939. @@ -319,113 +319,6 @@ extern int Fred_running;  // Is Fred running, or FreeSpace?
  4940.  
  4941.  
  4942.  //======================================================================================
  4943. -//======          D E B U G    C O N S O L E   S T U F F        ========================
  4944. -//======================================================================================
  4945. -
  4946. -// Here is a a sample command to toggle something that would
  4947. -// be called by doing "toggle it" from the debug console command window/
  4948. -
  4949. -/*
  4950. -DCF(toggle_it,"description")
  4951. -{
  4952. -   if (Dc_command) {
  4953. -       This_var = !This_var;
  4954. -   }
  4955. -
  4956. -   if (Dc_help) {
  4957. -       dc_printf( "Usage: sample\nToggles This_var on/off.\n" );
  4958. -   }
  4959. -
  4960. -   if (Dc_status) {
  4961. -       dc_printf( "The status is %d.\n", This_var );
  4962. -   }
  4963. -*/
  4964. -
  4965. -class debug_command {
  4966. -   public:
  4967. -   char *name;
  4968. -   char *help;
  4969. -   void (*func)();
  4970. -   debug_command(char *name,char *help,void (*func)());    // constructor
  4971. -};
  4972. -
  4973. -#define DCF(function_name,help_text)   \
  4974. -       void dcf_##function_name(); \
  4975. -       debug_command dc_##function_name(#function_name,help_text,dcf_##function_name); \
  4976. -       void dcf_##function_name()
  4977. -
  4978. -// Starts the debug console
  4979. -extern void debug_console( void (*func)() = NULL );
  4980. -
  4981. -// The next three variables tell your function what to do.  It should
  4982. -// only change something if the dc_command is set.   A minimal function
  4983. -// needs to process the dc_command.   Usually, these will be called in
  4984. -// these combinations:
  4985. -// dc_command=true, dc_status=true  means process it and show status
  4986. -// dc_help=true means show help only
  4987. -// dc_status=true means show status only
  4988. -// I would recommend doing this in each function:
  4989. -// if (dc_command) { process command }
  4990. -// if (dc_help) { print out help }
  4991. -// if (dc_status) { print out status }
  4992. -// with the last two being optional
  4993. -
  4994. -extern int Dc_command;         // If this is set, then process the command
  4995. -extern int Dc_help;                // If this is set, then print out the help text in the form, "usage: ... \nLong description\n" );
  4996. -extern int Dc_status;          // If this is set, then print out the current status of the command.
  4997. -
  4998. -void dc_get_arg(uint flags);   // Gets the next argument.   If it doesn't match the flags, this function will print an error and not return.
  4999. -extern char *Dc_arg;           // The (lowercased) string value of the argument retrieved from dc_arg
  5000. -extern char *Dc_arg_org;       // Dc_arg before it got converted to lowercase
  5001. -extern uint Dc_arg_type;       // The type of dc_arg.
  5002. -extern char *Dc_command_line;  // The rest of the command line, from the end of the last processed arg on.
  5003. -extern int Dc_arg_int;         // If Dc_arg_type & ARG_INT or ARG_HEX is set, then this is the value
  5004. -extern ubyte Dc_arg_ubyte;     // If Dc_arg_type & ARG_UBYTE is set, then this is the value
  5005. -extern float Dc_arg_float;     // If Dc_arg_type & ARG_FLOAT is set, then this is the value
  5006. -
  5007. -// Outputs text to the console
  5008. -void dc_printf( char *format, ... );
  5009. -
  5010. -// Each dc_arg_type can have one or more of these flags set.
  5011. -// This is because some things can fit into two categories.
  5012. -// Like 1 can be an integer, a float, a string, or a true boolean
  5013. -// value.
  5014. -#define ARG_NONE       (1<<0)      // no argument
  5015. -#define ARG_ANY            0xFFFFFFFF  // Anything.
  5016. -#define ARG_STRING     (1<<1)      // any valid string
  5017. -#define ARG_QUOTE      (1<<2)      // a quoted string
  5018. -#define ARG_INT            (1<<3)      // a valid integer
  5019. -#define ARG_FLOAT      (1<<4)      // a valid floating point number
  5020. -
  5021. -// some specific commonly used predefined types. Can add up to (1<<31)
  5022. -#define ARG_HEX            (1<<5)      // a valid hexadecimal integer. Note that ARG_INT will always be set also in this case.
  5023. -#define ARG_TRUE       (1<<6)      // on, true, non-zero number
  5024. -#define ARG_FALSE      (1<<7)      // off, false, zero
  5025. -#define ARG_PLUS       (1<<8)      // Plus sign
  5026. -#define ARG_MINUS      (1<<9)      // Minus sign
  5027. -#define ARG_COMMA      (1<<10)     // a comma
  5028. -#define ARG_UBYTE      (1<<11)     // a valid ubyte
  5029. -
  5030. -// A shortcut for boolean only variables.
  5031. -// Example:  
  5032. -// DCF_BOOL( lighting, Show_lighting )
  5033. -//
  5034. -#define DCF_BOOL( function_name, bool_variable )   \
  5035. -   void dcf_##function_name(); \
  5036. -   debug_command dc_##function_name(#function_name,"Toggles "#bool_variable,dcf_##function_name ); \
  5037. -   void dcf_##function_name()  {   \
  5038. -   if ( Dc_command )   {   \
  5039. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);        \
  5040. -       if ( Dc_arg_type & ARG_TRUE )   bool_variable = 1;  \
  5041. -       else if ( Dc_arg_type & ARG_FALSE ) bool_variable = 0;  \
  5042. -       else if ( Dc_arg_type & ARG_NONE ) bool_variable ^= 1;  \
  5043. -   }   \
  5044. -   if ( Dc_help )  dc_printf( "Usage: %s [bool]\nSets %s to true or false.  If nothing passed, then toggles it.\n", #function_name, #bool_variable );  \
  5045. -   if ( Dc_status )    dc_printf( "%s is %s\n", #function_name, (bool_variable?"TRUE":"FALSE") );  \
  5046. -}
  5047. -
  5048. -
  5049. -//======================================================================================
  5050.  //======================================================================================
  5051.  //======================================================================================
  5052.  
  5053. diff --git a/code/globalincs/systemvars.cpp b/code/globalincs/systemvars.cpp
  5054. index f7ac86c..72f6c21 100644
  5055. --- a/code/globalincs/systemvars.cpp
  5056. +++ b/code/globalincs/systemvars.cpp
  5057. @@ -8,7 +8,7 @@
  5058.  */
  5059.  
  5060.  
  5061. -
  5062. +#include "debugconsole/console.h"
  5063.  #include "globalincs/pstypes.h"
  5064.  #include "globalincs/systemvars.h"
  5065.  #include "io/timer.h"
  5066. @@ -248,73 +248,76 @@ int Monitor_inited = 0;
  5067.  char Monitor_filename[128];
  5068.  fix monitor_last_time = -1;
  5069.  
  5070. -DCF(monitor,"Monitors game performace")
  5071. +DCF(monitor,"Monitors game performace by saving to file")
  5072.  {
  5073. -   if ( Dc_command )   {
  5074. -       dc_get_arg(ARG_STRING|ARG_NONE);
  5075. -       if ( Dc_arg_type == ARG_NONE )  {
  5076. -           if ( Monitor_inited )   {
  5077. -               Monitor_inited = 0;
  5078. +   SCP_string filename;
  5079.  
  5080. -/*
  5081. -               FILE *fp = fopen( Monitor_filename, "at" );
  5082. -               if ( fp )   {
  5083. -                   fprintf( fp, "\n\n" );
  5084. -                   fprintf( fp, "Name\tMin\tMax\tAvg\n" );
  5085. -                   for (int i=0; i<Num_monitors; i++ ) {
  5086. -                       if ( Monitor[i]->cnt > 0 )  {
  5087. -                           fprintf( fp, "%s\t%d\t%d\t%d\n", Monitor[i]->name, Monitor[i]->min, Monitor[i]->max, Monitor[i]->sum / Monitor[i]->cnt  );
  5088. -                       } else {
  5089. -                           fprintf( fp, "%s\t%d\t%d\t?\n", Monitor[i]->name, Monitor[i]->min, Monitor[i]->max );
  5090. -                       }
  5091. -                   }
  5092. -                   fclose(fp);
  5093. -               }
  5094. -*/
  5095. +   if (dc_optional_string_either("help", "--help")) {
  5096. +       dc_printf("Usage: monitor [filename]\n");
  5097. +       dc_printf("Outputs monitoring info to [filename]. No filename turns it off\n" );
  5098. +       return;
  5099. +   }
  5100.  
  5101. -               dc_printf( "Monitor to file '%s' turned off\n", Monitor_filename );
  5102. -           } else {
  5103. -               dc_printf( "Monitor isn't on\n" );
  5104. -           }
  5105. -       } else {
  5106. -           if ( Monitor_inited )   {
  5107. +   if (dc_maybe_stuff_string_white(filename)) {
  5108. +       if ( Monitor_inited )   {
  5109.                 dc_printf( "Monitor already on\n" );
  5110. -           } else {
  5111. -               Monitor_inited = 1;
  5112. +       } else {
  5113. +           Monitor_inited = 1;
  5114.  
  5115. -               strcpy_s( Monitor_filename, Dc_arg );
  5116. +           strcpy(Monitor_filename, filename.c_str());
  5117. +
  5118. +           // Reset them all
  5119. +           int i;
  5120. +           for (i=0; i<Num_monitors; i++ ) {
  5121. +               Monitor[i]->value = 0;
  5122. +               Monitor[i]->sum = 0;
  5123. +               Monitor[i]->cnt = 0;
  5124. +               Monitor[i]->min = 0;
  5125. +               Monitor[i]->max = 0;
  5126. +           }
  5127.  
  5128. -               // Reset them all
  5129. -               int i;
  5130. +           FILE *fp = fopen( Monitor_filename, "wt" );
  5131. +           if ( fp )   {
  5132.                 for (i=0; i<Num_monitors; i++ ) {
  5133. -                   Monitor[i]->value = 0;
  5134. -                   Monitor[i]->sum = 0;
  5135. -                   Monitor[i]->cnt = 0;
  5136. -                   Monitor[i]->min = 0;
  5137. -                   Monitor[i]->max = 0;
  5138. +                   if ( i > 0 )    {
  5139. +                       fprintf( fp, "\t" );
  5140. +                   }
  5141. +                   fprintf( fp, "%s", Monitor[i]->name );
  5142. +
  5143.                 }
  5144. +               fprintf( fp, "\n" );
  5145. +               fclose(fp);
  5146. +           }
  5147. +           dc_printf( "Monitor outputting to file '%s'\n", Monitor_filename );
  5148. +           monitor_last_time = -1;
  5149. +       }
  5150. +
  5151. +   } else {
  5152. +       // Turn off monitoring
  5153. +       if ( Monitor_inited )   {
  5154. +           Monitor_inited = 0;
  5155.  
  5156. -               FILE *fp = fopen( Monitor_filename, "wt" );
  5157. -               if ( fp )   {
  5158. -                   for (i=0; i<Num_monitors; i++ ) {
  5159. -                       if ( i > 0 )    {
  5160. -                           fprintf( fp, "\t" );
  5161. -                       }
  5162. -                       fprintf( fp, "%s", Monitor[i]->name );
  5163. -                  
  5164. +/*
  5165. +           FILE *fp = fopen( Monitor_filename, "at" );
  5166. +           if ( fp )   {
  5167. +               fprintf( fp, "\n\n" );
  5168. +               fprintf( fp, "Name\tMin\tMax\tAvg\n" );
  5169. +               for (int i=0; i<Num_monitors; i++ ) {
  5170. +                   if ( Monitor[i]->cnt > 0 )  {
  5171. +                       fprintf( fp, "%s\t%d\t%d\t%d\n", Monitor[i]->name, Monitor[i]->min, Monitor[i]->max, Monitor[i]->sum / Monitor[i]->cnt  );
  5172. +                   } else {
  5173. +                       fprintf( fp, "%s\t%d\t%d\t?\n", Monitor[i]->name, Monitor[i]->min, Monitor[i]->max );
  5174.                     }
  5175. -                   fprintf( fp, "\n" );
  5176. -                   fclose(fp);
  5177.                 }
  5178. -               dc_printf( "Monitor outputting to file '%s'\n", Monitor_filename );
  5179. -               monitor_last_time = -1;
  5180. +               fclose(fp);
  5181.             }
  5182. +*/
  5183. +
  5184. +           dc_printf( "Monitor to file '%s' turned off\n", Monitor_filename );
  5185. +       } else {
  5186. +           dc_printf( "Monitor isn't on\n" );
  5187.         }
  5188.     }
  5189. -   if ( Dc_help )  {
  5190. -       dc_printf( "Usage: monitor filename\nOutputs monitoring info to filename. No filename turns it off\n" );
  5191. -   }
  5192. -  
  5193.  }
  5194.  
  5195.  
  5196. @@ -508,44 +511,41 @@ int current_detail_level()
  5197.  #ifndef NDEBUG
  5198.  DCF(detail_level,"Change the detail level")
  5199.  {
  5200. -   if ( Dc_command )   {
  5201. -       dc_get_arg(ARG_INT|ARG_NONE);
  5202. -       if ( Dc_arg_type & ARG_NONE )   {
  5203. -           Game_detail_level = 0;
  5204. -           dc_printf( "Detail level reset\n" );
  5205. -       }
  5206. -       if ( Dc_arg_type & ARG_INT )    {
  5207. -           Game_detail_level = Dc_arg_int;
  5208. -       }
  5209. +   int value;
  5210. +
  5211. +   if (dc_optional_string_either("help", "--help")) {
  5212. +       dc_printf( "Usage: detail_level [n]\n");
  5213. +       dc_printf("[n]  -- is detail level.\n");
  5214. +           dc_printf("\t0 is 'normal' detail,\n");
  5215. +           dc_printf("\tnegative values are lower, and\n");
  5216. +           dc_printf("\tpositive values are higher.\n\n");
  5217. +      
  5218. +       dc_printf("No parameter resets it to default.\n");
  5219. +       return;
  5220.     }
  5221.  
  5222. -   if ( Dc_help ) 
  5223. -       dc_printf( "Usage: detail_level [n]\nn is detail level. 0 normal, - lower, + higher, -2 to 2 usually\nNo parameter resets it to default.\n" );
  5224. -
  5225. -   if ( Dc_status )               
  5226. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  5227.         dc_printf("Detail level set to %d\n", Game_detail_level);
  5228. +       return;
  5229. +   }
  5230. +
  5231. +   if (dc_maybe_stuff_int(&value)) {
  5232. +       Game_detail_level = value;
  5233. +       dc_printf("Detail level set to %i\n", Game_detail_level);
  5234. +
  5235. +   } else {
  5236. +       Game_detail_level = 0;
  5237. +       dc_printf("Detail level reset\n");
  5238. +   }
  5239.  }
  5240.  
  5241.  DCF(detail, "Turns on/off parts of the game for speed testing" )
  5242.  {
  5243. -   if ( Dc_command )   {
  5244. -       dc_get_arg(ARG_INT|ARG_NONE);
  5245. -       if ( Dc_arg_type & ARG_NONE )   {
  5246. -           if ( Game_detail_flags == DETAIL_DEFAULT )  {
  5247. -               Game_detail_flags = DETAIL_FLAG_CLEAR;
  5248. -               dc_printf( "Detail flags set lowest (except has screen clear)\n" );
  5249. -           } else {
  5250. -               Game_detail_flags = DETAIL_DEFAULT;
  5251. -               dc_printf( "Detail flags set highest\n" );
  5252. -           }
  5253. -       }
  5254. -       if ( Dc_arg_type & ARG_INT )    {
  5255. -           Game_detail_flags ^= Dc_arg_int;
  5256. -       }
  5257. -   }
  5258. +   int value;
  5259.  
  5260. -   if ( Dc_help )  {
  5261. -       dc_printf( "Usage: detail [n]\nn is detail bit to toggle.\n" );
  5262. +   if (dc_optional_string_either("help", "--help")) {
  5263. +       dc_printf( "Usage: detail [n]\n");
  5264. +       dc_printf("[n] is detail bit to toggle:\n" );
  5265.         dc_printf( "   1: draw the stars\n" );
  5266.         dc_printf( "   2: draw the nebulas\n" );
  5267.         dc_printf( "   4: draw the motion debris\n" );
  5268. @@ -555,21 +555,38 @@ DCF(detail, "Turns on/off parts of the game for speed testing" )
  5269.         dc_printf( "  64: clear screen background after each frame\n" );
  5270.         dc_printf( " 128: draw hud stuff\n" );
  5271.         dc_printf( " 256: draw fireballs\n" );
  5272. -       dc_printf( " 512: do collision detection\n" );
  5273. +       dc_printf( " 512: do collision detection\n\n" );
  5274. +
  5275. +       dc_printf("No argument will toggle between highest/lowest detail settings\n");
  5276. +       return;
  5277.     }
  5278.  
  5279. -   if ( Dc_status )    {
  5280. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  5281.         dc_printf("Detail flags set to 0x%08x\n", Game_detail_flags);
  5282. -       dc_printf( "   1: draw the stars: %s\n", (Game_detail_flags&1?"on":"off") );
  5283. -       dc_printf( "   2: draw the nebulas: %s\n", (Game_detail_flags&2?"on":"off") );
  5284. -       dc_printf( "   4: draw the motion debris: %s\n", (Game_detail_flags&4?"on":"off")  );
  5285. -       dc_printf( "   8: draw planets: %s\n", (Game_detail_flags&8?"on":"off")  );
  5286. -       dc_printf( "  16: draw models not as blobs: %s\n", (Game_detail_flags&16?"on":"off")  );
  5287. -       dc_printf( "  32: draw lasers not as pixels: %s\n", (Game_detail_flags&32?"on":"off")  );
  5288. -       dc_printf( "  64: clear screen background after each frame: %s\n", (Game_detail_flags&64?"on":"off")  );
  5289. -       dc_printf( " 128: draw hud stuff: %s\n", (Game_detail_flags&128?"on":"off")  );
  5290. -       dc_printf( " 256: draw fireballs: %s\n", (Game_detail_flags&256?"on":"off")  );
  5291. -       dc_printf( " 512: do collision detection: %s\n", (Game_detail_flags&512?"on":"off")  );
  5292. +       dc_printf( "   1: draw the stars: %s\n", ((Game_detail_flags & 1) ? "on" : "off"));
  5293. +       dc_printf( "   2: draw the nebulas: %s\n", ((Game_detail_flags & 2)?"on" : "off"));
  5294. +       dc_printf( "   4: draw the motion debris: %s\n", ((Game_detail_flags & 4) ? "on" : "off"));
  5295. +       dc_printf( "   8: draw planets: %s\n", ((Game_detail_flags & 8) ? "on" : "off"));
  5296. +       dc_printf( "  16: draw models not as blobs: %s\n", ((Game_detail_flags & 16) ? "on" : "off"));
  5297. +       dc_printf( "  32: draw lasers not as pixels: %s\n", ((Game_detail_flags & 32) ? "on" : "off"));
  5298. +       dc_printf( "  64: clear screen background after each frame: %s\n", ((Game_detail_flags & 64) ? "on" : "off"));
  5299. +       dc_printf( " 128: draw hud stuff: %s\n", ((Game_detail_flags & 128) ? "on" : "off"));
  5300. +       dc_printf( " 256: draw fireballs: %s\n", ((Game_detail_flags & 256) ? "on" : "off"));
  5301. +       dc_printf( " 512: do collision detection: %s\n", ((Game_detail_flags & 512) ? "on" : "off"));
  5302. +       return;
  5303. +   }
  5304. +
  5305. +   if (dc_maybe_stuff_int(&value)) {
  5306. +       Game_detail_flags ^= value;
  5307. +  
  5308. +   } else {
  5309. +       if (Game_detail_flags == DETAIL_DEFAULT) {
  5310. +           Game_detail_flags = DETAIL_FLAG_CLEAR;
  5311. +           dc_printf( "Detail flags set lowest (except has screen clear)\n" );
  5312. +       } else {
  5313. +           Game_detail_flags = DETAIL_DEFAULT;
  5314. +           dc_printf( "Detail flags set highest\n" );
  5315. +       }
  5316.     }
  5317.  }
  5318.  #endif
  5319. diff --git a/code/globalincs/vmallocator.h b/code/globalincs/vmallocator.h
  5320. index 7cf2e37..1af80bc 100644
  5321. --- a/code/globalincs/vmallocator.h
  5322. +++ b/code/globalincs/vmallocator.h
  5323. @@ -8,6 +8,7 @@
  5324.  #include <map>
  5325.  #include <string>
  5326.  #include <queue>
  5327. +#include <deque>
  5328.  
  5329.  #if defined __GNUC__
  5330.  #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
  5331. @@ -127,6 +128,9 @@ class SCP_multimap : public std::multimap<T, U, std::less<T>, SCP_vm_allocator<s
  5332.  template< typename T >
  5333.  class SCP_queue : public std::queue< T, std::deque< T, SCP_vm_allocator< T > > > { };
  5334.  
  5335. +template< typename T >
  5336. +class SCP_deque : public std::deque< T, SCP_vm_allocator< T > > { };
  5337. +
  5338.  template <class T1, class T2>
  5339.  bool operator==(const SCP_vm_allocator<T1>&, const SCP_vm_allocator<T2>&) throw()
  5340.  {
  5341. diff --git a/code/globalincs/windebug.cpp b/code/globalincs/windebug.cpp
  5342. index c73057e..aaa5f83 100644
  5343. --- a/code/globalincs/windebug.cpp
  5344. +++ b/code/globalincs/windebug.cpp
  5345. @@ -33,6 +33,7 @@
  5346.  #include "cmdline/cmdline.h"
  5347.  #include "parse/lua.h"
  5348.  #include "parse/parselo.h"
  5349. +#include "debugconsole/console.h"
  5350.  
  5351.  #if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
  5352.  #  include "globalincs/mspdb_callstack.h"
  5353. @@ -1522,7 +1523,7 @@ void windebug_memwatch_init()
  5354.  #endif
  5355.  
  5356.  int Watch_malloc = 0;
  5357. -DCF_BOOL(watch_malloc, Watch_malloc )
  5358. +DCF_BOOL(watch_malloc, Watch_malloc );
  5359.  
  5360.  // Returns 0 if not enough RAM.
  5361.  int vm_init(int min_heap_size)
  5362. diff --git a/code/graphics/2d.cpp b/code/graphics/2d.cpp
  5363. index 454b88f..713a55a 100644
  5364. --- a/code/graphics/2d.cpp
  5365. +++ b/code/graphics/2d.cpp
  5366. @@ -31,6 +31,7 @@
  5367.  #include "parse/scripting.h"
  5368.  #include "gamesequence/gamesequence.h" //WMC - for scripting hooks in gr_flip()
  5369.  #include "io/keycontrol.h" // m!m
  5370. +#include "debugconsole/console.h"
  5371.  
  5372.  
  5373.  #if defined(SCP_UNIX) && !defined(__APPLE__)
  5374. @@ -266,12 +267,9 @@ DCF(clear_color, "set clear color r, g, b")
  5375.  {
  5376.     ubyte r, g, b;
  5377.  
  5378. -   dc_get_arg(ARG_UBYTE);
  5379. -   r = Dc_arg_ubyte;
  5380. -   dc_get_arg(ARG_UBYTE);
  5381. -   g = Dc_arg_ubyte;
  5382. -   dc_get_arg(ARG_UBYTE);
  5383. -   b = Dc_arg_ubyte;
  5384. +   dc_stuff_ubyte(&r);
  5385. +   dc_stuff_ubyte(&g);
  5386. +   dc_stuff_ubyte(&b);
  5387.  
  5388.     // set the color
  5389.     gr_set_clear_color(r, g, b);
  5390. diff --git a/code/graphics/gropengl.cpp b/code/graphics/gropengl.cpp
  5391. index 4e781e7..2e7b716 100644
  5392. --- a/code/graphics/gropengl.cpp
  5393. +++ b/code/graphics/gropengl.cpp
  5394. @@ -22,6 +22,7 @@
  5395.  #include "io/timer.h"
  5396.  #include "ddsutils/ddsutils.h"
  5397.  #include "model/model.h"
  5398. +#include "debugconsole/console.h"
  5399.  #include "debugconsole/timerbar.h"
  5400.  #include "graphics/gropenglbmpman.h"
  5401.  #include "graphics/gropengllight.h"
  5402. @@ -2078,56 +2079,61 @@ bool gr_opengl_init()
  5403.  
  5404.  DCF(ogl_minimize, "Minimizes opengl")
  5405.  {
  5406. +   bool minimize_ogl = false;
  5407. +
  5408.     if ( gr_screen.mode != GR_OPENGL ) {
  5409.         dc_printf("Command only available in OpenGL mode.\n");
  5410.         return;
  5411.     }
  5412.  
  5413. -   if (Dc_command) {
  5414. -       dc_get_arg(ARG_TRUE);
  5415. -
  5416. -       if ( Dc_arg_type & ARG_TRUE ) {
  5417. -           opengl_minimize();
  5418. -       }
  5419. +   if (dc_optional_string_either("help", "--help")) {
  5420. +       dc_printf("[bool] If true is passed, then the OpenGL window will minimize.\n");
  5421. +       return;
  5422.     }
  5423. +   dc_stuff_boolean(&minimize_ogl);
  5424.  
  5425. -   if (Dc_help)
  5426. -       dc_printf("If set to true then the OpenGL window will minimize.\n");
  5427. +   if (minimize_ogl) {
  5428. +       opengl_minimize();
  5429. +   }
  5430.  }
  5431.  
  5432.  DCF(ogl_anisotropy, "toggles anisotropic filtering")
  5433.  {
  5434. +   bool process = true;
  5435. +   int value;
  5436. +
  5437.     if ( gr_screen.mode != GR_OPENGL ) {
  5438.         dc_printf("Can only set anisotropic filter in OpenGL mode.\n");
  5439.         return;
  5440.     }
  5441.  
  5442. -   if ( Dc_command && !Is_Extension_Enabled(OGL_EXT_TEXTURE_FILTER_ANISOTROPIC) ) {
  5443. -       dc_printf("Error: Anisotropic filter is not settable!\n");
  5444. +   if (dc_optional_string_either("help", "--help")) {
  5445. +       dc_printf("Sets OpenGL anisotropic filtering level.\n");
  5446. +       dc_printf("GL_anisotropy [int]  Valid values are 0 to %i. 0 turns off anisotropic filtering.\n", (int)opengl_get_max_anisotropy());
  5447. +       process = false;
  5448. +   }
  5449. +
  5450. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  5451. +       dc_printf("Current anisotropic filter value is %i\n", (int)GL_anisotropy);
  5452. +       process = false;
  5453. +   }
  5454. +
  5455. +   if (!process) {
  5456.         return;
  5457.     }
  5458.  
  5459. -   if ( Dc_command ) {
  5460. -       dc_get_arg(ARG_INT | ARG_NONE);
  5461. +   if ( !Is_Extension_Enabled(OGL_EXT_TEXTURE_FILTER_ANISOTROPIC) ) {
  5462. +       dc_printf("Error: Anisotropic filter is not settable!\n");
  5463. +       return;
  5464. +   }
  5465.  
  5466. -       if ( Dc_arg_type & ARG_NONE ) {
  5467. +   if (!dc_maybe_stuff_int(&value)) {
  5468. +       // No arg passed, set to default
  5469.             GL_anisotropy = 1.0f;
  5470.         //  opengl_set_anisotropy();
  5471.             dc_printf("Anisotropic filter value reset to default level.\n");
  5472. -       }
  5473. -
  5474. -       if ( Dc_arg_type & ARG_INT ) {
  5475. -           GL_anisotropy = (GLfloat)Dc_arg_float;
  5476. +   } else {
  5477. +       GL_anisotropy = (GLfloat)value;
  5478.         //  opengl_set_anisotropy( (float)Dc_arg_float );
  5479. -       }
  5480. -   }
  5481. -
  5482. -   if ( Dc_status ) {
  5483. -       dc_printf("Current anisotropic filter value is %i\n", (int)GL_anisotropy);
  5484. -   }
  5485. -
  5486. -   if (Dc_help) {
  5487. -       dc_printf("Sets OpenGL anisotropic filtering level.\n");
  5488. -       dc_printf("Valid values are 1 to %i, or 0 to turn off.\n", (int)opengl_get_max_anisotropy());
  5489.     }
  5490.  }
  5491. diff --git a/code/hud/hudlock.cpp b/code/hud/hudlock.cpp
  5492. index fb7d58e..f8d3b61 100644
  5493. --- a/code/hud/hudlock.cpp
  5494. +++ b/code/hud/hudlock.cpp
  5495. @@ -26,6 +26,7 @@
  5496.  #include "mission/missionparse.h"
  5497.  #include "iff_defs/iff_defs.h"
  5498.  #include "network/multi.h"
  5499. +#include "debugconsole/console.h"
  5500.  
  5501.  
  5502.  vec3d lock_world_pos;
  5503. @@ -333,7 +334,7 @@ int hud_lock_has_homing_point()
  5504.  }
  5505.  
  5506.  int Nebula_sec_range = 0;
  5507. -DCF_BOOL(nebula_sec_range, Nebula_sec_range)
  5508. +DCF_BOOL(nebula_sec_range, Nebula_sec_range);
  5509.  
  5510.  int hud_lock_world_pos_in_range(vec3d *target_world_pos, vec3d *vec_to_target)
  5511.  {
  5512. diff --git a/code/io/joy.cpp b/code/io/joy.cpp
  5513. index 6494873..6905903 100644
  5514. --- a/code/io/joy.cpp
  5515. +++ b/code/io/joy.cpp
  5516. @@ -21,6 +21,7 @@
  5517.  #include "io/joy_ff.h"
  5518.  #include "directx/vdinput.h"
  5519.  #include "osapi/osapi.h"
  5520. +#include "debugconsole/console.h"
  5521.  
  5522.  
  5523.  
  5524. @@ -300,45 +301,51 @@ void joy_get_caps(int max)
  5525.  int joy_get_scaled_reading(int raw, int axn);
  5526.  int joy_get_unscaled_reading(int raw, int axn);
  5527.  
  5528. -DCF(joytest, "Test joystick")
  5529. +DCF(joytest, "Test joystick (X, Y)")
  5530.  {
  5531. -   if (Dc_command) {
  5532. -       while (!keyd_pressed[KEY_ESC]) {
  5533. -           int x, y, axis[JOY_NUM_AXES];
  5534. +   if (dc_optional_string_either("help", "--help")) {
  5535. +       dc_printf("Outputs the scaled reading of the joystick to a seperate window.\n");
  5536. +       dc_printf("Press ESC to end the test\n");
  5537. +   }
  5538.  
  5539. -           if (joy_num_sticks < 1)
  5540. -               return;
  5541. +   while (!keyd_pressed[KEY_ESC]) {
  5542. +       int x, y, axis[JOY_NUM_AXES];
  5543.  
  5544. -           joystick_read_raw_axis(JOY_NUM_AXES, axis);
  5545. +       if (joy_num_sticks < 1)
  5546. +           return;
  5547.  
  5548. -           x = joy_get_scaled_reading(axis[0], 0);
  5549. -           y = joy_get_scaled_reading(axis[1], 1);
  5550. +       joystick_read_raw_axis(JOY_NUM_AXES, axis);
  5551.  
  5552. -           mprintf(("X=%5d Y=%5d  Calibrated X=%6d Y=%6d\n", axis[0], axis[1], x, y));
  5553. -           Sleep(100);
  5554. -       }
  5555. +       x = joy_get_scaled_reading(axis[0], 0);
  5556. +       y = joy_get_scaled_reading(axis[1], 1);
  5557. +
  5558. +       mprintf(("X=%5d Y=%5d  Calibrated X=%6d Y=%6d\n", axis[0], axis[1], x, y));
  5559. +       Sleep(100);
  5560.     }
  5561.  }
  5562.  
  5563. -DCF(joytest2, "Test joystick (extended)")
  5564. +DCF(joytest2, "Test joystick (X, Y, Z, Rx, Ry, Rz)")
  5565.  {
  5566. -   if (Dc_command) {
  5567. -       while (!keyd_pressed[KEY_ESC]) {
  5568. -           int x, y, z, r, axis[JOY_NUM_AXES];
  5569. +   if (dc_optional_string_either("help", "--help")) {
  5570. +       dc_printf("Outputs the scaled reading of the joystick to a seperate window.\n");
  5571. +       dc_printf("Press ESC to end the test\n");
  5572. +   }
  5573.  
  5574. -           if (joy_num_sticks < 1)
  5575. -               return;
  5576. +   while (!keyd_pressed[KEY_ESC]) {
  5577. +       int x, y, z, r, axis[JOY_NUM_AXES];
  5578.  
  5579. -           joystick_read_raw_axis(JOY_NUM_AXES, axis);
  5580. +       if (joy_num_sticks < 1)
  5581. +           return;
  5582.  
  5583. -           x = joy_get_scaled_reading(axis[0], 0);
  5584. -           y = joy_get_scaled_reading(axis[1], 1);
  5585. -           z = joy_get_unscaled_reading(axis[2], 2);
  5586. -           r = joy_get_scaled_reading(axis[3], 3);
  5587. +       joystick_read_raw_axis(JOY_NUM_AXES, axis);
  5588.  
  5589. -           mprintf(("X=%5d Y=%5d Z=%5d Rx=%5d Ry=%5d Rz=%5d Cal X=%6d Y=%6d Z=%6d R=%6d\n", axis[0], axis[1], axis[2], axis[3], axis[4], axis[5], x, y, z, r));
  5590. -           Sleep(100);
  5591. -       }
  5592. +       x = joy_get_scaled_reading(axis[0], 0);
  5593. +       y = joy_get_scaled_reading(axis[1], 1);
  5594. +       z = joy_get_unscaled_reading(axis[2], 2);
  5595. +       r = joy_get_scaled_reading(axis[3], 3);
  5596. +
  5597. +       mprintf(("X=%5d Y=%5d Z=%5d Rx=%5d Ry=%5d Rz=%5d Cal X=%6d Y=%6d Z=%6d R=%6d\n", axis[0], axis[1], axis[2], axis[3], axis[4], axis[5], x, y, z, r));
  5598. +       Sleep(100);
  5599.     }
  5600.  }
  5601.  
  5602. diff --git a/code/lighting/lighting.cpp b/code/lighting/lighting.cpp
  5603. index 345c706..481e8b8 100644
  5604. --- a/code/lighting/lighting.cpp
  5605. +++ b/code/lighting/lighting.cpp
  5606. @@ -15,6 +15,7 @@
  5607.  #include "globalincs/systemvars.h"
  5608.  #include "graphics/2d.h"
  5609.  #include "cmdline/cmdline.h"
  5610. +#include "debugconsole/console.h"
  5611.  
  5612.  
  5613.  
  5614. @@ -62,52 +63,11 @@ int Lighting_flag = 1;
  5615.  
  5616.  DCF(light,"Changes lighting parameters")
  5617.  {
  5618. -   if ( Dc_command )   {
  5619. -       dc_get_arg(ARG_STRING);
  5620. -       if ( !strcmp( Dc_arg, "ambient" ))  {
  5621. -           dc_get_arg(ARG_FLOAT);
  5622. -           if ( (Dc_arg_float < 0.0f) || (Dc_arg_float > 1.0f) )   {
  5623. -               Dc_help = 1;
  5624. -           } else {
  5625. -               Ambient_light = Dc_arg_float;
  5626. -           }
  5627. -       } else if ( !strcmp( Dc_arg, "reflect" ))   {
  5628. -           dc_get_arg(ARG_FLOAT);
  5629. -           if ( (Dc_arg_float < 0.0f) || (Dc_arg_float > 1.0f) )   {
  5630. -               Dc_help = 1;
  5631. -           } else {
  5632. -               Reflective_light = Dc_arg_float;
  5633. -           }
  5634. -       } else if ( !strcmp( Dc_arg, "default" ))   {
  5635. -           Lighting_mode = LM_BRIGHTEN;
  5636. -           Ambient_light = AMBIENT_LIGHT_DEFAULT;
  5637. -           Reflective_light = REFLECTIVE_LIGHT_DEFAULT;
  5638. -           Lighting_flag = 0;
  5639. -       } else if ( !strcmp( Dc_arg, "mode" ))  {
  5640. -           dc_get_arg(ARG_STRING);
  5641. -           if ( !strcmp(Dc_arg, "light") ) {
  5642. -               Lighting_mode = LM_BRIGHTEN;
  5643. -           } else if ( !strcmp(Dc_arg, "darken"))  {
  5644. -               Lighting_mode = LM_DARKEN;
  5645. -           } else {
  5646. -               Dc_help = 1;
  5647. -           }
  5648. -       } else if ( !strcmp( Dc_arg, "dynamic" ))   {
  5649. -           dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  5650. -           if ( Dc_arg_type & ARG_TRUE )   Lighting_flag = 1
  5651. -           else if ( Dc_arg_type & ARG_FALSE ) Lighting_flag = 0
  5652. -           else if ( Dc_arg_type & ARG_NONE ) Lighting_flag ^= 1
  5653. -       } else if ( !strcmp( Dc_arg, "on" ) )   {
  5654. -           Lighting_off = 0;
  5655. -       } else if ( !strcmp( Dc_arg, "off" ) )  {
  5656. -           Lighting_off = 1;
  5657. -       } else {
  5658. -           // print usage, not stats
  5659. -           Dc_help = 1;
  5660. -       }
  5661. -   }
  5662. +   SCP_string arg_str;
  5663. +   float val_f;
  5664. +   bool  val_b;
  5665.  
  5666. -   if ( Dc_help )  {
  5667. +   if (dc_optional_string_either("help", "--help")) {
  5668.         dc_printf( "Usage: light keyword\nWhere keyword can be in the following forms:\n" );
  5669.         dc_printf( "light on|off          Turns all lighting on/off\n" );
  5670.         dc_printf( "light default         Resets lighting to all default values\n" );
  5671. @@ -117,18 +77,70 @@ DCF(light,"Changes lighting parameters")
  5672.         dc_printf( "light mode [light|darken]   Changes the lighting mode.\n" );
  5673.         dc_printf( "   Where 'light' means the global light adds light.\n");
  5674.         dc_printf( "   and 'darken' means the global light subtracts light.\n");
  5675. -       Dc_status = 0;  // don't print status if help is printed.  Too messy.
  5676. +       return;
  5677.     }
  5678.  
  5679. -   if ( Dc_status )    {
  5680. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  5681.         dc_printf( "Ambient light is set to %.2f\n", Ambient_light );
  5682.         dc_printf( "Reflective light is set to %.2f\n", Reflective_light );
  5683.         dc_printf( "Dynamic lighting is: %s\n", (Lighting_flag?"on":"off") );
  5684. -       switch( Lighting_mode ) {
  5685. -       case LM_BRIGHTEN:   dc_printf( "Lighting mode is: light\n" ); break;
  5686. -       case LM_DARKEN:   dc_printf( "Lighting mode is: darken\n" ); break;
  5687. -       default: dc_printf( "Lighting mode is: UNKNOWN\n" ); break;
  5688. +       switch( Lighting_mode ) {
  5689. +       case LM_BRIGHTEN:
  5690. +           dc_printf( "Lighting mode is: light\n" );
  5691. +           break;
  5692. +       case LM_DARKEN:
  5693. +           dc_printf( "Lighting mode is: darken\n" );
  5694. +           break;
  5695. +       default:
  5696. +           dc_printf( "Lighting mode is: UNKNOWN\n" );
  5697. +       }
  5698. +       return;
  5699. +   }
  5700. +  
  5701. +   if (dc_optional_string("ambient")) {
  5702. +       dc_stuff_float(&val_f);
  5703. +       if ((val_f < 0.0f) || (val_f > 1.0f)) {
  5704. +           dc_printf(" Error: ambient value must be between 0.0 and 1.0\n");
  5705. +       } else {
  5706. +           Ambient_light = val_f;
  5707.         }
  5708. +  
  5709. +   } else if (dc_optional_string("reflect")) {
  5710. +       dc_stuff_float(&val_f);
  5711. +       if ( (val_f < 0.0f) || (val_f > 1.0f))  {
  5712. +           dc_printf(" Error: reflect value mus be between 0.0 and 1.0\n");
  5713. +       } else {
  5714. +           Reflective_light = val_f;
  5715. +       }
  5716. +  
  5717. +   } else if (dc_optional_string("default")) {
  5718. +       Lighting_mode = LM_BRIGHTEN;
  5719. +       Ambient_light = AMBIENT_LIGHT_DEFAULT;
  5720. +       Reflective_light = REFLECTIVE_LIGHT_DEFAULT;
  5721. +       Lighting_flag = 0;
  5722. +  
  5723. +   } else if (dc_optional_string("mode")) {
  5724. +       dc_stuff_string_white(arg_str);
  5725. +       if (arg_str == "light") {
  5726. +           Lighting_mode = LM_BRIGHTEN;
  5727. +  
  5728. +       } else if (arg_str == "darken") {
  5729. +           Lighting_mode = LM_DARKEN;
  5730. +      
  5731. +       } else {
  5732. +           dc_printf(" Error: unknown light mode: '%s'\n", arg_str.c_str());
  5733. +       }
  5734. +  
  5735. +   } else if (dc_optional_string("dynamic")) {
  5736. +       dc_stuff_boolean(&val_b);
  5737. +       Lighting_flag = val_b;
  5738. +
  5739. +   } else if(dc_maybe_stuff_boolean(&Lighting_off)) {
  5740. +       Lighting_off = !Lighting_off;
  5741. +
  5742. +   } else {
  5743. +       dc_stuff_string_white(arg_str);
  5744. +       dc_printf("Error: Unknown argument '%s'\n");
  5745.     }
  5746.  }
  5747.  
  5748. diff --git a/code/menuui/playermenu.cpp b/code/menuui/playermenu.cpp
  5749. index c224cf8..3f399bc 100644
  5750. --- a/code/menuui/playermenu.cpp
  5751. +++ b/code/menuui/playermenu.cpp
  5752. @@ -31,6 +31,7 @@
  5753.  #include "parse/parselo.h"
  5754.  #include "cfile/cfile.h"
  5755.  #include "network/multi.h"
  5756. +#include "debugconsole/console.h"
  5757.  
  5758.  
  5759.  // --------------------------------------------------------------------------------------------------------
  5760. @@ -1236,39 +1237,37 @@ void player_select_cancel_create()
  5761.  
  5762.  DCF(bastion,"Sets the player to be on the bastion (or any other main hall)")
  5763.  {
  5764. -   if(gameseq_get_state() != GS_STATE_INITIAL_PLAYER_SELECT) {
  5765. -       dc_printf("This command can only be run in the initial player select screen.\n");
  5766. +   int idx;
  5767. +
  5768. +   if (gameseq_get_state() != GS_STATE_INITIAL_PLAYER_SELECT) {
  5769. +       dc_printf("This command can only be run while the in the initial player select screen. \n");
  5770.         return;
  5771.     }
  5772.  
  5773. -   if (Dc_command) {
  5774. -       dc_get_arg(ARG_INT | ARG_NONE);
  5775. -
  5776. -       if (Dc_arg_type & ARG_INT) {
  5777. -           int idx = Dc_arg_int;
  5778. -
  5779. -           Assert(Main_hall_defines.at(gr_screen.res).size() < INT_MAX);
  5780. -           if (idx < 0 || idx >= (int) Main_hall_defines.at(gr_screen.res).size()) {
  5781. -               dc_printf("Main hall index out of range\n");
  5782. -           } else {
  5783. -               main_hall_get_name(Player_select_force_main_hall, idx);
  5784. -               dc_printf("Player is now on main hall '%d'\n", Player_select_force_main_hall.c_str());
  5785. -           }
  5786. -       } else {
  5787. -           Player_select_force_main_hall = "1";
  5788. -           dc_printf("Player is now on the Bastion... hopefully\n");
  5789. -       }
  5790. -       Dc_status = 0;
  5791. +   if (dc_optional_string_either("help", "--help")) {
  5792. +       dc_printf("Usage: bastion [index]\n");
  5793. +       dc_printf("    [index] -- optional main hall index; if not supplied, defaults to 1\n");
  5794. +       return;
  5795.     }
  5796.  
  5797. -   if (Dc_help) {
  5798. -       dc_printf("Usage: bastion [index]\n");
  5799. -       dc_printf("       [index] -- optional main hall index; if not supplied, defaults to 1\n");
  5800. -       Dc_status = 0;
  5801. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  5802. +       dc_printf("Player is on main hall '%s'\n", Player_select_force_main_hall.c_str());
  5803. +       return;
  5804.     }
  5805.  
  5806. -   if (Dc_status) {
  5807. -       dc_printf("There is no current main hall, as the player has not been selected yet!\n");
  5808. +   if (dc_maybe_stuff_int(&idx)) {
  5809. +       Assert(Main_hall_defines.at(gr_screen.res).size() < INT_MAX);
  5810. +       if (idx < 0 || idx >= (int) Main_hall_defines.at(gr_screen.res).size()) {
  5811. +           dc_printf("Main hall index out of range\n");
  5812. +       } else {
  5813. +           main_hall_get_name(Player_select_force_main_hall, idx);
  5814. +           dc_printf("Player is now on main hall '%d'\n", Player_select_force_main_hall.c_str());
  5815. +       }
  5816. +  
  5817. +   } else {
  5818. +       // No argument passed
  5819. +       Player_select_force_main_hall = "1";
  5820. +       dc_printf("Player is now on the Bastion... hopefully\n");
  5821.     }
  5822.  }
  5823.  
  5824. diff --git a/code/mission/missiongoals.cpp b/code/mission/missiongoals.cpp
  5825. index e860491..5e355b4 100644
  5826. --- a/code/mission/missiongoals.cpp
  5827. +++ b/code/mission/missiongoals.cpp
  5828. @@ -13,6 +13,7 @@
  5829.  #include "mission/missiongoals.h"
  5830.  #include "mission/missionlog.h"
  5831.  #include "missionui/missionscreencommon.h"
  5832. +#include "debugconsole/console.h"
  5833.  #include "freespace2/freespace.h"
  5834.  #include "gamesequence/gamesequence.h"
  5835.  #include "hud/hud.h"
  5836. @@ -1264,77 +1265,101 @@ void mission_goal_mark_events_complete()
  5837.  }
  5838.  
  5839.  // some debug console functions to help list and change the status of mission goals
  5840. -DCF(show_mission_goals,"List and change the status of mission goals")
  5841. +DCF(show_mission_goals,"Lists the status of mission goals")
  5842.  {
  5843.     int i, type;
  5844.  
  5845. -   if (Dc_command)
  5846. -       Dc_status = 1;
  5847. -
  5848. -   if (Dc_help) {
  5849. +   if (dc_optional_string_either("help", "--help")) {
  5850.         dc_printf("Usage: show_mission_goals\n\nList all mission goals and their current status.\n");
  5851. -       Dc_status = 0;
  5852. -   }
  5853. -
  5854. -   if (Dc_status) {
  5855. -       for (i=0; i<Num_goals; i++) {
  5856. -           type = Mission_goals[i].type & GOAL_TYPE_MASK;
  5857. -           dc_printf("%2d. %32s(%10s) -- ", i, Mission_goals[i].name, Goal_type_text(type));
  5858. -           if ( Mission_goals[i].satisfied == GOAL_COMPLETE )
  5859. -               dc_printf("satisfied.\n");
  5860. -           else if ( Mission_goals[i].satisfied == GOAL_INCOMPLETE )
  5861. -               dc_printf("not satisfied\n");
  5862. -           else if ( Mission_goals[i].satisfied == GOAL_FAILED )
  5863. -               dc_printf("failed\n");
  5864. -           else
  5865. -               dc_printf("\t[unknown goal status].\n");
  5866. -       }
  5867. +       return;
  5868. +   }
  5869. +
  5870. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  5871. +       // Don't do anything, but advance the parser past the flag
  5872. +   }
  5873. +
  5874. +   for (i=0; i<Num_goals; i++) {
  5875. +       type = Mission_goals[i].type & GOAL_TYPE_MASK;
  5876. +       dc_printf("%2d. %32s(%10s) -- ", i, Mission_goals[i].name, Goal_type_text(type));
  5877. +       if ( Mission_goals[i].satisfied == GOAL_COMPLETE )
  5878. +           dc_printf("satisfied.\n");
  5879. +       else if ( Mission_goals[i].satisfied == GOAL_INCOMPLETE )
  5880. +           dc_printf("unsatisfied\n");
  5881. +       else if ( Mission_goals[i].satisfied == GOAL_FAILED )
  5882. +           dc_printf("failed\n");
  5883. +       else
  5884. +           dc_printf("Warning! Mission goal %i is in an invalid state! (value: %i)", i, Mission_goals[i].satisfied);
  5885.     }
  5886. +  
  5887.  }
  5888.  
  5889.  //XSTR:OFF
  5890. -DCF(change_mission_goal, "Change the mission goal")
  5891. +DCF(change_mission_goal, "Changes the mission goal status")
  5892.  {
  5893.     int num;
  5894. +   bool val_b;
  5895. +   char *string;
  5896.  
  5897. -   if ( Dc_command ) {
  5898. -       dc_get_arg(ARG_INT);
  5899. -       if ( Dc_arg_int >= Num_goals ) {
  5900. -           dc_printf ("First parameter must be a valid goal number.\n");
  5901. -           return;
  5902. -       }
  5903. +   if (dc_optional_string_either("help", "--help")) {
  5904. +       dc_printf("Usage: change_mission_goal <goal_num> [status]\n");
  5905. +       dc_printf("<goal_num> --  Integer number of goal to change.  See show_mission_goals\n");
  5906. +       dc_printf("[status]   --  Goal status to change to.\n\n");
  5907.  
  5908. -       num = Dc_arg_int;
  5909. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_STRING);
  5910. -       if ( Dc_arg_type & ARG_TRUE )
  5911. -           Mission_goals[num].satisfied = GOAL_COMPLETE;
  5912. -       else if ( Dc_arg_type & ARG_FALSE )
  5913. -           Mission_goals[num].satisfied = GOAL_FAILED;
  5914. -       else if ( Dc_arg_type & ARG_NONE )
  5915. -           Mission_goals[num].satisfied = GOAL_INCOMPLETE;
  5916. -       else if ( Dc_arg_type & ARG_STRING) {
  5917. -           if ( !stricmp(Dc_arg, "satisfied") )
  5918. -               Mission_goals[num].satisfied = GOAL_COMPLETE;
  5919. -           else if ( !stricmp( Dc_arg, "failed") )
  5920. -               Mission_goals[num].satisfied = GOAL_FAILED;
  5921. -           else if ( !stricmp( Dc_arg, "unknown") )
  5922. -               Mission_goals[num].satisfied = GOAL_INCOMPLETE;
  5923. -           else
  5924. -               dc_printf("Unknown status %s.  Use 'satisfied', 'failed', or 'unknown'\n", Dc_arg);
  5925. -       }
  5926. +       dc_printf("The optional [status] field may be either a bool type or a string.\n");
  5927. +       dc_printf("\ttrue  -- Goal status set to 'complete'\n");
  5928. +       dc_printf("\tfalse -- Goal status set to 'failed'\n\n");
  5929. +
  5930. +       dc_printf("A string value of 'satisfied', 'failed', or 'unknown' will set the goal status to the respective state.\n");
  5931. +       dc_printf("If [status] is not given, then the goal status will be set to 'unknown'");
  5932. +
  5933. +       dc_printf("Examples:\n");
  5934. +       dc_printf("\t'change_mission_goal 1 true'  makes goal 1 as successful.\n");
  5935. +       dc_printf("\t'change_mission_goal 2'       marks goal 2 as unknown/incomplete\n");
  5936. +       dc_printf("\t'change_mission_goal 0 satisfied'    marks goal 0 as satisfied\n");
  5937. +       return;
  5938.     }
  5939.  
  5940. -   if ( Dc_help ) {
  5941. -       dc_printf("Usage: change_mission_goal <goal_num> <status>\n");
  5942. -       dc_printf("<goal_num> --  Integer number of goal to change.  See show_mission_goals\n");
  5943. -       dc_printf("<status>   --  [bool] where a true value makes the goal satisfied,\n");
  5944. -       dc_printf("               a false value makes the goal failed.\n");
  5945. -       dc_printf("The <status> field may also be one of 'satisfied', 'failed', or 'unknown'\n");
  5946. -       dc_printf("\nExamples:\n\n'change_mission_goal 1 true' makes goal 1 successful.\n");
  5947. -       dc_printf("'change_mission_goal 2' marks goal 2 not complete\n");
  5948. -       dc_printf("'change_mission_goal 0 satisfied' marks goal 0 as satisfied\n");
  5949. -       Dc_status = 0;
  5950. +   dc_stuff_int(&num);
  5951. +   if ( num >= Num_goals ) {
  5952. +       dc_printf (" Error: Invalid value for <goal_num>. Valid values: 0 - %i\n", Num_goals);
  5953. +       return;
  5954. +   }
  5955. +
  5956. +   if (dc_optional_string("satisfied")) {
  5957. +       Mission_goals[num].satisfied = GOAL_COMPLETE;
  5958. +
  5959. +   } else if (dc_optional_string("failed")) {
  5960. +       Mission_goals[num].satisfied = GOAL_FAILED;
  5961. +
  5962. +   } else if (dc_optional_string("unsatisfied")) {
  5963. +       Mission_goals[num].satisfied = GOAL_INCOMPLETE;
  5964. +
  5965. +   } else if (dc_maybe_stuff_boolean(&val_b)) {
  5966. +       val_b ? Mission_goals[num].satisfied = GOAL_COMPLETE : Mission_goals[num].satisfied = GOAL_FAILED;
  5967. +
  5968. +   } else {
  5969. +       // No argument given
  5970. +       Mission_goals[num].satisfied = GOAL_INCOMPLETE;
  5971. +   }
  5972. +
  5973. +   switch(Mission_goals[num].satisfied) {
  5974. +   case GOAL_COMPLETE:
  5975. +       string = "satisfied";
  5976. +       break;
  5977. +
  5978. +   case GOAL_FAILED:
  5979. +       string = "failed";
  5980. +       break;
  5981. +
  5982. +   case GOAL_INCOMPLETE:
  5983. +       string = "unsatisfied";
  5984. +       break;
  5985. +
  5986. +   default:
  5987. +       dc_printf("Warning! Mission goal %i is in an invalid state! (value: %i)", num, Mission_goals[num].satisfied);
  5988. +       return;
  5989.     }
  5990. +   dc_printf("Mission goal %i set to '%s'\n", num, string);
  5991.  }
  5992.  //XSTR:ON
  5993.  
  5994. diff --git a/code/model/modelinterp.cpp b/code/model/modelinterp.cpp
  5995. index 54e33c7..948447f 100644
  5996. --- a/code/model/modelinterp.cpp
  5997. +++ b/code/model/modelinterp.cpp
  5998. @@ -33,6 +33,7 @@
  5999.  #include "graphics/gropengllight.h"
  6000.  #include "ship/shipfx.h"
  6001.  #include "gamesequence/gamesequence.h"
  6002. +#include "debugconsole/console.h"
  6003.  
  6004.  #include <limits.h>
  6005.  
  6006. @@ -1941,19 +1942,20 @@ float Interp_depth_scale = 1500.0f;
  6007.  
  6008.  DCF(model_darkening,"Makes models darker with distance")
  6009.  {
  6010. -   if ( Dc_command )   {
  6011. -       dc_get_arg(ARG_FLOAT);
  6012. -       Interp_depth_scale = Dc_arg_float;
  6013. -   }
  6014. -
  6015. -   if ( Dc_help )  {
  6016. -       dc_printf( "Usage: model_darkening float\n" );
  6017. -       Dc_status = 0;  // don't print status if help is printed.  Too messy.
  6018. +   if (dc_optional_string_either("help", "--help")) {
  6019. +       dc_printf( "Usage: model_darkening <float>\n" );
  6020. +       dc_printf("Sets the distance at which to start blacking out models (namely asteroids).\n");
  6021. +       return;
  6022.     }
  6023.  
  6024. -   if ( Dc_status )    {
  6025. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6026.         dc_printf( "model_darkening = %.1f\n", Interp_depth_scale );
  6027. +       return;
  6028.     }
  6029. +
  6030. +   dc_stuff_float(&Interp_depth_scale);
  6031. +
  6032. +   dc_printf("model_darkening set to %.1f\n", Interp_depth_scale);
  6033.  }
  6034.  
  6035.  void model_render(int model_num, matrix *orient, vec3d * pos, uint flags, int objnum, int lighting_skip, int *replacement_textures)
  6036. @@ -2116,8 +2118,13 @@ float model_find_closest_point( vec3d *outpnt, int model_num, int submodel_num,
  6037.  }
  6038.  
  6039.  int tiling = 1;
  6040. -DCF(tiling, "")
  6041. +DCF(tiling, "Toggles rendering of tiled textures (default is on)")
  6042.  {
  6043. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6044. +       dc_printf("Tiled textures are %s", tiling ? "ON" : "OFF");
  6045. +       return;
  6046. +   }
  6047. +
  6048.     tiling = !tiling;
  6049.     if(tiling){
  6050.         dc_printf("Tiled textures\n");
  6051. diff --git a/code/nebula/neb.cpp b/code/nebula/neb.cpp
  6052. index d038741..135efd6 100644
  6053. --- a/code/nebula/neb.cpp
  6054. +++ b/code/nebula/neb.cpp
  6055. @@ -24,6 +24,7 @@
  6056.  #include "mission/missionparse.h"
  6057.  #include "ship/ship.h"
  6058.  #include "cmdline/cmdline.h"
  6059. +#include "debugconsole/console.h"
  6060.  
  6061.  
  6062.  // --------------------------------------------------------------------------------------------------------
  6063. @@ -503,7 +504,7 @@ void neb2_page_in()
  6064.  
  6065.  // should we not render this object because its obscured by the nebula?
  6066.  int neb_skip_opt = 1;
  6067. -DCF(neb_skip, "")
  6068. +DCF(neb_skip, "Toggles culling of objects obscured by nebula")
  6069.  {
  6070.     neb_skip_opt = !neb_skip_opt;
  6071.     if (neb_skip_opt) {
  6072. @@ -896,12 +897,14 @@ void neb2_regen()
  6073.     }
  6074.  }
  6075.  
  6076. +/*
  6077. + * TODO: remove this
  6078.  float max_area = 100000000.0f;
  6079.  DCF(max_area, "")
  6080.  {
  6081. -   dc_get_arg(ARG_FLOAT);
  6082. -   max_area = Dc_arg_float;
  6083. +   dc_stuff_float(&max_area);
  6084.  }
  6085. +*/
  6086.  
  6087.  float g3_draw_rotated_bitmap_area(vertex *pnt, float angle, float rad, uint tmap_flags, float area);
  6088.  int neb_mode = 1;
  6089. @@ -1443,7 +1446,7 @@ int neb2_get_bitmap()
  6090.  }
  6091.  
  6092.  // nebula DCF functions ------------------------------------------------------
  6093. -
  6094. +// TODO: With the new debug parser in place, most of these sub-commands can now be handled by neb2. This should clear up the DCF list a bit
  6095.  DCF(neb2, "list nebula console commands")
  6096.  {     
  6097.  // dc_printf("neb2_fog <X> <float> <float>  : set near and far fog planes for ship type X\n");
  6098. @@ -1463,7 +1466,7 @@ DCF(neb2, "list nebula console commands")
  6099.     dc_printf("neb2_cinner      : poof cube inner dimension\n");
  6100.     dc_printf("neb2_couter      : poof cube outer dimension\n");
  6101.     dc_printf("neb2_jitter      : poof jitter\n");
  6102. -   dc_printf("neb2_mode        : switch between no nebula, polygon background, pof background, lame or HTL rendering (0, 1, 2, 3 and 4 respectively)\n\n");   
  6103. +   dc_printf("neb2_mode        : switch between no nebula, polygon background, pof background, lame, or HTL rendering (0, 1, 2, 3 and 4 respectively)\n\n");  
  6104.     dc_printf("neb2_ff          : flash fade/sec\n");
  6105.     dc_printf("neb2_background  : rgb background color\n");
  6106.     dc_printf("neb2_fog_color   : rgb fog color\n");
  6107. @@ -1471,95 +1474,91 @@ DCF(neb2, "list nebula console commands")
  6108.  // dc_printf("neb2_fog_vals    : display all the current settings for all above values\n");   
  6109.  }
  6110.  
  6111. -DCF(neb2_prad, "")
  6112. +DCF(neb2_prad, "set cloud poof radius")
  6113.  {
  6114. -   dc_get_arg(ARG_FLOAT);
  6115. -   Nd->prad = Dc_arg_float;
  6116. +   dc_stuff_float(&Nd->prad);
  6117.  }
  6118. -DCF(neb2_cdim, "")
  6119. +DCF(neb2_cdim, "poof cube dimension")
  6120.  {
  6121. -   dc_get_arg(ARG_FLOAT);
  6122. -   Nd->cube_dim = Dc_arg_float;
  6123. +   dc_stuff_float(&Nd->cube_dim);
  6124.  }
  6125.  
  6126. -DCF(neb2_cinner, "")
  6127. +DCF(neb2_cinner, "poof cube inner dimension")
  6128.  {
  6129. -   dc_get_arg(ARG_FLOAT);
  6130. -   Nd->cube_inner = Dc_arg_float;
  6131. +   dc_stuff_float(&Nd->cube_inner);
  6132.  }
  6133.  
  6134. -DCF(neb2_couter, "")
  6135. +DCF(neb2_couter, "poof cube outer dimension")
  6136.  {
  6137. -   dc_get_arg(ARG_FLOAT);
  6138. -   Nd->cube_outer = Dc_arg_float;
  6139. +   dc_stuff_float(&Nd->cube_outer);
  6140.  }
  6141.  
  6142. -DCF(neb2_jitter, "")
  6143. +DCF(neb2_jitter, "poof jitter")
  6144.  {
  6145. -   dc_get_arg(ARG_FLOAT);
  6146. -   Nd->hj = Nd->dj = Nd->wj = Dc_arg_float;
  6147. +   float value;
  6148. +   dc_stuff_float(&value);
  6149. +   Nd->hj = Nd->dj = Nd->wj = value;
  6150.  }
  6151.  
  6152. -DCF(neb2_max_alpha, "")
  6153. +DCF(neb2_max_alpha, "max alpha value (0.0 to 1.0) for cloud poofs.")
  6154.  {
  6155. -   dc_get_arg(ARG_FLOAT);
  6156. -   Nd->max_alpha_glide = Dc_arg_float;
  6157. +   dc_stuff_float(&Nd->max_alpha_glide);
  6158.  }
  6159.  
  6160. -DCF(neb2_break_alpha, "")
  6161. +DCF(neb2_break_alpha, "alpha value (0.0 to 1.0) at which faded polygons are not drawn.")
  6162.  {
  6163. -   dc_get_arg(ARG_FLOAT);
  6164. -   Nd->break_alpha = Dc_arg_float;
  6165. +   dc_stuff_float(&Nd->break_alpha);
  6166.  }
  6167.  
  6168. -DCF(neb2_break_off, "")
  6169. +DCF(neb2_break_off, "how many pixels offscreen (left, right, top, bottom) when a cloud poof becomes fully transparent.")
  6170.  {
  6171. -   dc_get_arg(ARG_INT);
  6172. -   Nd->break_y = (float)Dc_arg_int;
  6173. -   Nd->break_x = Nd->break_y * 1.3333f;
  6174. +   int value;
  6175. +   dc_stuff_int(&value);
  6176. +   Nd->break_y = (float)value;
  6177. +   Nd->break_x = Nd->break_y * gr_screen.aspect;
  6178.  }
  6179.  
  6180. -DCF(neb2_smooth, "")
  6181. +DCF(neb2_smooth, "magic fog smoothing modes (0 - 3)")
  6182.  {
  6183.     int index;
  6184. -   dc_get_arg(ARG_INT);
  6185. -   index = Dc_arg_int;
  6186. +   dc_stuff_int(&index);
  6187.     if ( (index >= 0) && (index <= 3) ) {
  6188.         wacky_scheme = index;
  6189. +   } else {
  6190. +       dc_printf("Invalid smooth mode %i", index);
  6191.     }
  6192.  }
  6193.  
  6194. -DCF(neb2_select, "")
  6195. +DCF(neb2_select, "Enables/disables a poof bitmap")
  6196.  {
  6197. -   dc_get_arg(ARG_INT);
  6198. -   int bmap = Dc_arg_int;
  6199. +   int bmap;
  6200. +   bool val_b;
  6201. +
  6202. +   dc_stuff_int(&bmap);
  6203. +
  6204.     if ( (bmap >= 0) && (bmap < Neb2_poof_count) ) {
  6205. -       dc_get_arg(ARG_INT);
  6206. -       if (Dc_arg_int) {
  6207. -           Neb2_poof_flags |= (1<<bmap);
  6208. -       } else {
  6209. -           Neb2_poof_flags &= ~(1<<bmap);
  6210. -       }
  6211. +       dc_stuff_boolean(&val_b);
  6212. +
  6213. +       val_b ? (Neb2_poof_flags |= (1<<bmap)) : (Neb2_poof_flags &= ~(1<<bmap));
  6214.     }
  6215.  }
  6216.  
  6217. -DCF(neb2_rot, "")
  6218. +DCF(neb2_rot, "set max rotation speed for poofs")
  6219.  {
  6220. -   dc_get_arg(ARG_FLOAT);
  6221. -   max_rotation = Dc_arg_float;
  6222. +   dc_stuff_float(&max_rotation);
  6223.  }
  6224.  
  6225. -DCF(neb2_ff, "")
  6226. +DCF(neb2_ff, "flash fade/sec")
  6227.  {
  6228. -   dc_get_arg(ARG_FLOAT);
  6229. -   neb2_flash_fade = Dc_arg_float;
  6230. +   dc_stuff_float(&neb2_flash_fade);
  6231.  }
  6232.  
  6233. -DCF(neb2_mode, "")
  6234. +DCF(neb2_mode, "Switches nebula render modes")
  6235.  {
  6236. -   dc_get_arg(ARG_INT);
  6237. +   int mode;
  6238. +   dc_stuff_int(&mode);
  6239.  
  6240. -   switch (Dc_arg_int) {
  6241. +   switch (mode) {
  6242.         case NEB2_RENDER_NONE:
  6243.             Neb2_render_mode = NEB2_RENDER_NONE;
  6244.         break;
  6245. @@ -1586,39 +1585,32 @@ DCF(neb2_mode, "")
  6246.     }
  6247.  }
  6248.  
  6249. -DCF(neb2_slices, "")
  6250. +DCF(neb2_slices, "Sets how many 'slices' are used in the nebula")
  6251.  {
  6252. -   dc_get_arg(ARG_INT);
  6253. -   Neb2_slices = Dc_arg_int;
  6254. +   dc_stuff_int(&Neb2_slices);
  6255.     neb2_eye_changed();
  6256.  }
  6257.  
  6258. -DCF(neb2_background, "")
  6259. +DCF(neb2_background, "Sets the RGB background color (lame rendering)")
  6260.  {
  6261.     int r, g, b;
  6262.  
  6263. -   dc_get_arg(ARG_INT);
  6264. -   r = Dc_arg_int;
  6265. -   dc_get_arg(ARG_INT);
  6266. -   g = Dc_arg_int;
  6267. -   dc_get_arg(ARG_INT);
  6268. -   b = Dc_arg_int;
  6269. +   dc_stuff_int(&r);
  6270. +   dc_stuff_int(&g);
  6271. +   dc_stuff_int(&b);
  6272.  
  6273.     Neb2_background_color[0] = r;
  6274.     Neb2_background_color[1] = g;
  6275.     Neb2_background_color[2] = b;
  6276.  }
  6277.  
  6278. -DCF(neb2_fog_color, "")
  6279. +DCF(neb2_fog_color, "Sets the RGB fog color (HTL)")
  6280.  {
  6281.     ubyte r, g, b;
  6282.  
  6283. -   dc_get_arg(ARG_UBYTE);
  6284. -   r = Dc_arg_ubyte;
  6285. -   dc_get_arg(ARG_UBYTE);
  6286. -   g = Dc_arg_ubyte;
  6287. -   dc_get_arg(ARG_UBYTE);
  6288. -   b = Dc_arg_ubyte;
  6289. +   dc_stuff_ubyte(&r);
  6290. +   dc_stuff_ubyte(&g);
  6291. +   dc_stuff_ubyte(&b);
  6292.  
  6293.     Neb2_fog_color_r = r;
  6294.     Neb2_fog_color_g = g;
  6295. diff --git a/code/nebula/neblightning.cpp b/code/nebula/neblightning.cpp
  6296. index f311e4a..b189349 100644
  6297. --- a/code/nebula/neblightning.cpp
  6298. +++ b/code/nebula/neblightning.cpp
  6299. @@ -13,6 +13,7 @@
  6300.  #include "parse/parselo.h"
  6301.  #include "globalincs/linklist.h"
  6302.  #include "io/timer.h"
  6303. +#include "debugconsole/console.h"
  6304.  #include "freespace2/freespace.h"
  6305.  #include "gamesnd/gamesnd.h"
  6306.  #include "render/3d.h"
  6307. @@ -81,52 +82,43 @@ vec3d Nebl_bolt_strike;         // strike point of the bolt being generated
  6308.  storm_type *Storm = NULL;
  6309.  
  6310.  // vars
  6311. -DCF(b_scale, "")
  6312. +DCF(b_scale, "Sets the scale factor for debug nebula bolts")
  6313.  {
  6314. -   dc_get_arg(ARG_FLOAT);
  6315. -   Bolt_types[DEBUG_BOLT].b_scale = Dc_arg_float;
  6316. +   dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_scale);
  6317.  }
  6318. -DCF(b_rand, "")
  6319. +DCF(b_rand, "Sets the randomness factor for debug nebula bolts")
  6320.  {
  6321. -   dc_get_arg(ARG_FLOAT);
  6322. -   Bolt_types[DEBUG_BOLT].b_rand = Dc_arg_float;
  6323. +   dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_rand);
  6324.  }
  6325. -DCF(b_shrink, "")
  6326. +DCF(b_shrink, "Sets the shrink factor for debug nebula bolts")
  6327.  {
  6328. -   dc_get_arg(ARG_FLOAT);
  6329. -   Bolt_types[DEBUG_BOLT].b_shrink = Dc_arg_float;
  6330. +   dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_shrink);
  6331.  }
  6332. -DCF(b_poly_pct, "")
  6333. +DCF(b_poly_pct, "Sets b_poly_pct")
  6334.  {
  6335. -   dc_get_arg(ARG_FLOAT);
  6336. -   Bolt_types[DEBUG_BOLT].b_poly_pct = Dc_arg_float;
  6337. +   dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_poly_pct);
  6338.  }
  6339. -DCF(b_add, "")
  6340. +DCF(b_add, "Sets b_add")
  6341.  {
  6342. -   dc_get_arg(ARG_FLOAT);
  6343. -   Bolt_types[DEBUG_BOLT].b_add = Dc_arg_float;
  6344. +   dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_add);
  6345.  }
  6346. -DCF(b_strikes, "")
  6347. +DCF(b_strikes, "Sets num_strikes")
  6348.  {
  6349. -   dc_get_arg(ARG_INT);
  6350. -   Bolt_types[DEBUG_BOLT].num_strikes = Dc_arg_int;
  6351. +   dc_stuff_int(&Bolt_types[DEBUG_BOLT].num_strikes);
  6352.  }
  6353. -DCF(b_noise, "")
  6354. +DCF(b_noise, "Sets noise factor")
  6355.  {
  6356. -   dc_get_arg(ARG_FLOAT);
  6357. -   Bolt_types[DEBUG_BOLT].noise = Dc_arg_float;
  6358. +   dc_stuff_float(&Bolt_types[DEBUG_BOLT].noise);
  6359.  }
  6360. -DCF(b_bright, "")
  6361. +DCF(b_bright, "Sets brightness factor")
  6362.  {
  6363. -   dc_get_arg(ARG_FLOAT);
  6364. -   Bolt_types[DEBUG_BOLT].b_bright = Dc_arg_float;
  6365. +   dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_bright);
  6366.  }
  6367. -DCF(b_lifetime, "")
  6368. +DCF(b_lifetime, "Sets lifetime duration")
  6369.  {
  6370. -   dc_get_arg(ARG_INT);
  6371. -   Bolt_types[DEBUG_BOLT].lifetime = Dc_arg_int;
  6372. +   dc_stuff_int(&Bolt_types[DEBUG_BOLT].lifetime);
  6373.  }
  6374. -DCF(b_list, "")
  6375. +DCF(b_list, "Displays status of debug lightning commands")
  6376.  {
  6377.     dc_printf("Debug lightning bolt settings :\n");
  6378.  
  6379. @@ -144,12 +136,12 @@ DCF(b_list, "")
  6380.  // nebula lightning intensity (0.0 to 1.0)
  6381.  float Nebl_intensity = 0.6667f;
  6382.  
  6383. -DCF(lightning_intensity, "")
  6384. +DCF(lightning_intensity, "Sets lightning intensity between 0.0 and 1.0 (Default is 0.6667)")
  6385.  {
  6386. -   dc_get_arg(ARG_FLOAT);
  6387. -   float val = Dc_arg_float;
  6388. -    
  6389. -    CLAMP(val, 0.0f, 1.0f);
  6390. +   float val;
  6391. +   dc_stuff_float(&val);
  6392. +
  6393. +   CLAMP(val, 0.0f, 1.0f);
  6394.  
  6395.     Nebl_intensity = 1.0f - val;
  6396.  }
  6397. diff --git a/code/network/multi.cpp b/code/network/multi.cpp
  6398. index 93d18c1..95fff3b 100644
  6399. --- a/code/network/multi.cpp
  6400. +++ b/code/network/multi.cpp
  6401. @@ -48,6 +48,7 @@
  6402.  #include "cfile/cfile.h"
  6403.  #include "fs2netd/fs2netd_client.h"
  6404.  #include "pilotfile/pilotfile.h"
  6405. +#include "debugconsole/console.h"
  6406.  
  6407.  
  6408.  
  6409. @@ -1105,14 +1106,15 @@ void multi_process_incoming()
  6410.  //
  6411.  
  6412.  int eye_tog = 1;
  6413. -DCF(eye_tog, "")
  6414. +DCF(eye_tog, "Toggles setting of the local player eyepoint on every frame (Multiplayer)")
  6415.  {
  6416. -   eye_tog = !eye_tog;
  6417. -   if(eye_tog){
  6418. -       dc_printf("proper eye stuff on\n");
  6419. -   } else {
  6420. -       dc_printf("proper eye stuff off\n");
  6421. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6422. +       dc_printf("proper eye stuff is %s\n", eye_tog ? "ON" : "OFF");
  6423. +       return;
  6424.     }
  6425. +
  6426. +   eye_tog = !eye_tog;
  6427. +   dc_printf("proper eye stuff is %s\n", eye_tog ? "ON" : "OFF");
  6428.  }
  6429.  
  6430.  void multi_do_frame()
  6431. @@ -1772,13 +1774,14 @@ void multi_reset_timestamps()
  6432.  }
  6433.  
  6434.  // netgame debug flags for debug console stuff
  6435. -DCF(netd, "change/list netgame debug flags")
  6436. +DCF(netd, "change netgame debug flags (Mulitplayer)")
  6437.  {
  6438. -   dc_get_arg(ARG_INT);
  6439. +   int value;
  6440. +   dc_stuff_int(&value);
  6441.    
  6442. -   // if we got an integer, and we're the server, change flags
  6443. -   if((Dc_arg_type & ARG_INT) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Dc_arg_int <= 7)){
  6444. -       Netgame.debug_flags ^= (1<<Dc_arg_int);
  6445. +   // if we're the server, change flags
  6446. +   if ((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && (value <= 7)) {
  6447. +       Netgame.debug_flags ^= (1 << value);
  6448.     }
  6449.  
  6450.     // display network flags
  6451. diff --git a/code/network/multi_kick.cpp b/code/network/multi_kick.cpp
  6452. index 86e3227..3c95d17 100644
  6453. --- a/code/network/multi_kick.cpp
  6454. +++ b/code/network/multi_kick.cpp
  6455. @@ -18,6 +18,7 @@
  6456.  #include "freespace2/freespace.h"
  6457.  #include "playerman/player.h"
  6458.  #include "io/timer.h"
  6459. +#include "debugconsole/console.h"
  6460.  
  6461.  
  6462.  // ----------------------------------------------------------------------------------
  6463. @@ -137,18 +138,14 @@ int multi_kick_is_banned(net_addr *addr)
  6464.  void multi_dcf_kick()
  6465.  {
  6466.     int player_num,idx;
  6467. +   SCP_string arg;
  6468.  
  6469.     // get the callsign of the player to kick
  6470. -   dc_get_arg(ARG_STRING);
  6471. -
  6472. -   if(Dc_arg[0] == '\0'){
  6473. -       dc_printf("Invalid player callsign!\n");
  6474. -       return ;
  6475. -   }
  6476. +   dc_stuff_string(arg);
  6477.  
  6478.     player_num = -1;
  6479.     for(idx=0;idx<MAX_PLAYERS;idx++){
  6480. -       if(MULTI_CONNECTED(Net_players[idx]) && (stricmp(Net_players[idx].m_player->callsign,Dc_arg)==0)){
  6481. +       if(MULTI_CONNECTED(Net_players[idx]) && (stricmp(Net_players[idx].m_player->callsign, arg.c_str()) == 0)) {
  6482.             player_num = idx;
  6483.             break;
  6484.         }
  6485. @@ -156,7 +153,7 @@ void multi_dcf_kick()
  6486.  
  6487.     // if we didn't find the player, notify of the results
  6488.     if(player_num == -1){
  6489. -       dc_printf("Could not find player %s to kick!",Dc_arg);
  6490. +       dc_printf("Could not find player %s to kick!", arg.c_str());
  6491.     }
  6492.     // if we found the guy, then try and kick him
  6493.     else {
  6494. diff --git a/code/network/multi_obj.cpp b/code/network/multi_obj.cpp
  6495. index 1b7941c..4c421f7 100644
  6496. --- a/code/network/multi_obj.cpp
  6497. +++ b/code/network/multi_obj.cpp
  6498. @@ -26,6 +26,7 @@
  6499.  #include "physics/physics.h"
  6500.  #include "ship/afterburner.h"
  6501.  #include "cfile/cfile.h"
  6502. +#include "debugconsole/console.h"
  6503.  
  6504.  
  6505.  // ---------------------------------------------------------------------------------------------------
  6506. @@ -1569,10 +1570,21 @@ int OO_server_rate_stamp = -1;
  6507.  
  6508.  // bandwidth granularity
  6509.  int OO_gran = 1;
  6510. -DCF(oog, "")
  6511. +DCF(oog, "Sets bandwidth granularity (Multiplayer)")
  6512.  {
  6513. -   dc_get_arg(ARG_INT);
  6514. -   OO_gran = Dc_arg_int;
  6515. +   if (dc_optional_string_either("help", "--help")) {
  6516. +       dc_printf("Usage: oog <OO_gran>\n");
  6517. +       dc_printf("Sets bandwidth granularity\n");
  6518. +       return;
  6519. +   }
  6520. +
  6521. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6522. +       dc_printf("Current Granularity is '%i' (default is 1)", OO_gran);
  6523. +       return;
  6524. +   }
  6525. +
  6526. +   dc_stuff_int(&OO_gran);
  6527. +   dc_printf("Ganularity set to %i", OO_gran);
  6528.  }
  6529.  
  6530.  // process datarate limiting stuff for the server
  6531. @@ -1939,10 +1951,21 @@ void multi_oo_interp(object *objp)
  6532.  }
  6533.  
  6534.  float oo_error = 0.8f;
  6535. -DCF(oo_error, "")
  6536. +DCF(oo_error, "Sets error factor for flight path prediction physics (Multiplayer)")
  6537.  {
  6538. -   dc_get_arg(ARG_FLOAT);
  6539. -   oo_error = Dc_arg_float;
  6540. +   if (dc_optional_string_either("help", "--help")) {
  6541. +       dc_printf("Usage: oo_error <value>\n");
  6542. +       return;
  6543. +   }
  6544. +
  6545. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6546. +       dc_printf("oo_error is currently %f", oo_error);
  6547. +       return;
  6548. +   }
  6549. +
  6550. +   dc_stuff_float(&oo_error);
  6551. +  
  6552. +   dc_printf("oo_error set to %f", oo_error);
  6553.  }
  6554.  
  6555.  void multi_oo_calc_interp_splines(int ship_index, vec3d *cur_pos, matrix *cur_orient, physics_info *cur_phys_info, vec3d *new_pos, matrix *new_orient, physics_info *new_phys_info)
  6556. @@ -1994,14 +2017,16 @@ void oo_update_time()
  6557.  }
  6558.  
  6559.  int display_oo_bez = 0;
  6560. -DCF(bez, "")
  6561. +DCF(bez, "Toggles rendering of player ship trajectory interpolation splines (Multiplayer) *disabled*")
  6562.  {
  6563. -   display_oo_bez = !display_oo_bez;
  6564. -   if(display_oo_bez){
  6565. -       dc_printf("Showing interp splines");
  6566. -   } else {
  6567. -       dc_printf("Not showing interp splines");
  6568. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6569. +       dc_printf("Rendering of interpolation splines is '%s'", display_oo_bez ? "ON" : "OFF");
  6570. +       return;
  6571.     }
  6572. +
  6573. +   display_oo_bez = !display_oo_bez;
  6574. +
  6575. +   dc_printf("%showing interp splines", display_oo_bez ? "S" : "Not s");
  6576.  }
  6577.  
  6578.  void oo_display()
  6579. diff --git a/code/network/multi_pxo.cpp b/code/network/multi_pxo.cpp
  6580. index fc562c6..39307d3 100644
  6581. --- a/code/network/multi_pxo.cpp
  6582. +++ b/code/network/multi_pxo.cpp
  6583. @@ -42,6 +42,7 @@
  6584.  #include "playerman/player.h"
  6585.  #include "fs2netd/fs2netd_client.h"
  6586.  #include "menuui/mainhallmenu.h"
  6587. +#include "debugconsole/console.h"
  6588.  
  6589.  
  6590.  
  6591. @@ -461,14 +462,15 @@ void multi_pxo_scroll_players_down();
  6592.  // get the absolute index of the displayed items which our currently selected one is
  6593.  int multi_pxo_get_select_index();
  6594.  
  6595. -DCF(players, "")
  6596. +DCF(players, "Adds the specified number of bogus players to the PXO listing (Multiplayer)")
  6597.  {
  6598.     char name[512] = "";
  6599. -
  6600. +   int i;
  6601.     // add a bunch of bogus players
  6602. -   dc_get_arg(ARG_INT);
  6603. -   for(int idx=0; idx<Dc_arg_int; idx++){
  6604. -       sprintf(name, "player %d", idx);
  6605. +   dc_stuff_int(&i);
  6606. +
  6607. +   for(int idx = 0; idx < i; idx++){
  6608. +       sprintf(name, "bogus player %d", idx);
  6609.         multi_pxo_add_player(name);
  6610.     }
  6611.  }
  6612. diff --git a/code/network/multi_voice.cpp b/code/network/multi_voice.cpp
  6613. index ac8f6de..ee9b794 100644
  6614. --- a/code/network/multi_voice.cpp
  6615. +++ b/code/network/multi_voice.cpp
  6616. @@ -22,7 +22,7 @@
  6617.  #include "menuui/optionsmenumulti.h"
  6618.  #include "network/multi.h"
  6619.  #include "playerman/player.h"
  6620. -
  6621. +#include "debugconsole/console.h"
  6622.  
  6623.  
  6624.  // --------------------------------------------------------------------------------------------------
  6625. @@ -483,16 +483,17 @@ void multi_voice_process()
  6626.  // voice settings debug console function
  6627.  void multi_voice_dcf()
  6628.  {
  6629. -   dc_get_arg(ARG_STRING);
  6630. +   SCP_string arg;
  6631. +   int value;
  6632. +
  6633. +   dc_stuff_string_white(arg);
  6634.  
  6635.     // set the quality of sound
  6636. -   if (strcmp(Dc_arg, NOX("qos")) == 0) {
  6637. -       dc_get_arg(ARG_INT);
  6638. -       if(Dc_arg_type & ARG_INT){
  6639. -           if((Dc_arg_int >= 1) && (Dc_arg_int <= 10) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
  6640. -               multi_voice_set_vars(Dc_arg_int,-1);
  6641. -               dc_printf("Quality of sound : %d\n",Dc_arg_int);
  6642. -           }
  6643. +   if (arg == NOX("qos")) {
  6644. +       dc_stuff_int(&value);
  6645. +       if((value >= 1) && (value <= 10) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
  6646. +           multi_voice_set_vars(value,-1);
  6647. +           dc_printf("Quality of sound : %d\n", value);
  6648.         }
  6649.     }
  6650.  }
  6651. diff --git a/code/network/multilag.cpp b/code/network/multilag.cpp
  6652. index de8a524..9e10441 100644
  6653. --- a/code/network/multilag.cpp
  6654. +++ b/code/network/multilag.cpp
  6655. @@ -18,6 +18,7 @@
  6656.  #include "io/timer.h"
  6657.  #include "globalincs/linklist.h"
  6658.  #include "network/psnet2.h"
  6659. +#include "debugconsole/console.h"
  6660.  
  6661.  
  6662.  
  6663. @@ -392,6 +393,7 @@ void multi_lag_put_free(lag_buf *buf)
  6664.     Lag_buf_count--;
  6665.  }
  6666.  
  6667. +// Help and status provider for the lag-loss system
  6668.  void multi_lagloss_dcf()
  6669.  {
  6670.     // if the lag system isn't inited, don't do anything
  6671. @@ -400,183 +402,290 @@ void multi_lagloss_dcf()
  6672.         return;
  6673.     }
  6674.  
  6675. +   // display status of lag system
  6676. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6677. +       dc_printf("Lag system status:\n");
  6678. +       // display lag settings
  6679. +       dc_printf("Lag : \n");
  6680. +       dc_printf("Base  \t\tMin   \t\tMax   \t\tStreak\n");
  6681. +       dc_printf("%f\t\t%f\t\t%f\t\t%f\n\n", Multi_lag_base, Multi_lag_min, Multi_lag_max, Multi_streak_time);
  6682. +
  6683. +       // display loss settings
  6684. +       dc_printf("Loss : \n");
  6685. +       dc_printf("Base  \t\tMin   \t\tMax\n");
  6686. +       dc_printf("%f\t\t%f\t\t%f\n", Multi_loss_base, Multi_loss_min, Multi_loss_max);
  6687. +       return;
  6688. +   }
  6689. +
  6690.     // display all available commands
  6691. -   dc_printf("Usage :\nlag <ms>  (-1 to disable)\nlag_min <ms>\nlag_max <ms>\nloss <0-100>  (-1 to disable)\nloss_min <0-100>\nloss_max <0-100>\nlag_streak <ms>\nlagloss\n");
  6692. +   dc_printf("Lag system commands\n\n");
  6693. +
  6694. +   dc_printf("Usage :\n");
  6695. +   dc_printf("lag <ms>\n");
  6696. +       dc_printf("\tSets the lag base value if <ms> is within the max and min limits (see lag_min and lag_max)\n");
  6697. +       dc_printf("\tIf <ms> is outside of the max and min limits, then nothing is done\n");
  6698. +       dc_printf("\tIf <ms> is negative, then lag simulation is turned off\n\n");
  6699. +
  6700. +   dc_printf("lag_min <ms>\n");
  6701. +       dc_printf("\tSets the lag min value if <ms> is less than the base value\n");
  6702. +       dc_printf("\tIf <ms> is outside the base or max values, then nothing is done\n");
  6703. +       dc_printf("\tIf <ms> is negative, then the min limit is removed\n\n");
  6704. +
  6705. +   dc_printf("lag_max <ms>\n");
  6706. +       dc_printf("\tSets the lag max value if <ms> is greater than the base value\n");
  6707. +       dc_printf("\tIf <ms> is outside the base or min values, then nothing is done\n");
  6708. +       dc_printf("\tIf <ms> is negative, then the max limit is removed\n\n");
  6709. +
  6710. +   dc_printf("loss    <0-100>  (-1 to disable)\n");
  6711. +       dc_printf("\tSimilar to lag, but applies value to loss base value\n\n");
  6712. +
  6713. +   dc_printf("loss_min <0-100>\n");
  6714. +       dc_printf("\tSimilar to lag_min, but applies value to loss min value\n\n");
  6715. +  
  6716. +   dc_printf("loss_max <0-100>\n");
  6717. +       dc_printf("\tSimilar to lag_max, but applies value to loss max value\n\n");
  6718.  
  6719. -   // display lag settings
  6720. -   dc_printf("Lag : ");       
  6721. -   dc_printf("\n   Base %d\n   Min %d\n   Max %d\n   Streak %d\n", Multi_lag_base, Multi_lag_min, Multi_lag_max, Multi_streak_time);  
  6722.  
  6723. -   // display loss settings
  6724. -   dc_printf("Loss : ");      
  6725. -   dc_printf("\n   Base %f\n   Min %f\n   Max %f\n", Multi_loss_base, Multi_loss_min, Multi_loss_max);
  6726. +   dc_printf("lag_streak <ms>\n");
  6727. +       dc_printf("\tSets the duration of lag streaks where the lag is consistant for <ms>\n");
  6728. +       dc_printf("\tEx: A value of 2000 would result in lag streaks that last 2 seconds each\n\n");
  6729. +
  6730. +   dc_printf("lagloss\n");
  6731. +       dc_printf("\tDisplays this text. Passing --status will display the status of the entire lag system");
  6732.  }
  6733.  
  6734. -DCF(lag, "")
  6735. +DCF(lag, "Sets the lag base value (Muliplayer)")
  6736.  {
  6737. +   int value;
  6738. +
  6739.     // if the lag system isn't inited, don't do anything
  6740.     if(!Multi_lag_inited){
  6741.         dc_printf("Lag System Not Initialized!\n");
  6742.         return;
  6743.     }
  6744.  
  6745. -   dc_get_arg(ARG_INT);       
  6746. +   if (dc_optional_string_either("help", "--help")) {
  6747. +       multi_lagloss_dcf();
  6748. +       return;
  6749. +   }
  6750. +
  6751. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6752. +       dc_printf("Lag base value is currently %i\n", Multi_lag_base);
  6753. +       return;
  6754. +   }
  6755. +
  6756. +   dc_stuff_int(&value);
  6757.     // parse the argument and change things around accordingly
  6758. -   if(Dc_arg_type & ARG_INT){         
  6759. -       if(Dc_arg_int < 0){
  6760. -           // switch the lag sim off
  6761. -           Multi_lag_base = -1;
  6762. -           Multi_lag_min = -1;
  6763. -           Multi_lag_max = -1;
  6764. -           dc_printf("Turning simulated lag off\n");
  6765. -           multi_lagloss_dcf();
  6766. -       } else if((Multi_lag_max >= 0) && (Dc_arg_int > Multi_lag_max)){
  6767. -           dc_printf("Base value greater than max value, ignoring...");
  6768. -       } else if((Multi_lag_min >= 0) && (Dc_arg_int < Multi_lag_min)){
  6769. -           dc_printf("Base value smaller than min value, ignoring...");
  6770. -       } else {
  6771. -           Multi_lag_base = Dc_arg_int;
  6772. -           multi_lagloss_dcf();
  6773. -       }
  6774. -   }  
  6775. +   if (value < 0) {
  6776. +       // switch the lag sim off
  6777. +       Multi_lag_base = -1;
  6778. +       Multi_lag_min = -1;
  6779. +       Multi_lag_max = -1;
  6780. +       dc_printf("Turning simulated lag off\n");
  6781. +       multi_lagloss_dcf();
  6782. +
  6783. +   } else if ((Multi_lag_max >= 0) && (value > Multi_lag_max)) {
  6784. +       dc_printf("Base value greater than max value, ignoring...");
  6785. +
  6786. +   } else if ((Multi_lag_min >= 0) && (value < Multi_lag_min)) {
  6787. +       dc_printf("Base value smaller than min value, ignoring...");
  6788. +
  6789. +   } else {
  6790. +
  6791. +       Multi_lag_base = value;
  6792. +       multi_lagloss_dcf();
  6793. +       dc_printf("Base value set to %i", value);
  6794. +   }
  6795.  }
  6796.  
  6797. -DCF(lag_min, "")
  6798. +DCF(lag_min, "Sets the lag min value (Multiplayer)")
  6799.  {
  6800. +   int value;
  6801. +
  6802.     // if the lag system isn't inited, don't do anything
  6803.     if(!Multi_lag_inited){
  6804.         dc_printf("Lag System Not Initialized!\n");
  6805.         return;
  6806.     }
  6807.  
  6808. -   dc_get_arg(ARG_INT);       
  6809. +   if (dc_optional_string_either("help", "--help")) {
  6810. +       multi_lagloss_dcf();
  6811. +   }
  6812. +
  6813. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6814. +       dc_printf("Lag min value is currently %i\n", Multi_lag_min);
  6815. +   }
  6816. +
  6817. +   dc_stuff_int(&value);
  6818.     // parse the argument and change things around accordingly
  6819. -   if(Dc_arg_type & ARG_INT){         
  6820. -       if(Dc_arg_int > Multi_lag_base){
  6821. -           dc_printf("Min value greater than base value, ignoring...");
  6822. -       } else {
  6823. -           if(Dc_arg_int < 0){
  6824. -               Multi_lag_min = -1;
  6825. -           } else {
  6826. -               Multi_lag_min = Dc_arg_int;
  6827. -           }
  6828. -           multi_lagloss_dcf();
  6829. -       }
  6830. -   }          
  6831. +  
  6832. +   if (value > Multi_lag_base) {
  6833. +       dc_printf("Min value greater than base value, ignoring...");
  6834. +       return;
  6835. +
  6836. +   } else if (value < 0) {
  6837. +       Multi_lag_min = -1;
  6838. +
  6839. +   } else {
  6840. +       Multi_lag_min = value;
  6841. +   }
  6842. +   dc_printf("Lag min value set to %i\n", Multi_lag_min);
  6843.  }
  6844.  
  6845. -DCF(lag_max, "")
  6846. +DCF(lag_max, "Sets the lag max value (Multiplayer)")
  6847.  {
  6848. +   int value;
  6849. +
  6850.     // if the lag system isn't inited, don't do anything
  6851. -   if(!Multi_lag_inited){
  6852. +   if (!Multi_lag_inited) {
  6853.         dc_printf("Lag System Not Initialized!\n");
  6854.         return;
  6855.     }
  6856.  
  6857. +   if (dc_optional_string_either("help", "--help")) {
  6858. +       multi_lagloss_dcf();
  6859. +       return;
  6860. +   }
  6861. +
  6862. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6863. +       dc_printf("Lag max value is currently %i\n", Multi_lag_max);
  6864. +       return;
  6865. +   }
  6866. +
  6867.     // parse the argument and change things around accordingly
  6868. -   dc_get_arg(ARG_INT);
  6869. -   if(Dc_arg_type & ARG_INT){         
  6870. -       if((Dc_arg >=0) && (Dc_arg_int < Multi_lag_base)){
  6871. -           dc_printf("Max value smaller than base value, ignoring...");
  6872. -       } else {
  6873. -           if(Dc_arg_int < 0){
  6874. -               Multi_lag_max = -1;
  6875. -           } else {
  6876. -               Multi_lag_max = Dc_arg_int;
  6877. -           }
  6878. -           multi_lagloss_dcf();
  6879. -       }
  6880. -   }      
  6881. +   dc_stuff_int(&value);
  6882. +  
  6883. +   if ((value >= 0) && (value < Multi_lag_base)) {
  6884. +       dc_printf("Max value smaller than base value, ignoring...");
  6885. +
  6886. +   } else if (value < 0) {
  6887. +       Multi_lag_max = -1;
  6888. +
  6889. +   } else {
  6890. +       Multi_lag_max = value;
  6891. +   }
  6892. +   dc_printf("Lag max value set to %i\n", Multi_lag_max);
  6893.  }
  6894.  
  6895. -DCF(loss, "")
  6896. +DCF(loss, "Sets the loss base value (Multiplayer)")
  6897.  {
  6898. +   int val_i;
  6899. +   float val_f;
  6900. +
  6901.     // if the lag system isn't inited, don't do anything
  6902.     if(!Multi_lag_inited){
  6903.         dc_printf("Lag System Not Initialized!\n");
  6904.         return;
  6905.     }
  6906.  
  6907. +       if (dc_optional_string_either("help", "--help")) {
  6908. +       multi_lagloss_dcf();
  6909. +       return;
  6910. +   }
  6911. +
  6912. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6913. +       dc_printf("Loss value is currently %i percent", Multi_loss_base);
  6914. +       return;
  6915. +   }
  6916. +
  6917.     // parse the argument and change things around accordingly
  6918. -   dc_get_arg(ARG_INT);
  6919. -   if(Dc_arg_type & ARG_INT){
  6920. -       float val = (float)Dc_arg_int / 100.0f;
  6921. -          
  6922. -       if(Dc_arg_int > 100){
  6923. -           dc_printf("Illegal loss base value, ignoring...");
  6924. -       } else if(Dc_arg_int < 0){
  6925. -           // switch the loss sim off
  6926. -           dc_printf("Turning simulated loss off\n");
  6927. -           Multi_loss_base = -1.0f;
  6928. -           Multi_loss_min = -1.0f;
  6929. -           Multi_loss_max = -1.0f;
  6930. -           multi_lagloss_dcf();
  6931. -       } else if((Multi_loss_max >= 0.0f) && (val > Multi_loss_max)){
  6932. -           dc_printf("Base value greater than max value, ignoring...");
  6933. -       } else if((Multi_loss_min >= 0.0f) && (val < Multi_loss_min)){
  6934. -           dc_printf("Base value smaller than min value, ignoring...");
  6935. -       } else {
  6936. -           Multi_loss_base = val;
  6937. -           multi_lagloss_dcf();
  6938. -       }
  6939. -   }          
  6940. +   dc_stuff_int(&val_i);
  6941. +
  6942. +   val_f = (float)val_i / 100.0f;
  6943. +      
  6944. +   if(val_i > 100){
  6945. +       dc_printf("Illegal loss base value, ignoring...");
  6946. +   } else if (val_i < 0){
  6947. +       // switch the loss sim off
  6948. +       dc_printf("Turning simulated loss off\n");
  6949. +       Multi_loss_base = -1.0f;
  6950. +       Multi_loss_min = -1.0f;
  6951. +       Multi_loss_max = -1.0f;
  6952. +
  6953. +   } else if((Multi_loss_max >= 0.0f) && (val_f > Multi_loss_max)){
  6954. +       dc_printf("Base value greater than max value, ignoring...");
  6955. +
  6956. +   } else if((Multi_loss_min >= 0.0f) && (val_f < Multi_loss_min)){
  6957. +       dc_printf("Base value smaller than min value, ignoring...");
  6958. +
  6959. +   } else {
  6960. +       Multi_loss_base = val_f;
  6961. +   }
  6962.  }
  6963.  
  6964. -DCF(loss_min, "")
  6965. +DCF(loss_min, "Sets the loss min value (Multiplayer)")
  6966.  {
  6967. +   int val_i;
  6968. +   float val_f;
  6969. +
  6970.     // if the lag system isn't inited, don't do anything
  6971.     if(!Multi_lag_inited){
  6972.         dc_printf("Lag System Not Initialized!\n");
  6973.         return;
  6974.     }
  6975.  
  6976. +   if (dc_optional_string_either("help", "--help")) {
  6977. +       multi_lagloss_dcf();
  6978. +       return;
  6979. +   }
  6980. +
  6981. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  6982. +       dc_printf("loss_min value is currently %f percent", Multi_loss_min);
  6983. +   }
  6984. +
  6985.     // parse the argument and change things around accordingly
  6986. -   dc_get_arg(ARG_INT);
  6987. -   if(Dc_arg_type & ARG_INT){         
  6988. -      float val = (float)Dc_arg_int / 100.0f;
  6989. +   dc_stuff_int(&val_i);
  6990. +
  6991. +   val_f = (float)val_i / 100.0f;
  6992.  
  6993. -       if(val > Multi_loss_base){
  6994. -           dc_printf("Min value greater than base value, ignoring...");
  6995. +   if(val_f > Multi_loss_base){
  6996. +       dc_printf("Min value greater than base value, ignoring...");
  6997. +   } else {
  6998. +       // otherwise set the value
  6999. +       if (val_f < 0) {
  7000. +           Multi_loss_min = -1.0f;
  7001.         } else {
  7002. -           // otherwise set the value
  7003. -           if(Dc_arg_int < 0){
  7004. -               Multi_loss_min = -1.0f;
  7005. -           } else {
  7006. -               Multi_loss_min = val;
  7007. -           }
  7008. -           multi_lagloss_dcf();
  7009. +           Multi_loss_min = val_f;
  7010.         }
  7011.     }
  7012.  }
  7013.  
  7014. -DCF(loss_max, "")
  7015. -{ 
  7016. +DCF(loss_max, "Sets the loss max value (Multiplayer)")
  7017. +{
  7018. +   int val_i;
  7019. +   float val_f;
  7020.     // if the lag system isn't inited, don't do anything
  7021.     if(!Multi_lag_inited){
  7022.         dc_printf("Lag System Not Initialized!\n");
  7023.         return;
  7024.     }
  7025.  
  7026. +   if (dc_optional_string_either("help", "--help")) {
  7027. +       multi_lagloss_dcf();
  7028. +       return;
  7029. +   }
  7030. +
  7031. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  7032. +       dc_printf("loss_max value is currently %f percent", Multi_loss_max);
  7033. +   }
  7034. +
  7035.     // parse the argument and change things around accordingly
  7036. -   dc_get_arg(ARG_INT);
  7037. -   if(Dc_arg_type & ARG_INT){         
  7038. -      float val = (float)Dc_arg_int / 100.0f;
  7039. +   dc_stuff_int(&val_i);
  7040. +   val_f = (float)val_i / 100.0f;
  7041.  
  7042. -       if(val < Multi_loss_base){
  7043. -           dc_printf("Max value smaller than base value, ignoring...");
  7044. +   if (val_f < Multi_loss_base) {
  7045. +       dc_printf("Max value smaller than base value, ignoring...");
  7046. +   } else {
  7047. +       // otherwise set the value
  7048. +       if (val_f < 0) {
  7049. +           Multi_loss_max = -1.0f;
  7050.         } else {
  7051. -           // otherwise set the value
  7052. -           if(Dc_arg_int < 0){
  7053. -               Multi_loss_max = -1.0f;
  7054. -           } else {
  7055. -               Multi_loss_min = val;
  7056. -           }
  7057. -           multi_lagloss_dcf();
  7058. +           Multi_loss_max = val_f;
  7059.         }
  7060. -   }          
  7061. +   }
  7062.  }
  7063.  
  7064. -DCF(lagloss, "")
  7065. +DCF(lagloss, "Help provider for the lag system (Multiplayer)")
  7066.  {
  7067.     // if the lag system isn't inited, don't do anything
  7068.     if(!Multi_lag_inited){
  7069. @@ -587,29 +696,46 @@ DCF(lagloss, "")
  7070.     multi_lagloss_dcf();
  7071.  }
  7072.  
  7073. -DCF(lag_streak, "")
  7074. +DCF(lag_streak, "Sets the duration of lag streaks (Multiplayer)")
  7075.  {
  7076. +   int val;
  7077. +
  7078.     // if the lag system isn't inited, don't do anything
  7079. -   if(!Multi_lag_inited){
  7080. +   if (!Multi_lag_inited) {
  7081.         dc_printf("Lag System Not Initialized!\n");
  7082.         return;
  7083.     }
  7084.  
  7085. -   dc_get_arg(ARG_INT);
  7086. -   if(Dc_arg_type & ARG_INT){                     
  7087. -       if(Dc_arg_int >= 0){
  7088. -           Multi_streak_time = Dc_arg_int;
  7089. -       }
  7090. +   if (dc_optional_string_either("help", "--help")) {
  7091. +       multi_lagloss_dcf();
  7092. +       return;
  7093. +   }
  7094. +
  7095. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  7096. +       dc_printf("lag_streak value is currently %i", Multi_streak_time);
  7097. +       return;
  7098. +   }
  7099. +
  7100. +   dc_stuff_int(&val);
  7101. +   if(val >= 0){
  7102. +       Multi_streak_time = val;
  7103. +   } else {
  7104. +       dc_printf("Ignoring invalid value (must be non-negative)\n");
  7105.     }
  7106.  }
  7107.  
  7108. -DCF(lag_bad, "")
  7109. +DCF(lag_bad, "Lag system shortcut - Sets for 'bad' lag simulation (Multiplayer)")
  7110.  {
  7111.     // if the lag system isn't inited, don't do anything
  7112.     if(!Multi_lag_inited){
  7113.         dc_printf("Lag System Not Initialized!\n");
  7114.         return;
  7115.     }
  7116. +  
  7117. +   if (dc_optional_string_either("help", "--help")) {
  7118. +       multi_lagloss_dcf();
  7119. +       return;
  7120. +   }
  7121.  
  7122.     dc_printf("Setting bad lag/loss parameters\n");
  7123.  
  7124. @@ -627,7 +753,7 @@ DCF(lag_bad, "")
  7125.     Multi_current_streak = -1;
  7126.  }
  7127.  
  7128. -DCF(lag_avg, "")
  7129. +DCF(lag_avg, "Lag system shortcut - Sets for 'average' lag simulation (Multiplayer)")
  7130.  {
  7131.     // if the lag system isn't inited, don't do anything
  7132.     if(!Multi_lag_inited){
  7133. @@ -635,6 +761,11 @@ DCF(lag_avg, "")
  7134.         return;
  7135.     }
  7136.  
  7137. +   if (dc_optional_string_either("help", "--help")) {
  7138. +       multi_lagloss_dcf();
  7139. +       return;
  7140. +   }
  7141. +
  7142.     dc_printf("Setting avg lag/loss parameters\n");
  7143.  
  7144.     // set good lagloss parameters
  7145. @@ -651,7 +782,7 @@ DCF(lag_avg, "")
  7146.     Multi_current_streak = -1;
  7147.  }
  7148.  
  7149. -DCF(lag_good, "")
  7150. +DCF(lag_good, "Lag system shortcut - Sets for 'good' lag simulation (Multiplayer)")
  7151.  {
  7152.     // if the lag system isn't inited, don't do anything
  7153.     if(!Multi_lag_inited){
  7154. @@ -659,6 +790,11 @@ DCF(lag_good, "")
  7155.         return;
  7156.     }
  7157.  
  7158. +   if (dc_optional_string_either("help", "--help")) {
  7159. +       multi_lagloss_dcf();
  7160. +       return;
  7161. +   }
  7162. +
  7163.     dc_printf("Setting good lag/loss parameters\n");
  7164.  
  7165.     // set good lagloss parameters
  7166. diff --git a/code/network/multiui.cpp b/code/network/multiui.cpp
  7167. index ba601d9..9f28f47 100644
  7168. --- a/code/network/multiui.cpp
  7169. +++ b/code/network/multiui.cpp
  7170. @@ -64,6 +64,7 @@
  7171.  #include "cfile/cfile.h"
  7172.  #include "fs2netd/fs2netd_client.h"
  7173.  #include "menuui/mainhallmenu.h"
  7174. +#include "debugconsole/console.h"
  7175.  
  7176.  #include <algorithm>
  7177.  
  7178. @@ -754,13 +755,20 @@ int multi_join_maybe_warn();
  7179.  int multi_join_warn_pxo();
  7180.  void multi_join_blit_protocol();
  7181.  
  7182. -DCF(mj_make, "")
  7183. +DCF(mj_make, "Makes a multijoin game? (Multiplayer)")
  7184.  {
  7185.     active_game ag, *newitem;
  7186.     int idx;
  7187. +   int idx_max;
  7188.  
  7189. -   dc_get_arg(ARG_INT);
  7190. -   for(idx=0; idx<Dc_arg_int; idx++){
  7191. +   if (dc_optional_string_either("help", "--help")) {
  7192. +       dc_printf("Usage: mj_make <num_games>\n");
  7193. +       return;
  7194. +   }
  7195. +
  7196. +   dc_stuff_int(&idx_max);
  7197. +
  7198. +   for(idx = 0; idx < idx_max; idx++){
  7199.         // stuff some fake info
  7200.         memset(&ag, 0, sizeof(active_game));
  7201.         sprintf(ag.name, "Game %d", idx);
  7202. @@ -776,7 +784,7 @@ DCF(mj_make, "")
  7203.         if(newitem != NULL){
  7204.             // newitem->heard_from_timer = timestamp((int)frand_range(500.0f, 10000.0f));
  7205.         }
  7206. -   }  
  7207. +   }
  7208.  }
  7209.  
  7210.  void multi_join_notify_new_game()
  7211. diff --git a/code/network/multiutil.cpp b/code/network/multiutil.cpp
  7212. index fb05620..05f817f 100644
  7213. --- a/code/network/multiutil.cpp
  7214. +++ b/code/network/multiutil.cpp
  7215. @@ -77,6 +77,7 @@
  7216.  #include "network/multi_rate.h"
  7217.  #include "fs2netd/fs2netd_client.h"
  7218.  #include "parse/parselo.h"
  7219. +#include "debugconsole/console.h"
  7220.  
  7221.  extern int ascii_table[];
  7222.  extern int shifted_ascii_table[];
  7223. @@ -3198,65 +3199,73 @@ short multi_get_new_id()
  7224.  // ------------------------------------
  7225.  
  7226.  //XSTR:OFF
  7227. -DCF(multi,"changes multiplayer settings")
  7228. +DCF(multi,"changes multiplayer settings (Multiplayer)")
  7229.  {
  7230. -   if(Dc_command){
  7231. -       dc_get_arg(ARG_STRING);
  7232. -      
  7233. -       if(strcmp(Dc_arg, "kick")==0){              // kick a player
  7234. -           multi_dcf_kick();
  7235. +   if (dc_optional_string("kick")) {
  7236. +       // kick a player
  7237. +       multi_dcf_kick();
  7238. +
  7239.  #ifndef NDEBUG
  7240. -       } else if(strcmp(Dc_arg, "stats")==0) {
  7241. -           // multi_toggle_stats();
  7242. -       } else if(strcmp(Dc_arg, "show_stats")==0) {
  7243. -           // multi_show_basic_stats(0);
  7244. -       } else if(strcmp(Dc_arg, "dump_stats")==0) {
  7245. -           // multi_show_basic_stats(1);
  7246. +   } else if (dc_optional_string("stats")) {
  7247. +       // multi_toggle_stats();
  7248. +
  7249. +   } else if (dc_optional_string("show_stats")) {
  7250. +       // multi_show_basic_stats(0);
  7251. +
  7252. +   } else if (dc_optional_string("dump_stats")) {
  7253. +       // multi_show_basic_stats(1);
  7254.  #endif
  7255. -       } else if(strcmp(Dc_arg, "voice")==0){              // settings for multiplayer voice
  7256. -           multi_voice_dcf();
  7257. -       } else if(strcmp(Dc_arg, "respawn_chump")==0){  // set a really large # of respawns
  7258. -           if((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_GAME_HOST)){          
  7259. -               Netgame.respawn = 9999;
  7260. -               Netgame.options.respawn = 9999;            
  7261. -
  7262. -               // if i'm the server, send a netgame update
  7263. -               if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
  7264. -                   send_netgame_update_packet();
  7265. -               }
  7266. -           }
  7267. -       } else if(strcmp(Dc_arg, "ss_leaders")==0){     // only host or team captains can modify ships
  7268. -           if((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_GAME_HOST)){          
  7269. -               Netgame.options.flags |= MSO_FLAG_SS_LEADERS;
  7270. -               multi_options_update_netgame();
  7271. -           }
  7272. -       } else if(strcmp(Dc_arg, "make_players")==0){
  7273. +
  7274. +   } else if (dc_optional_string("voice")) {
  7275. +       // settings for multiplayer voice
  7276. +       multi_voice_dcf();
  7277. +
  7278. +   } else if (dc_optional_string("respawn_chump")){
  7279. +       // set a really large # of respawns
  7280. +       if((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_GAME_HOST)) {
  7281. +           Netgame.respawn = 9999;
  7282. +           Netgame.options.respawn = 9999;
  7283. +
  7284. +           // if i'm the server, send a netgame update
  7285. +           if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
  7286. +               send_netgame_update_packet();
  7287. +           }
  7288. +       }
  7289. +
  7290. +   } else if (dc_optional_string("ss_leaders")) {
  7291. +       // only host or team captains can modify ships
  7292. +       if((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_GAME_HOST)) {
  7293. +           Netgame.options.flags |= MSO_FLAG_SS_LEADERS;
  7294. +           multi_options_update_netgame();
  7295. +       }
  7296. +
  7297. +   } else if (dc_optional_string("make_players")) {
  7298.  #ifndef NDEBUG
  7299. -           multi_make_fake_players(MAX_PLAYERS);
  7300. +       multi_make_fake_players(MAX_PLAYERS);
  7301.  #endif
  7302. -       } else if(strcmp(Dc_arg, "givecd")==0){
  7303. -           extern int Multi_has_cd;
  7304. -           Multi_has_cd = 1;
  7305. -       } else if(strcmp(Dc_arg, "oo")==0){                    
  7306. -           int new_flags = -1;
  7307. -
  7308. -           dc_get_arg(ARG_INT);
  7309. -           if(Dc_arg_type & ARG_INT){
  7310. -               new_flags = Dc_arg_int;
  7311. -           }
  7312.  
  7313. -           dc_printf("Interesting flags\nPos : %d\nVelocity : %d\nDesired vel : %d\nOrient : %d\nRotvel : %d\nDesired rotvel %d\n",
  7314. -                        1<<0, 1<<7, 1<<8, 1<<1, 1<<9, 1<<10);                     
  7315. -       } else if(strcmp(Dc_arg, "oo_sort")==0){           
  7316. -           extern int OO_sort;
  7317. +   } else if (dc_optional_string("givecd")) {
  7318. +       extern int Multi_has_cd;
  7319. +       Multi_has_cd = 1;
  7320.  
  7321. -           OO_sort = !OO_sort;
  7322. -           if(OO_sort){
  7323. -               dc_printf("Network object sorting ENABLED\n");
  7324. -           } else {
  7325. -               dc_printf("Network object sorting DISABLED\n");
  7326. -           }
  7327. -       }
  7328. +   } else if (dc_optional_string("oo")) {
  7329. +       int new_flags = -1;
  7330. +
  7331. +       dc_maybe_stuff_int(&new_flags);
  7332. +
  7333. +       dc_printf("Interesting flags\n");
  7334. +       dc_printf("Pos : %d\n", 1 << 0);
  7335. +       dc_printf("Velocity    : %d\n", 1 << 7);
  7336. +       dc_printf("Desired vel : %d\n", 1 << 8);
  7337. +       dc_printf("Orient : %d\n", 1 << 1);
  7338. +       dc_printf("Rotvel : %d\n", 1 << 9);
  7339. +       dc_printf("Desired rotvel : %d\n", 1 << 10);
  7340. +
  7341. +   } else if (dc_optional_string("oo_sort")) {
  7342. +       extern int OO_sort;
  7343. +
  7344. +       OO_sort = !OO_sort;
  7345. +       dc_printf("Network object sorting %s\n", OO_sort ? "ENABLED" : "DISABLED");
  7346.     }
  7347.  }
  7348.  
  7349. @@ -3447,19 +3456,20 @@ Done:
  7350.  }
  7351.  */
  7352.  
  7353. -DCF(pxospew,"spew PXO 32 bit checksums for all visible mission files")
  7354. +DCF(pxospew,"spew PXO 32 bit checksums for all visible mission files (Multiplayer)")
  7355.  {
  7356.     int max_files;
  7357. +   char file_str[MAX_NAME_LEN];
  7358.  
  7359. -   dc_get_arg(ARG_INT);
  7360. -   if(Dc_arg_type & ARG_INT){
  7361. -       max_files = Dc_arg_int;
  7362. -
  7363. -       dc_get_arg(ARG_STRING);
  7364. -       if(Dc_arg_type & ARG_STRING){
  7365. -           multi_spew_pxo_checksums(max_files, Dc_arg);
  7366. -       }
  7367. +   if (dc_optional_string_either("help", "--help")) {
  7368. +       dc_printf("Usage: pxospew <max_files> <filename>\n");
  7369. +       return;
  7370.     }
  7371. +
  7372. +   dc_stuff_int(&max_files);
  7373. +   dc_stuff_string_white(file_str, MAX_NAME_LEN);
  7374. +
  7375. +   multi_spew_pxo_checksums(max_files, file_str);
  7376.  }
  7377.  
  7378.  
  7379. diff --git a/code/object/collideshipship.cpp b/code/object/collideshipship.cpp
  7380. index d799ab1..009548a 100644
  7381. --- a/code/object/collideshipship.cpp
  7382. +++ b/code/object/collideshipship.cpp
  7383. @@ -27,6 +27,7 @@
  7384.  #include "object/objectdock.h"
  7385.  #include "object/objectshield.h"
  7386.  #include "parse/scripting.h"
  7387. +#include "debugconsole/console.h"
  7388.  
  7389.  
  7390.  #define COLLIDE_DEBUG
  7391. diff --git a/code/object/object.cpp b/code/object/object.cpp
  7392. index 50b08e5..73fa7d0 100644
  7393. --- a/code/object/object.cpp
  7394. +++ b/code/object/object.cpp
  7395. @@ -41,6 +41,7 @@
  7396.  #include "weapon/shockwave.h"
  7397.  #include "weapon/swarm.h"
  7398.  #include "weapon/weapon.h"
  7399. +#include "debugconsole/console.h"
  7400.  
  7401.  
  7402.  
  7403. diff --git a/code/object/objectsnd.cpp b/code/object/objectsnd.cpp
  7404. index 498517c..64c3270 100644
  7405. --- a/code/object/objectsnd.cpp
  7406. +++ b/code/object/objectsnd.cpp
  7407. @@ -22,7 +22,7 @@
  7408.  #include "render/3d.h"
  7409.  #include "io/joy_ff.h"
  7410.  #include "species_defs/species_defs.h"
  7411. -
  7412. +#include "debugconsole/console.h"
  7413.  
  7414.  
  7415.  //  // --mharris port hack--
  7416. @@ -96,62 +96,65 @@ void obj_snd_source_pos(vec3d *sound_pos, obj_snd *osp)
  7417.  //XSTR:OFF
  7418.  DCF(objsnd, "Persistent sound stuff" )
  7419.  {
  7420. -   char        buf1[16], buf2[64];
  7421. -   obj_snd *osp;
  7422. +   char buf1[4];
  7423. +   char buf2[MAX_NAME_LEN];
  7424. +   obj_snd *osp;
  7425. +   SCP_string arg;
  7426. +
  7427. +   if (dc_optional_string_either("help", "--help")) {
  7428. +       dc_printf ("Usage: objsnd [-list]\n");
  7429. +       dc_printf ("[-list] --  displays status of all objects with linked sounds\n");
  7430. +       dc_printf ("with no parameters, object sounds are toggled on/off\n");
  7431. +       return;
  7432. +   }
  7433.  
  7434. -   if ( Dc_command )   {
  7435. -       dc_get_arg(ARG_STRING|ARG_NONE);
  7436. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  7437. +       dc_printf( "Object sounds are: %s\n", (Obj_snd_enabled?"ON":"OFF") );
  7438. +   }
  7439. +  
  7440. +   if (dc_optional_string("-list")) {
  7441. +       for ( osp = GET_FIRST(&obj_snd_list); osp !=END_OF_LIST(&obj_snd_list); osp = GET_NEXT(osp) ) {
  7442. +           vec3d source_pos;
  7443. +           float distance;
  7444.  
  7445. -       if ( Dc_arg_type & ARG_NONE ) {
  7446. -           if ( Obj_snd_enabled == TRUE ) {
  7447. -               obj_snd_stop_all();
  7448. -               Obj_snd_enabled = FALSE;
  7449. +           Assert(osp != NULL);
  7450. +           if ( osp->instance == -1 ) {
  7451. +               continue;
  7452. +               //sprintf(buf1,"OFF");
  7453. +           } else {
  7454. +               sprintf(buf1,"ON");
  7455. +           }
  7456. +
  7457. +           if ( Objects[osp->objnum].type == OBJ_SHIP ) {
  7458. +               strcpy_s(buf2, Ships[Objects[osp->objnum].instance].ship_name);
  7459. +           }
  7460. +           else if ( Objects[osp->objnum].type == OBJ_DEBRIS ) {
  7461. +               sprintf(buf2, "Debris");
  7462.             }
  7463.             else {
  7464. -               Obj_snd_enabled = TRUE;
  7465. +               sprintf(buf2, "Unknown");
  7466.             }
  7467. -       }
  7468. -       if ( !stricmp( Dc_arg, "list" ))    {
  7469. -           for ( osp = GET_FIRST(&obj_snd_list); osp !=END_OF_LIST(&obj_snd_list); osp = GET_NEXT(osp) ) {
  7470. -               Assert(osp != NULL);
  7471. -               if ( osp->instance == -1 ) {
  7472. -                   continue;
  7473. -                   //sprintf(buf1,"OFF");
  7474. -               } else {
  7475. -                   sprintf(buf1,"ON");
  7476. -               }
  7477.  
  7478. -               if ( Objects[osp->objnum].type == OBJ_SHIP ) {
  7479. -                   strcpy_s(buf2, Ships[Objects[osp->objnum].instance].ship_name);
  7480. -               }
  7481. -               else if ( Objects[osp->objnum].type == OBJ_DEBRIS ) {
  7482. -                   sprintf(buf2, "Debris");
  7483. -               }
  7484. -               else {
  7485. -                   sprintf(buf2, "Unknown");
  7486. -               }
  7487. +           obj_snd_source_pos(&source_pos, osp);
  7488. +           distance = vm_vec_dist_quick( &source_pos, &View_position );
  7489.  
  7490. -               vec3d source_pos;
  7491. -               float distance;
  7492. -
  7493. -               obj_snd_source_pos(&source_pos, osp);
  7494. -               distance = vm_vec_dist_quick( &source_pos, &View_position );
  7495. -
  7496. -               dc_printf("Object %d => name: %s vol: %.2f pan: %.2f dist: %.2f status: %s\n", osp->objnum, buf2, osp->vol, osp->pan, distance, buf1);
  7497. -           } // end for
  7498. -               dc_printf("Number object-linked sounds playing: %d\n", Num_obj_sounds_playing);
  7499. -       }
  7500. -   }
  7501. +           dc_printf("Object %d => name: %s vol: %.2f pan: %.2f dist: %.2f status: %s\n", osp->objnum, buf2, osp->vol, osp->pan, distance, buf1);
  7502. +       } // end for
  7503.  
  7504. -   if ( Dc_help ) {
  7505. -       dc_printf ("Usage: objsnd [list]\n");
  7506. -       dc_printf ("[list] --  displays status of all objects with linked sounds\n");
  7507. -       dc_printf ("with no parameters, object sounds are toggled on/off\n");
  7508. -       Dc_status = 0;
  7509. +       dc_printf("Number object-linked sounds playing: %d\n", Num_obj_sounds_playing);
  7510. +       return;
  7511.     }
  7512.  
  7513. -   if ( Dc_status )    {
  7514. -       dc_printf( "Object sounds are: %s\n", (Obj_snd_enabled?"ON":"OFF") );
  7515. +   if (!dc_maybe_stuff_string_white(arg)) {
  7516. +       // No arguments, toggle snd on/off
  7517. +       if ( Obj_snd_enabled == TRUE ) {
  7518. +               obj_snd_stop_all();
  7519. +               Obj_snd_enabled = FALSE;
  7520. +           } else {
  7521. +               Obj_snd_enabled = TRUE;
  7522. +       }
  7523. +   } else {
  7524. +       dc_printf("Unknown argument '%s'\n", arg.c_str());
  7525.     }
  7526.  }
  7527.  //XSTR:ON
  7528. diff --git a/code/palman/palman.cpp b/code/palman/palman.cpp
  7529. index cdb18ec..dee89aa 100644
  7530. --- a/code/palman/palman.cpp
  7531. +++ b/code/palman/palman.cpp
  7532. @@ -11,6 +11,7 @@
  7533.  
  7534.  #include "palman/palman.h"
  7535.  #include "bmpman/bmpman.h"
  7536. +#include "debugconsole/console.h"
  7537.  #include "pcxutils/pcxutils.h"
  7538.  #include "parse/parselo.h"
  7539.  #include "graphics/grinternal.h"
  7540. @@ -165,17 +166,14 @@ void palette_load_table( const char * filename )
  7541.  
  7542.  DCF(palette,"Loads a new palette")
  7543.  {
  7544. -   if ( Dc_command )   {
  7545. -       dc_get_arg(ARG_STRING|ARG_NONE);
  7546. -       if ( Dc_arg_type == ARG_NONE )  {
  7547. -       } else {
  7548. -           palette_load_table( Dc_arg );
  7549. -       }
  7550. -   }
  7551. -   if ( Dc_help )  {
  7552. -       dc_printf( "Usage: palette filename\nLoads the palette file.\n" );
  7553. +   char palette_file[MAX_FILENAME_LEN];
  7554. +
  7555. +   if (dc_optional_string_either("help", "--help")) {
  7556. +       dc_printf( "Usage: palette <filename>\nLoads the palette file.\n" );
  7557.     }
  7558.  
  7559. +   dc_stuff_string_white(palette_file, MAX_FILENAME_LEN);
  7560. +   palette_load_table(palette_file);
  7561.  }
  7562.  
  7563.  int Palman_allow_any_color = 0;
  7564. diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp
  7565. index 80514a7..5abf1ef 100644
  7566. --- a/code/parse/sexp.cpp
  7567. +++ b/code/parse/sexp.cpp
  7568. @@ -96,6 +96,7 @@
  7569.  #include "mod_table/mod_table.h"
  7570.  #include "ship/afterburner.h"
  7571.  #include "globalincs/alphacolors.h"
  7572. +#include "debugconsole/console.h"
  7573.  
  7574.  #ifndef NDEBUG
  7575.  #include "hud/hudmessage.h"
  7576. @@ -24558,40 +24559,38 @@ int run_sexp(const char* sexpression)
  7577.     return sexp_val;
  7578.  }
  7579.  
  7580. -DCF(sexpc, "Always runs the given sexp command ")
  7581. +DCF(sexpc, "Always runs the given sexp command (Warning! There is no undo for this!)")
  7582.  {
  7583. -   if ( Dc_command )       {
  7584. -       if (Dc_command_line != NULL) {
  7585. -           char buf[8192];
  7586. -           snprintf(buf, 8191, "( when ( true ) ( %s ) )", Dc_command_line);
  7587. -
  7588. -           int sexp_val = run_sexp( buf );
  7589. -           dc_printf("SEXP '%s' run, sexp_val = %d\n", buf, sexp_val);
  7590. -           do {
  7591. -               dc_get_arg(ARG_ANY);
  7592. -           } while (Dc_arg_type != ARG_NONE);
  7593. -       }
  7594. -   }
  7595. -   if ( Dc_help )  {
  7596. +   SCP_string sexp;
  7597. +   SCP_string sexp_always;
  7598. +  
  7599. +   if (dc_optional_string_either("help", "--help")) {
  7600.         dc_printf( "Usage: sexpc sexpression\n. Always runs the given sexp as '( when ( true ) ( sexp ) )' .\n" );
  7601. +       return;
  7602.     }
  7603. +
  7604. +   dc_stuff_string(sexp);
  7605. +
  7606. +   sprintf(sexp_always, "( when ( true ) ( %s ) )", sexp.c_str());
  7607. +
  7608. +   int sexp_val = run_sexp(sexp_always.c_str());
  7609. +   dc_printf("SEXP '%s' run, sexp_val = %d\n", sexp_always.c_str(), sexp_val);
  7610.  }
  7611.  
  7612.  
  7613.  DCF(sexp,"Runs the given sexp")
  7614.  {
  7615. -   if ( Dc_command )       {
  7616. -       if (Dc_command_line != NULL) {
  7617. -           int sexp_val = run_sexp( Dc_command_line );
  7618. -           dc_printf("SEXP '%s' run, sexp_val = %d\n", Dc_command_line, sexp_val);
  7619. -           do {
  7620. -               dc_get_arg(ARG_ANY);
  7621. -           } while (Dc_arg_type != ARG_NONE);
  7622. -       }
  7623. -   }
  7624. -   if ( Dc_help )  {
  7625. +   SCP_string sexp;
  7626. +
  7627. +   if (dc_optional_string_either("help", "--help")) {
  7628.         dc_printf( "Usage: sexp 'sexpression'\n. Runs the given sexp.\n");
  7629. +       return;
  7630.     }
  7631. +
  7632. +   dc_stuff_string(sexp);
  7633. +
  7634. +   int sexp_val = run_sexp(sexp.c_str());
  7635. +   dc_printf("SEXP '%s' run, sexp_val = %d\n", dc_command_str.c_str(), sexp_val);
  7636.  }
  7637.  
  7638.  
  7639. diff --git a/code/particle/particle.cpp b/code/particle/particle.cpp
  7640. index 22afb30..c28ef40 100644
  7641. --- a/code/particle/particle.cpp
  7642. +++ b/code/particle/particle.cpp
  7643. @@ -17,6 +17,7 @@
  7644.  #include "object/object.h"
  7645.  #include "cmdline/cmdline.h"
  7646.  #include "graphics/grbatch.h"
  7647. +#include "debugconsole/console.h"
  7648.  
  7649.  #ifndef NDEBUG
  7650.  #include "io/timer.h"
  7651. @@ -90,18 +91,7 @@ void particle_page_in()
  7652.     bm_page_in_texture( Anim_bitmap_id_smoke2 );
  7653.  }
  7654.  
  7655. -DCF(particles,"Turns particles on/off")
  7656. -{
  7657. -   if ( Dc_command )   {  
  7658. -       dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);       
  7659. -       if ( Dc_arg_type & ARG_TRUE )   Particles_enabled = 1
  7660. -       else if ( Dc_arg_type & ARG_FALSE ) Particles_enabled = 0
  7661. -       else if ( Dc_arg_type & ARG_NONE ) Particles_enabled ^= 1
  7662. -   }  
  7663. -   if ( Dc_help )  dc_printf( "Usage: particles [bool]\nTurns particle system on/off.  If nothing passed, then toggles it.\n" );  
  7664. -   if ( Dc_status )    dc_printf( "particles are %s\n", (Particles_enabled?"ON":"OFF") )
  7665. -}
  7666. -
  7667. +DCF_BOOL2(particles, Particles_enabled, "Turns particles on/off", "Usage: particles [bool]\nTurns particle system on/off.  If nothing passed, then toggles it.\n");
  7668.  
  7669.  int Num_particles_hwm = 0;
  7670.  
  7671. diff --git a/code/playerman/playercontrol.cpp b/code/playerman/playercontrol.cpp
  7672. index 6eebd3f..60b65a8 100644
  7673. --- a/code/playerman/playercontrol.cpp
  7674. +++ b/code/playerman/playercontrol.cpp
  7675. @@ -34,6 +34,7 @@
  7676.  #include "network/multiutil.h"
  7677.  #include "network/multi_obj.h"
  7678.  #include "parse/parselo.h"
  7679. +#include "debugconsole/console.h"
  7680.  
  7681.  #ifndef NDEBUG
  7682.  #include "io/key.h"
  7683. @@ -286,10 +287,16 @@ void do_view_chase(float frame_time)
  7684.  
  7685.  float camera_zoom_scale = 1.0f;
  7686.  
  7687. -DCF(camera_speed, "")
  7688. +DCF(camera_speed, "Sets the camera zoom scale")
  7689.  {
  7690. -   dc_get_arg(ARG_FLOAT);
  7691. -   camera_zoom_scale = Dc_arg_float;
  7692. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  7693. +       dc_printf("Camera zoom scale is %f\n", camera_zoom_scale);
  7694. +       return;
  7695. +   }
  7696. +
  7697. +   dc_stuff_float(&camera_zoom_scale);
  7698. +
  7699. +   dc_printf("Camera zoom scale set to %f\n", camera_zoom_scale);
  7700.  }
  7701.  
  7702.  void do_view_external(float frame_time)
  7703. diff --git a/code/radar/radarsetup.cpp b/code/radar/radarsetup.cpp
  7704. index b065092..a4e51d2 100644
  7705. --- a/code/radar/radarsetup.cpp
  7706. +++ b/code/radar/radarsetup.cpp
  7707. @@ -31,6 +31,7 @@
  7708.  #include "radar/radarsetup.h"
  7709.  #include "iff_defs/iff_defs.h"
  7710.  #include "globalincs/linklist.h"
  7711. +#include "debugconsole/console.h"
  7712.  
  7713.  int Radar_static_looping = -1;
  7714.  
  7715. @@ -84,7 +85,7 @@ extern int radar_iff_color[5][2][4];
  7716.  
  7717.  int See_all = 0;
  7718.  
  7719. -DCF_BOOL(see_all, See_all)
  7720. +DCF_BOOL(see_all, See_all);
  7721.  
  7722.  static const char radar_default_filenames[2][16]=
  7723.  {
  7724. diff --git a/code/render/3dlaser.cpp b/code/render/3dlaser.cpp
  7725. index 0a0156c..45e479a 100644
  7726. --- a/code/render/3dlaser.cpp
  7727. +++ b/code/render/3dlaser.cpp
  7728. @@ -14,6 +14,7 @@
  7729.  #include "globalincs/systemvars.h"
  7730.  #include "io/key.h"
  7731.  #include "cmdline/cmdline.h"
  7732. +#include "debugconsole/console.h"
  7733.  
  7734.  
  7735.  
  7736. diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp
  7737. index 4e081ce..0516cae 100644
  7738. --- a/code/ship/ship.cpp
  7739. +++ b/code/ship/ship.cpp
  7740. @@ -80,6 +80,7 @@
  7741.  #include "graphics/gropenglshader.h"
  7742.  #include "model/model.h"
  7743.  #include "mod_table/mod_table.h"
  7744. +#include "debugconsole/console.h"
  7745.  
  7746.  
  7747.  #define NUM_SHIP_SUBSYSTEM_SETS            20      // number of subobject sets to use (because of the fact that it's a linked list,
  7748. @@ -8356,10 +8357,14 @@ int ship_subsys_disrupted(ship *sp, int type)
  7749.  }
  7750.  
  7751.  float Decay_rate = 1.0f / 120.0f;
  7752. -DCF(lethality_decay, "time in sec to return from 100 to 0")
  7753. +DCF(lethality_decay, "Sets ship lethality_decay, or the time in sec to go from 100 to 0 health (default is 1/120)")
  7754.  {
  7755. -   dc_get_arg(ARG_FLOAT);
  7756. -   Decay_rate = Dc_arg_float;
  7757. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  7758. +       dc_printf("Decay rate is currently %f\n", Decay_rate);
  7759. +       return;
  7760. +   }
  7761. +  
  7762. +   dc_stuff_float(&Decay_rate);
  7763.  }
  7764.  
  7765.  float min_lethality = 0.0f;
  7766. @@ -9865,31 +9870,44 @@ float t_len = 10.0f;
  7767.  float t_vel = 0.2f;
  7768.  float t_min = 150.0f;
  7769.  float t_max = 300.0f;
  7770. -DCF(t_rad, "")
  7771. +DCF(t_rad, "Sets weapon tracer radius")
  7772.  {
  7773. -   dc_get_arg(ARG_FLOAT);
  7774. -   t_rad = Dc_arg_float;
  7775. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  7776. +       dc_printf("t_rad : %f\n", t_rad);
  7777. +       return;
  7778. +   }
  7779. +  
  7780. +   dc_stuff_float(&t_rad);
  7781.  }
  7782. -DCF(t_len, "")
  7783. +DCF(t_len, "Sets weapon tracer length")
  7784.  {
  7785. -   dc_get_arg(ARG_FLOAT);
  7786. -   t_len = Dc_arg_float;
  7787. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  7788. +       dc_printf("t_len : %f\n", t_len);
  7789. +       return;
  7790. +   }
  7791. +
  7792. +   dc_stuff_float(&t_len);
  7793.  }
  7794. -DCF(t_vel, "")
  7795. +DCF(t_vel, "Sets weapon tracer velocity")
  7796.  {
  7797. -   dc_get_arg(ARG_FLOAT);
  7798. -   t_vel = Dc_arg_float;
  7799. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  7800. +       dc_printf("t_vel : %f\n", t_vel);
  7801. +       return;
  7802. +   }
  7803. +
  7804. +   dc_stuff_float(&t_vel);
  7805.  }
  7806. +/*
  7807. + TODO: These two DCF's (and variables) are unused
  7808.  DCF(t_min, "")
  7809.  {
  7810. -   dc_get_arg(ARG_FLOAT);
  7811. -   t_min = Dc_arg_float;
  7812. +   dc_stuff_float(&t_min);
  7813.  }
  7814.  DCF(t_max, "")
  7815.  {
  7816. -   dc_get_arg(ARG_FLOAT);
  7817. -   t_max = Dc_arg_float;
  7818. +   dc_stuff_float(&t_max);
  7819.  }
  7820. +*/
  7821.  void ship_fire_tracer(int weapon_objnum)
  7822.  {
  7823.     particle_info pinfo;
  7824. @@ -13611,26 +13629,25 @@ void ship_assign_sound_all()
  7825.   */
  7826.  DCF(set_shield,"Change player ship shield strength")
  7827.  {
  7828. -   if ( Dc_command )   {
  7829. -       dc_get_arg(ARG_FLOAT|ARG_NONE);
  7830. -
  7831. -       if ( Dc_arg_type & ARG_FLOAT ) {
  7832. -            CLAMP(Dc_arg_float, 0.0f, 1.0f);
  7833. -           shield_set_strength(Player_obj, Dc_arg_float * Player_ship->ship_max_shield_strength);
  7834. -           dc_printf("Shields set to %.2f\n", shield_get_strength(Player_obj) );
  7835. -       }
  7836. -   }
  7837. +   float value;
  7838.  
  7839. -   if ( Dc_help ) {
  7840. +   if (dc_optional_string_either("help", "--help")) {
  7841.         dc_printf ("Usage: set_shield [num]\n");
  7842.         dc_printf ("[num] --  shield percentage 0.0 -> 1.0 of max\n");
  7843. -       dc_printf ("with no parameters, displays shield strength\n");
  7844. -       Dc_status = 0;
  7845. +       return;
  7846.     }
  7847.  
  7848. -   if ( Dc_status )    {
  7849. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  7850.         dc_printf( "Shields are currently %.2f", shield_get_strength(Player_obj) );
  7851. +       return;
  7852.     }
  7853. +
  7854. +   dc_stuff_float(&value);
  7855. +
  7856. +   CLAMP(value, 0.0f, 1.0f);
  7857. +
  7858. +   shield_set_strength(Player_obj, value * Player_ship->ship_max_shield_strength);
  7859. +   dc_printf("Shields set to %.2f\n", shield_get_strength(Player_obj) );
  7860.  }
  7861.  
  7862.  /**
  7863. @@ -13638,26 +13655,24 @@ DCF(set_shield,"Change player ship shield strength")
  7864.   */
  7865.  DCF(set_hull, "Change player ship hull strength")
  7866.  {
  7867. -   if ( Dc_command )   {
  7868. -       dc_get_arg(ARG_FLOAT|ARG_NONE);
  7869. -
  7870. -       if ( Dc_arg_type & ARG_FLOAT ) {
  7871. -           CLAMP(Dc_arg_float, 0.0f, 1.0f);
  7872. -           Player_obj->hull_strength = Dc_arg_float * Player_ship->ship_max_hull_strength;
  7873. -           dc_printf("Hull set to %.2f\n", Player_obj->hull_strength );
  7874. -       }
  7875. -   }
  7876. -
  7877. -   if ( Dc_help ) {
  7878. +   float value;
  7879. +  
  7880. +   if (dc_optional_string_either("help", "--help")) {
  7881.         dc_printf ("Usage: set_hull [num]\n");
  7882.         dc_printf ("[num] --  hull percentage 0.0 -> 1.0 of max\n");
  7883. -       dc_printf ("with no parameters, displays hull strength\n");
  7884. -       Dc_status = 0;
  7885. +       return;
  7886.     }
  7887.  
  7888. -   if ( Dc_status )    {
  7889. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  7890.         dc_printf( "Hull is currently %.2f", Player_obj->hull_strength );
  7891. +       return;
  7892.     }
  7893. +
  7894. +   dc_stuff_float(&value);
  7895. +
  7896. +   CLAMP(value, 0.0f, 1.0f);
  7897. +   Player_obj->hull_strength = value * Player_ship->ship_max_hull_strength;
  7898. +   dc_printf("Hull set to %.2f\n", Player_obj->hull_strength );
  7899.  }
  7900.  
  7901.  /**
  7902. @@ -13666,70 +13681,65 @@ DCF(set_hull, "Change player ship hull strength")
  7903.  //XSTR:OFF
  7904.  DCF(set_subsys, "Set the strength of a particular subsystem on player ship" )
  7905.  {
  7906. -   if ( Dc_command )   {
  7907. -       dc_get_arg(ARG_STRING);
  7908. -       if ( !subsystem_stricmp( Dc_arg, "weapons" ))   {
  7909. -           dc_get_arg(ARG_FLOAT);
  7910. -           if ( (Dc_arg_float < 0.0f) || (Dc_arg_float > 1.0f) )   {
  7911. -               Dc_help = 1;
  7912. -           } else {
  7913. -               ship_set_subsystem_strength( Player_ship, SUBSYSTEM_WEAPONS, Dc_arg_float );
  7914. -           }
  7915. -       } else if ( !subsystem_stricmp( Dc_arg, "engine" )) {
  7916. -           dc_get_arg(ARG_FLOAT);
  7917. -           if ( (Dc_arg_float < 0.0f) || (Dc_arg_float > 1.0f) )   {
  7918. -               Dc_help = 1;
  7919. -           } else {
  7920. -               ship_set_subsystem_strength( Player_ship, SUBSYSTEM_ENGINE, Dc_arg_float );
  7921. -               if ( Dc_arg_float < ENGINE_MIN_STR )    {
  7922. -                   Player_ship->flags |= SF_DISABLED;              // add the disabled flag
  7923. -               } else {
  7924. -                   Player_ship->flags &= (~SF_DISABLED);               // add the disabled flag
  7925. -               }
  7926. -           }
  7927. -       } else if ( !subsystem_stricmp( Dc_arg, "sensors" ))    {
  7928. -           dc_get_arg(ARG_FLOAT);
  7929. -           if ( (Dc_arg_float < 0.0f) || (Dc_arg_float > 1.0f) )   {
  7930. -               Dc_help = 1;
  7931. -           } else {
  7932. -               ship_set_subsystem_strength( Player_ship, SUBSYSTEM_SENSORS, Dc_arg_float );
  7933. -           }
  7934. -       } else if ( !subsystem_stricmp( Dc_arg, "communication" ))  {
  7935. -           dc_get_arg(ARG_FLOAT);
  7936. -           if ( (Dc_arg_float < 0.0f) || (Dc_arg_float > 1.0f) )   {
  7937. -               Dc_help = 1;
  7938. -           } else {
  7939. -               ship_set_subsystem_strength( Player_ship, SUBSYSTEM_COMMUNICATION, Dc_arg_float );
  7940. -           }
  7941. -       } else if ( !subsystem_stricmp( Dc_arg, "navigation" )) {
  7942. -           dc_get_arg(ARG_FLOAT);
  7943. -           if ( (Dc_arg_float < 0.0f) || (Dc_arg_float > 1.0f) )   {
  7944. -               Dc_help = 1;
  7945. -           } else {
  7946. -               ship_set_subsystem_strength( Player_ship, SUBSYSTEM_NAVIGATION, Dc_arg_float );
  7947. -           }
  7948. -       } else if ( !subsystem_stricmp( Dc_arg, "radar" ))  {
  7949. -           dc_get_arg(ARG_FLOAT);
  7950. -           if ( (Dc_arg_float < 0.0f) || (Dc_arg_float > 1.0f) )   {
  7951. -               Dc_help = 1;
  7952. -           } else {
  7953. -               ship_set_subsystem_strength( Player_ship, SUBSYSTEM_RADAR, Dc_arg_float );
  7954. -           }
  7955. -       } else {
  7956. -           // print usage
  7957. -           Dc_help = 1;
  7958. -       }
  7959. +   SCP_string arg;
  7960. +   int subsystem = SUBSYSTEM_NONE;
  7961. +   float val_f;
  7962. +  
  7963. +   if (dc_optional_string_either("help", "--help")) {
  7964. +       dc_printf( "Usage: set_subsys <type> [--status] <strength>\n");
  7965. +       dc_printf("<type> is any of the following:\n");
  7966. +       dc_printf("\tweapons\n");
  7967. +       dc_printf("\tengine\n");
  7968. +       dc_printf("\tsensors\n");
  7969. +       dc_printf("\tcommunication\n");
  7970. +       dc_printf("\tnavigation\n");
  7971. +       dc_printf("\tradar\n\n");
  7972. +
  7973. +       dc_printf("[--status] will display status of that subsystem\n\n");
  7974. +      
  7975. +       dc_printf("<strength> is any value between 0 and 1.0\n");
  7976. +       return;
  7977.     }
  7978.  
  7979. -   if ( Dc_help )  {
  7980. -       dc_printf( "Usage: set_subsys type X\nWhere X is value between 0 and 1.0, and type can be:\n" );
  7981. -       dc_printf( "weapons\n" );
  7982. -       dc_printf( "engine\n" );
  7983. -       dc_printf( "sensors\n" );
  7984. -       dc_printf( "communication\n" );
  7985. -       dc_printf( "navigation\n" );
  7986. -       dc_printf( "radar\n" );
  7987. -       Dc_status = 0;  // don't print status if help is printed.  Too messy.
  7988. +   dc_stuff_string_white(arg);
  7989. +
  7990. +   if (arg == "weapons") {
  7991. +       subsystem = SUBSYSTEM_WEAPONS;
  7992. +  
  7993. +   } else if (arg == "engine") {
  7994. +       subsystem = SUBSYSTEM_ENGINE;  
  7995. +  
  7996. +   } else if (arg == "sensors") {
  7997. +       subsystem = SUBSYSTEM_SENSORS;
  7998. +
  7999. +   } else if (arg == "communication") {
  8000. +       subsystem = SUBSYSTEM_COMMUNICATION;
  8001. +
  8002. +   } else if (arg == "navigation") {
  8003. +       subsystem = SUBSYSTEM_NAVIGATION;
  8004. +
  8005. +   } else if (arg == "radar") {
  8006. +       subsystem = SUBSYSTEM_RADAR;
  8007. +
  8008. +   } else {
  8009. +       dc_printf("Erro: Unknown argument '%s'\n", arg.c_str());
  8010. +       return;
  8011. +   }
  8012. +
  8013. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  8014. +       dc_printf("Subsystem '%s' is at %f strength\n", arg.c_str(), ship_get_subsystem_strength(Player_ship, subsystem));
  8015. +
  8016. +   } else {
  8017. +       // Set the subsystem strength
  8018. +       dc_stuff_float(&val_f);
  8019. +
  8020. +       CLAMP(val_f, 0.0, 1.0);
  8021. +       ship_set_subsystem_strength( Player_ship, subsystem, val_f );
  8022. +      
  8023. +       if (subsystem == SUBSYSTEM_ENGINE) {
  8024. +           // If subsystem is an engine, set/clear the disabled flag
  8025. +           (val_f < ENGINE_MIN_STR) ? (Player_ship->flags |= SF_DISABLED) : (Player_ship->flags &= (~SF_DISABLED));
  8026. +       }
  8027.     }
  8028.  }
  8029.  //XSTR:ON
  8030. @@ -16420,11 +16430,11 @@ int ship_get_texture(int bitmap)
  8031.  // update artillery lock info
  8032.  #define CLEAR_ARTILLERY_AND_CONTINUE() { if(aip != NULL){ aip->artillery_objnum = -1; aip->artillery_sig = -1; aip->artillery_lock_time = 0.0f;} continue; }
  8033.  float artillery_dist = 10.0f;
  8034. -DCF(art, "")
  8035. +DCF(art, "Sets artillery disance")
  8036.  {
  8037. -   dc_get_arg(ARG_FLOAT);
  8038. -   artillery_dist = Dc_arg_float;
  8039. +   dc_stuff_float(&artillery_dist);
  8040.  }
  8041. +
  8042.  void ship_update_artillery_lock()
  8043.  {
  8044.     ai_info *aip = NULL;
  8045. diff --git a/code/ship/shipfx.cpp b/code/ship/shipfx.cpp
  8046. index 6a656f6..ecea0fb 100644
  8047. --- a/code/ship/shipfx.cpp
  8048. +++ b/code/ship/shipfx.cpp
  8049. @@ -40,6 +40,7 @@
  8050.  #include "bmpman/bmpman.h"
  8051.  #include "model/model.h"
  8052.  #include "cmdline/cmdline.h"
  8053. +#include "debugconsole/console.h"
  8054.  
  8055.  
  8056.  #ifndef NDEBUG
  8057. @@ -1355,42 +1356,58 @@ void shipfx_flash_do_frame(float frametime)
  8058.  }
  8059.  
  8060.  float Particle_width = 1.2f;
  8061. -DCF(particle_width, "Multiplier for angular width of the particle spew")
  8062. +DCF(particle_width, "Sets multiplier for angular width of the particle spew ( 0 - 5)")
  8063.  {
  8064. -   if ( Dc_command ) {
  8065. -       dc_get_arg(ARG_FLOAT);
  8066. -       if ( (Dc_arg_float >= 0 ) && (Dc_arg_float <= 5) ) {
  8067. -           Particle_width = Dc_arg_float;
  8068. -       } else {
  8069. -           dc_printf( "Illegal value for particle width. (Must be from 0-5) \n\n");
  8070. -       }
  8071. +   float value;
  8072. +
  8073. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  8074. +       dc_printf("Particle_width : %f\n", Particle_width);
  8075. +       return;
  8076.     }
  8077. +
  8078. +   dc_stuff_float(&value);
  8079. +
  8080. +   CLAMP(value, 0.0, 5.0);
  8081. +   Particle_width = value;
  8082. +
  8083. +   dc_printf("Particle_width set to %f\n", Particle_width);
  8084.  }
  8085.  
  8086.  float Particle_number = 1.2f;
  8087. -DCF(particle_num, "Multiplier for the number of particles created")
  8088. +DCF(particle_num, "Sets multiplier for the number of particles created")
  8089.  {
  8090. -   if ( Dc_command ) {
  8091. -       dc_get_arg(ARG_FLOAT);
  8092. -       if ( (Dc_arg_float >= 0 ) && (Dc_arg_float <= 5) ) {
  8093. -           Particle_number = Dc_arg_float;
  8094. -       } else {
  8095. -           dc_printf( "Illegal value for particle num. (Must be from 0-5) \n\n");
  8096. -       }
  8097. +  
  8098. +   float value;
  8099. +
  8100. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  8101. +       dc_printf("Particle_number : %f\n", Particle_number);
  8102. +       return;
  8103.     }
  8104. +
  8105. +   dc_stuff_float(&value);
  8106. +
  8107. +   CLAMP(value, 0.0, 5.0);
  8108. +   Particle_number = value;
  8109. +
  8110. +   dc_printf("Particle_number set to %f\n", Particle_number);
  8111.  }
  8112.  
  8113.  float Particle_life = 1.2f;
  8114.  DCF(particle_life, "Multiplier for the lifetime of particles created")
  8115.  {
  8116. -   if ( Dc_command ) {
  8117. -       dc_get_arg(ARG_FLOAT);
  8118. -       if ( (Dc_arg_float >= 0 ) && (Dc_arg_float <= 5) ) {
  8119. -           Particle_life = Dc_arg_float;
  8120. -       } else {
  8121. -           dc_printf( "Illegal value for particle life. (Must be from 0-5) \n\n");
  8122. -       }
  8123. +   float value;
  8124. +
  8125. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  8126. +       dc_printf("Particle_life : %f\n", Particle_life);
  8127. +       return;
  8128.     }
  8129. +
  8130. +   dc_stuff_float(&value);
  8131. +
  8132. +   CLAMP(value, 0.0, 5.0);
  8133. +   Particle_life = value;
  8134. +
  8135. +   dc_printf("Particle_life set to %f\n", Particle_life);
  8136.  }
  8137.  
  8138.  // Make sparks fly off of ship n.
  8139. @@ -1602,16 +1619,20 @@ int Bs_exp_fire_low = 1;
  8140.  float  Bs_exp_fire_time_mult = 1.0f;
  8141.  
  8142.  DCF_BOOL(bs_exp_fire_low, Bs_exp_fire_low)
  8143. -DCF(bs_exp_fire_time_mult, "Multiplier time between fireball in big ship explosion")
  8144. +DCF(bs_exp_fire_time_mult, "Sets multiplier time between fireball in big ship explosion")
  8145.  {
  8146. -   if ( Dc_command ) {
  8147. -       dc_get_arg(ARG_FLOAT);
  8148. -       if ( (Dc_arg_float >= 0.1 ) && (Dc_arg_float <= 5) ) {
  8149. -           Bs_exp_fire_time_mult = Dc_arg_float;
  8150. -       } else {
  8151. -           dc_printf( "Illegal value for bs_exp_fire_time_mult. (Must be from 0.1-5) \n\n");
  8152. -       }
  8153. +   float value;
  8154. +
  8155. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  8156. +       dc_printf("Bs_exp_fire_time_mult : %f\n", Bs_exp_fire_time_mult);
  8157. +       return;
  8158.     }
  8159. +
  8160. +   dc_stuff_float(&value);
  8161. +
  8162. +   CLAMP(value, 0.1f, 5.0f);
  8163. +   Bs_exp_fire_time_mult = value;
  8164. +   dc_printf("Bs_exp_fire_time_mult set to %f\n", Bs_exp_fire_time_mult);
  8165.  }
  8166.  
  8167.  
  8168. diff --git a/code/sound/sound.cpp b/code/sound/sound.cpp
  8169. index ddb2cbf..1a15fb1 100644
  8170. --- a/code/sound/sound.cpp
  8171. +++ b/code/sound/sound.cpp
  8172. @@ -15,6 +15,7 @@
  8173.  #include "cmdline/cmdline.h"
  8174.  #include "osapi/osapi.h"
  8175.  #include "globalincs/vmallocator.h"
  8176. +#include "debugconsole/console.h"
  8177.  
  8178.  #include "gamesnd/gamesnd.h"
  8179.  #include "globalincs/alphacolors.h"
  8180. @@ -200,14 +201,15 @@ void snd_spew_info()
  8181.  }
  8182.  
  8183.  int Sound_spew = 0;
  8184. -DCF(show_sounds, "")
  8185. +DCF(show_sounds, "Toggles display of sound debug info")
  8186.  {
  8187. -   Sound_spew = !Sound_spew;
  8188. -   if(Sound_spew){
  8189. -       dc_printf("Sound debug info ON");
  8190. -   } else {
  8191. -       dc_printf("Sound debug info OFF");
  8192. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  8193. +       dc_printf("Sound debug info is %s", (Sound_spew ? "ON" : "OFF"));
  8194. +       return;
  8195.     }
  8196. +
  8197. +   Sound_spew = !Sound_spew;
  8198. +   dc_printf("Sound debug info is %s", (Sound_spew ? "ON" : "OFF"));
  8199.  }
  8200.  void snd_spew_debug_info()
  8201.  {
  8202. diff --git a/code/starfield/nebula.cpp b/code/starfield/nebula.cpp
  8203. index a43ab9b..4187ae0 100644
  8204. --- a/code/starfield/nebula.cpp
  8205. +++ b/code/starfield/nebula.cpp
  8206. @@ -15,7 +15,7 @@
  8207.  #include "mission/missionparse.h"
  8208.  #include "nebula/neb.h"
  8209.  #include "cfile/cfile.h"
  8210. -
  8211. +#include "debugconsole/console.h"
  8212.  
  8213.  
  8214.  #define MAX_TRIS 200
  8215. @@ -215,17 +215,19 @@ void nebula_render()
  8216.  
  8217.  DCF(nebula,"Loads a different nebula")
  8218.  {
  8219. -   if ( Dc_command )   {
  8220. -       dc_get_arg(ARG_STRING|ARG_NONE);
  8221. -       if ( Dc_arg_type == ARG_NONE )  {
  8222. -           nebula_close();
  8223. -       } else {
  8224. -           nebula_init( Dc_arg );
  8225. -       }
  8226. +   char filename[MAX_NAME_LEN];
  8227. +
  8228. +   if (dc_optional_string_either("help", "--help")) {
  8229. +       dc_printf("Usage: nebula [filename]\n");
  8230. +       dc_printf("Loads the nebula file. No filename takes away nebula\n" );
  8231. +       return;
  8232. +   }
  8233. +
  8234. +   if (dc_maybe_stuff_string_white(filename, MAX_NAME_LEN)) {
  8235. +           nebula_init(filename);
  8236. +   } else {
  8237. +       nebula_close();
  8238.     }
  8239. -   if ( Dc_help )  {
  8240. -       dc_printf( "Usage: nebula filename\nLoads the nebula file. No filename takes away nebula\n" );
  8241. -   }  
  8242.  }
  8243.  
  8244.  
  8245. diff --git a/code/starfield/starfield.cpp b/code/starfield/starfield.cpp
  8246. index 4a08d5d..0df45a7 100644
  8247. --- a/code/starfield/starfield.cpp
  8248. +++ b/code/starfield/starfield.cpp
  8249. @@ -25,6 +25,7 @@
  8250.  #include "parse/parselo.h"
  8251.  #include "hud/hud.h"
  8252.  #include "hud/hudtarget.h"
  8253. +#include "debugconsole/console.h"
  8254.  
  8255.  
  8256.  #define MAX_DEBRIS_VCLIPS          4
  8257. @@ -866,75 +867,11 @@ uint Star_flags = STAR_FLAG_DEFAULT;
  8258.  //XSTR:OFF
  8259.  DCF(stars,"Set parameters for starfield")
  8260.  {
  8261. -   if ( Dc_command ) {
  8262. -       dc_get_arg(ARG_STRING);
  8263. -       if ( !strcmp( Dc_arg, "tail" )) {
  8264. -           dc_get_arg(ARG_FLOAT);
  8265. -           if ( (Dc_arg_float < 0.0f) || (Dc_arg_float > 1.0f) ) {
  8266. -               Dc_help = 1;
  8267. -           } else {
  8268. -               Star_amount = Dc_arg_float;
  8269. -           }
  8270. -       } else if ( !strcmp( Dc_arg, "len" )) {
  8271. -           dc_get_arg(ARG_FLOAT);
  8272. -           Star_max_length = Dc_arg_float;
  8273. -       } else if ( !strcmp( Dc_arg, "dim" )) {
  8274. -           dc_get_arg(ARG_FLOAT);
  8275. -           if ( Dc_arg_float < 0.0f ) {
  8276. -               Dc_help = 1;
  8277. -           } else {
  8278. -               Star_dim = Dc_arg_float;
  8279. -           }
  8280. -       } else if ( !strcmp( Dc_arg, "flag" )) {
  8281. -           dc_get_arg(ARG_STRING);
  8282. -           if ( !strcmp( Dc_arg, "tail" )) {
  8283. -               Star_flags ^= STAR_FLAG_TAIL;
  8284. -           } else if ( !strcmp( Dc_arg, "dim" )) {
  8285. -               Star_flags ^= STAR_FLAG_DIM;
  8286. -           } else if ( !strcmp( Dc_arg, "aa" )) {
  8287. -               Star_flags ^= STAR_FLAG_ANTIALIAS;
  8288. -           } else {
  8289. -               Dc_help = 1;
  8290. -           }
  8291. -       } else if ( !strcmp( Dc_arg, "cap" )) {
  8292. -           dc_get_arg(ARG_FLOAT);
  8293. -           if ( (Dc_arg_float < 0.0f) || (Dc_arg_float > 255.0f) ) {
  8294. -               Dc_help = 1;
  8295. -           } else {
  8296. -               Star_cap = Dc_arg_float;
  8297. -           }
  8298. -       } else if ( !strcmp( Dc_arg, "m0" )) {
  8299. -           Star_amount = 0.0f;
  8300. -           Star_dim = 0.0f;
  8301. -           Star_cap = 0.0f;
  8302. -           Star_flags = 0;
  8303. -           Star_max_length = STAR_MAX_LENGTH_DEFAULT;
  8304. -       } else if ( !strcmp( Dc_arg, "m1" ) || !strcmp( Dc_arg, "default" )) {
  8305. -           Star_amount = STAR_AMOUNT_DEFAULT;
  8306. -           Star_dim = STAR_DIM_DEFAULT;
  8307. -           Star_cap = STAR_CAP_DEFAULT;
  8308. -           Star_flags = STAR_FLAG_DEFAULT;
  8309. -           Star_max_length = STAR_MAX_LENGTH_DEFAULT;
  8310. -       } else if ( !strcmp( Dc_arg, "m2" )) {
  8311. -           Star_amount = 0.75f;
  8312. -           Star_dim = 20.0f;
  8313. -           Star_cap = 75.0f;
  8314. -           Star_flags = STAR_FLAG_TAIL|STAR_FLAG_DIM|STAR_FLAG_ANTIALIAS;
  8315. -           Star_max_length = STAR_MAX_LENGTH_DEFAULT;
  8316. -       } else if ( !strcmp( Dc_arg, "num" )) {
  8317. -           dc_get_arg(ARG_INT);
  8318. -           if ( (Dc_arg_int < 0) || (Dc_arg_int > MAX_STARS) ) {
  8319. -               Dc_help = 1;
  8320. -           } else {
  8321. -               Num_stars = Dc_arg_int;
  8322. -           }
  8323. -       } else {
  8324. -           // print usage, not stats
  8325. -           Dc_help = 1;
  8326. -       }
  8327. -   }
  8328. +   SCP_string arg;
  8329. +   float val_f;
  8330. +   int val_i;
  8331.  
  8332. -   if ( Dc_help ) {
  8333. +   if (dc_optional_string_either("help", "--help")) {
  8334.         dc_printf( "Usage: stars keyword\nWhere keyword can be in the following forms:\n" );
  8335.         dc_printf( "stars default   Resets stars to all default values\n" );
  8336.         dc_printf( "stars num X     Sets number of stars to X.  Between 0 and %d.\n", MAX_STARS );
  8337. @@ -949,21 +886,105 @@ DCF(stars,"Set parameters for starfield")
  8338.         dc_printf( "\nHINT: set cap to 0 to get dim rate and tail down, then use\n" );
  8339.         dc_printf( "cap to keep the lines from going away when moving too fast.\n" );
  8340.         dc_printf( "\nUse '? stars' to see current values.\n" );
  8341. -       Dc_status = 0;  // don't print status if help is printed.  Too messy.
  8342. +       return; // don't print status if help is printed.  Too messy.
  8343.     }
  8344.  
  8345. -   if ( Dc_status ) {
  8346. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  8347.         dc_printf( "Num_stars: %d\n", Num_stars );
  8348.         dc_printf( "Tail: %.2f\n", Star_amount );
  8349. -       dc_printf( "Dim: %.2f\n", Star_dim );
  8350. -       dc_printf( "Cap: %.2f\n", Star_cap );
  8351. +       dc_printf( "Dim : %.2f\n", Star_dim );
  8352. +       dc_printf( "Cap : %.2f\n", Star_cap );
  8353.         dc_printf( "Max length: %.2f\n", Star_max_length );
  8354.         dc_printf( "Flags:\n" );
  8355. -       dc_printf( "  Tail: %s\n", (Star_flags&STAR_FLAG_TAIL?"On":"Off") );
  8356. -       dc_printf( "  Dim: %s\n", (Star_flags&STAR_FLAG_DIM?"On":"Off") );
  8357. +       dc_printf( "  Tail : %s\n", (Star_flags&STAR_FLAG_TAIL?"On":"Off") );
  8358. +       dc_printf( "  Dim  : %s\n", (Star_flags&STAR_FLAG_DIM?"On":"Off") );
  8359.         dc_printf( "  Antialias: %s\n", (Star_flags&STAR_FLAG_ANTIALIAS?"On":"Off") );
  8360.         dc_printf( "\nTHESE AREN'T SAVED TO DISK, SO IF YOU TWEAK\n" );
  8361.         dc_printf( "THESE AND LIKE THEM, WRITE THEM DOWN!!\n" );
  8362. +       return;
  8363. +   }
  8364. +
  8365. +   dc_stuff_string_white(arg);
  8366. +   // "stars default" is handled by "stars m1"
  8367. +   if (arg == "num") {
  8368. +       dc_stuff_int(&val_i);
  8369. +
  8370. +       CLAMP(val_i, 0, MAX_STARS);
  8371. +       Num_stars = val_i;
  8372. +
  8373. +       dc_printf("Num_stars set to %i\n", Num_stars);
  8374. +  
  8375. +   } else if (arg == "tail") {
  8376. +       dc_stuff_float(&val_f);
  8377. +       CLAMP(val_f, 0.0, 1.0);
  8378. +       Star_amount = val_f;
  8379. +      
  8380. +       dc_printf("Star_amount set to %f\n", Star_amount);
  8381. +
  8382. +   } else if (arg == "dim") {
  8383. +       dc_stuff_float(&val_f);
  8384. +
  8385. +       if (val_f > 0.0f ) {
  8386. +           Star_dim = val_f;
  8387. +           dc_printf("Star_dim set to %f\n", Star_dim);
  8388. +      
  8389. +       } else {
  8390. +           dc_printf("Error: Star_dim value must be non-negative\n");
  8391. +       }
  8392. +  
  8393. +   } else if (arg == "cap") {
  8394. +       dc_stuff_float(&val_f);
  8395. +       CLAMP(val_f, 0.0, 255);
  8396. +       Star_cap = val_f;
  8397. +      
  8398. +       dc_printf("Star_cap set to %f\n", Star_cap);
  8399. +  
  8400. +   } else if (arg == "len") {
  8401. +       dc_stuff_float(&Star_max_length);
  8402. +
  8403. +       dc_printf("Star_max_length set to %f\n", Star_max_length);
  8404. +
  8405. +   } else if (arg == "m0") {
  8406. +       Star_amount = 0.0f;
  8407. +       Star_dim = 0.0f;
  8408. +       Star_cap = 0.0f;
  8409. +       Star_flags = 0;
  8410. +       Star_max_length = STAR_MAX_LENGTH_DEFAULT;
  8411. +
  8412. +       dc_printf("Starfield set: Old 'pixel type' crappy stars. flags=none\n");
  8413. +  
  8414. +   } else if ((arg == "m1") || (arg == "default")) {
  8415. +       Star_amount = STAR_AMOUNT_DEFAULT;
  8416. +       Star_dim = STAR_DIM_DEFAULT;
  8417. +       Star_cap = STAR_CAP_DEFAULT;
  8418. +       Star_flags = STAR_FLAG_DEFAULT;
  8419. +       Star_max_length = STAR_MAX_LENGTH_DEFAULT;
  8420. +
  8421. +       dc_printf("Starfield set: (default) tail=.75, dim=20.0, cap=75.0, flags=dim,tail\n");
  8422. +
  8423. +   } else if (arg == "m2") {
  8424. +       Star_amount = 0.75f;
  8425. +       Star_dim = 20.0f;
  8426. +       Star_cap = 75.0f;
  8427. +       Star_flags = STAR_FLAG_TAIL|STAR_FLAG_DIM|STAR_FLAG_ANTIALIAS;
  8428. +       Star_max_length = STAR_MAX_LENGTH_DEFAULT;
  8429. +
  8430. +       dc_printf("Starfield set: tail=.75, dim=20.0, cap=75.0, flags=dim,tail,aa\n");
  8431. +
  8432. +   } else if (arg == "flag") {
  8433. +       dc_stuff_string_white(arg);
  8434. +       if (arg == "tail") {
  8435. +           Star_flags ^= STAR_FLAG_TAIL;
  8436. +       } else if (arg == "dim" ) {
  8437. +           Star_flags ^= STAR_FLAG_DIM;
  8438. +       } else if (arg == "aa" ) {
  8439. +           Star_flags ^= STAR_FLAG_ANTIALIAS;
  8440. +       } else {
  8441. +           dc_printf("Error: unknown flag argument '%s'\n", arg.c_str());
  8442. +       }
  8443. +
  8444. +   } else {
  8445. +       dc_printf("Error: Unknown argument '%s'", arg.c_str());
  8446.     }
  8447.  }
  8448.  //XSTR:ON
  8449. @@ -1284,39 +1305,44 @@ float Subspace_glow_rate = 1.0f;
  8450.  //XSTR:OFF
  8451.  DCF(subspace_set,"Set parameters for subspace effect")
  8452.  {
  8453. -   if ( Dc_command ) {
  8454. -       dc_get_arg(ARG_STRING);
  8455. -       if ( !strcmp( Dc_arg, "u" )) {
  8456. -           dc_get_arg(ARG_FLOAT);
  8457. -           if ( Dc_arg_float < 0.0f ) {
  8458. -               Dc_help = 1;
  8459. -           } else {
  8460. -               subspace_u_speed = Dc_arg_float;
  8461. -           }
  8462. -       } else if ( !strcmp( Dc_arg, "v" )) {
  8463. -           dc_get_arg(ARG_FLOAT);
  8464. -           if ( Dc_arg_float < 0.0f ) {
  8465. -               Dc_help = 1;
  8466. -           } else {
  8467. -               subspace_v_speed = Dc_arg_float;
  8468. -           }
  8469. -       } else {
  8470. -           // print usage, not stats
  8471. -           Dc_help = 1;
  8472. -       }
  8473. -   }
  8474. -
  8475. -   if ( Dc_help ) {
  8476. -       dc_printf( "Usage: subspace keyword\nWhere keyword can be in the following forms:\n" );
  8477. -       dc_printf( "subspace u X    Where X is how fast u moves.\n", MAX_STARS );
  8478. -       dc_printf( "subspace v X    Where X is how fast v moves.\n" );
  8479. -       dc_printf( "\nUse '? subspace' to see current values.\n" );
  8480. -       Dc_status = 0;  // don't print status if help is printed.  Too messy.
  8481. +   SCP_string arg;
  8482. +   float value;
  8483. +
  8484. +   if (dc_optional_string_either("help", "--help")) {
  8485. +       dc_printf( "Usage: subspace [--status] <axis> <speed>\n");
  8486. +       dc_printf("[--status] -- Displays the current speeds for both axes\n");
  8487. +       dc_printf("<axis>  -- May be either 'u' or 'v', and corresponds to the texture axis\n");
  8488. +       dc_printf("<speed> -- is the speed along the axis that the texture is moved\n");
  8489. +       return;
  8490.     }
  8491.  
  8492. -   if ( Dc_status ) {
  8493. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  8494.         dc_printf( "u: %.2f\n", subspace_u_speed );
  8495.         dc_printf( "v: %.2f\n", subspace_v_speed );
  8496. +       return;
  8497. +   }
  8498. +
  8499. +   dc_stuff_string_white(arg);
  8500. +   if (arg == "u") {
  8501. +       dc_stuff_float(&value);
  8502. +
  8503. +       if ( value < 0.0f ) {
  8504. +           dc_printf("Error: speed must be non-negative");
  8505. +           return;
  8506. +       }
  8507. +       subspace_u_speed = value;
  8508. +
  8509. +   } else if (arg == "v") {
  8510. +       dc_stuff_float(&value);
  8511. +
  8512. +       if (value < 0.0f) {
  8513. +           dc_printf("Error: speed must be non-negative");
  8514. +           return;
  8515. +       }
  8516. +       subspace_v_speed = value;
  8517. +
  8518. +   } else {
  8519. +       dc_printf("Error: Unknown axis '%s'", arg.c_str());
  8520.     }
  8521.  }
  8522.  //XSTR:ON
  8523. diff --git a/code/starfield/supernova.cpp b/code/starfield/supernova.cpp
  8524. index 7a1c420..058ce66 100644
  8525. --- a/code/starfield/supernova.cpp
  8526. +++ b/code/starfield/supernova.cpp
  8527. @@ -21,6 +21,7 @@
  8528.  #include "gamesequence/gamesequence.h"
  8529.  #include "gamesnd/gamesnd.h"
  8530.  #include "cmdline/cmdline.h"
  8531. +#include "debugconsole/console.h"
  8532.  
  8533.  // --------------------------------------------------------------------------------------------------------------------------
  8534.  // SUPERNOVA DEFINES/VARS
  8535. @@ -116,11 +117,8 @@ void supernova_stop()
  8536.  
  8537.  
  8538.  int sn_particles = 100;
  8539. -DCF(sn_part, "")
  8540. -{
  8541. -   dc_get_arg(ARG_INT);
  8542. -   sn_particles = Dc_arg_int;
  8543. -}
  8544. +DCF_INT2(sn_part, sn_particles, 0, INT_MAX, "Sets number of supernova particles (default is 100)");
  8545. +
  8546.  void supernova_do_particles()
  8547.  {
  8548.     int idx;
  8549. @@ -181,11 +179,7 @@ void supernova_do_particles()
  8550.  
  8551.  // call once per frame
  8552.  float sn_shudder = 0.45f;
  8553. -DCF(sn_shud, "")
  8554. -{
  8555. -   dc_get_arg(ARG_FLOAT);
  8556. -   sn_shudder = Dc_arg_float;
  8557. -}
  8558. +DCF_FLOAT2(sn_shud, sn_shudder, 0.0, FLT_MAX, "Sets camera shudder rate for being in supernova shockwave (default is 0.45)");
  8559.  
  8560.  void supernova_process()
  8561.  {
  8562. @@ -318,17 +312,10 @@ int supernova_camera_cut()
  8563.  // get view params from supernova
  8564.  float sn_distance = 300.0f;                // shockwave moving at 1000/ms ?
  8565.  float sn_cam_distance = 25.0f;
  8566. -DCF(sn_dist, "")
  8567. -{
  8568. -   dc_get_arg(ARG_FLOAT);
  8569. -   sn_distance = Dc_arg_float;
  8570. -}
  8571. +DCF_FLOAT2(sn_dist, sn_distance, 0.0, FLT_MAX, "Sets supernova shockwave distance (default is 300.0f)");
  8572.  
  8573. -DCF(sn_cam_dist, "")
  8574. -{
  8575. -   dc_get_arg(ARG_FLOAT);
  8576. -   sn_cam_distance = Dc_arg_float;
  8577. -}
  8578. +
  8579. +DCF_FLOAT2(sn_cam_dist, sn_cam_distance, 0.0, FLT_MAX, "Sets supernova camera distance (default is 25.0f)");
  8580.  
  8581.  void supernova_get_eye(vec3d *eye_pos, matrix *eye_orient)
  8582.  {
  8583. diff --git a/code/stats/medals.cpp b/code/stats/medals.cpp
  8584. index 34e0bc5..98a5df8 100644
  8585. --- a/code/stats/medals.cpp
  8586. +++ b/code/stats/medals.cpp
  8587. @@ -21,6 +21,7 @@
  8588.  #include "globalincs/alphacolors.h"
  8589.  #include "localization/localize.h"
  8590.  #include "parse/parselo.h"
  8591. +#include "debugconsole/console.h"
  8592.  
  8593.  #ifndef NDEBUG
  8594.  #include "cmdline/cmdline.h"
  8595. @@ -437,78 +438,17 @@ void parse_medal_tbl()
  8596.  DCF(medals, "Grant or revoke medals")
  8597.  {
  8598.     int i;
  8599. +   int idx;
  8600.  
  8601. -   if (Dc_command)
  8602. -   {
  8603. -       dc_get_arg(ARG_STRING | ARG_INT | ARG_NONE);
  8604. -
  8605. -       if (Dc_arg_type & ARG_INT)
  8606. -       {
  8607. -           int idx = Dc_arg_int;
  8608. -
  8609. -           if (idx < 0 || idx >= Num_medals)
  8610. -           {
  8611. -               dc_printf("Medal index %d is out of range\n", idx);
  8612. -               return;
  8613. -           }
  8614. -
  8615. -           dc_printf("Granted %s\n", Medals[idx].name);
  8616. -           Player->stats.medal_counts[idx]++;
  8617. -       }
  8618. -       else if (Dc_arg_type & ARG_STRING)
  8619. -       {
  8620. -           if (!strcmp(Dc_arg, "all"))
  8621. -           {
  8622. -               for (i = 0; i < Num_medals; i++)
  8623. -                   Player->stats.medal_counts[i]++;
  8624. -
  8625. -               dc_printf("Granted all medals\n");
  8626. -           }
  8627. -           else if (!strcmp(Dc_arg, "clear"))
  8628. -           {
  8629. -               for (i = 0; i < Num_medals; i++)
  8630. -                   Player->stats.medal_counts[i] = 0;
  8631. -
  8632. -               dc_printf("Cleared all medals\n");
  8633. -           }
  8634. -           else if (!strcmp(Dc_arg, "demote"))
  8635. -           {
  8636. -               if (Player->stats.rank > 0)
  8637. -                   Player->stats.rank--;
  8638. -
  8639. -               dc_printf("Demoted to %s\n", Ranks[Player->stats.rank].name);
  8640. -           }
  8641. -           else if (!strcmp(Dc_arg, "promote"))
  8642. -           {
  8643. -               if (Player->stats.rank < MAX_FREESPACE2_RANK)
  8644. -                   Player->stats.rank++;
  8645. -
  8646. -               dc_printf("Promoted to %s\n", Ranks[Player->stats.rank].name);
  8647. -           }
  8648. -           else
  8649. -           {
  8650. -               Dc_help = 1;
  8651. -           }
  8652. -       }
  8653. -       else
  8654. -       {
  8655. -           dc_printf("The following medals are available:\n");
  8656. -           for (i = 0; i < Num_medals; i++)
  8657. -               dc_printf("%d: %s\n", i, Medals[i].name);
  8658. -       }
  8659. -
  8660. -       Dc_status = 0;
  8661. -   }
  8662. -
  8663. -   if (Dc_help)
  8664. +   if (dc_optional_string_either("help", "--help"))
  8665.     {
  8666. -       dc_printf ("Usage: gimmemedals all | clear | promote | demote | [index]\n");
  8667. +       dc_printf ("Usage: medals all | clear | promote | demote | [index]\n");
  8668.         dc_printf ("       [index] --  index of medal to grant\n");
  8669.         dc_printf ("       with no parameters, displays the available medals\n");
  8670. -       Dc_status = 0;
  8671. +       return;
  8672.     }
  8673.  
  8674. -   if (Dc_status)
  8675. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?"))
  8676.     {
  8677.         dc_printf("You have the following medals:\n");
  8678.  
  8679. @@ -518,6 +458,53 @@ DCF(medals, "Grant or revoke medals")
  8680.                 dc_printf("%d %s\n", Player->stats.medal_counts[i], Medals[i].name);
  8681.         }
  8682.         dc_printf("%s\n", Ranks[Player->stats.rank].name);
  8683. +       return;
  8684. +   }
  8685. +
  8686. +   if (dc_optional_string("all")) {
  8687. +       for (i = 0; i < Num_medals; i++) {
  8688. +           Player->stats.medal_counts[i]++;
  8689. +       }
  8690. +       dc_printf("Granted all medals\n");
  8691. +       return;
  8692. +
  8693. +   } else if (dc_optional_string("clear")) {
  8694. +       for (i = 0; i < Num_medals; i++) {
  8695. +           Player->stats.medal_counts[i] = 0;
  8696. +       }
  8697. +       dc_printf("Cleared all medals\n");
  8698. +       return;
  8699. +
  8700. +   } else if (dc_optional_string("promote")) {
  8701. +       if (Player->stats.rank < MAX_FREESPACE2_RANK) {
  8702. +           Player->stats.rank++;
  8703. +       }
  8704. +       dc_printf("Promoted to %s\n", Ranks[Player->stats.rank].name);
  8705. +       return;
  8706. +
  8707. +   } else if (dc_optional_string("demote")) {
  8708. +       if (Player->stats.rank > 0) {
  8709. +           Player->stats.rank--;
  8710. +       }
  8711. +       dc_printf("Demoted to %s\n", Ranks[Player->stats.rank].name);
  8712. +       return;
  8713. +   }
  8714. +
  8715. +   if (dc_maybe_stuff_int(&idx)) {
  8716. +       if (idx < 0 || idx >= Num_medals)
  8717. +       {
  8718. +           dc_printf("Medal index %d is out of range\n", idx);
  8719. +           return;
  8720. +       }
  8721. +
  8722. +       dc_printf("Granted %s\n", Medals[idx].name);
  8723. +       Player->stats.medal_counts[idx]++;
  8724. +       return;
  8725. +   }
  8726. +
  8727. +   dc_printf("The following medals are available:\n");
  8728. +   for (i = 0; i < Num_medals; i++) {
  8729. +       dc_printf("%d: %s\n", i, Medals[i].name);
  8730.     }
  8731.  }
  8732.  
  8733. diff --git a/code/stats/scoring.cpp b/code/stats/scoring.cpp
  8734. index c617635..08b4d25 100644
  8735. --- a/code/stats/scoring.cpp
  8736. +++ b/code/stats/scoring.cpp
  8737. @@ -31,6 +31,7 @@
  8738.  #include "network/multi_pmsg.h"
  8739.  #include "ai/ai_profiles.h"
  8740.  #include "pilotfile/pilotfile.h"
  8741. +#include "debugconsole/console.h"
  8742.  
  8743.  /*
  8744.  // uncomment to get extra debug messages when a player scores
  8745. @@ -1509,20 +1510,42 @@ void scoring_bash_rank(player *pl,int rank)
  8746.     pl->stats.rank = rank;
  8747.  }
  8748.  
  8749. -DCF(rank, "changes scoring vars")
  8750. +DCF(rank, "changes player rank")
  8751.  {
  8752. -   if(Dc_command){    
  8753. -       dc_get_arg(ARG_INT);       
  8754. -      
  8755. -       // parse the argument and change things around accordingly     
  8756. -       if((Dc_arg_type & ARG_INT) && (Player != NULL)){                           
  8757. -           scoring_bash_rank(Player,Dc_arg_int);
  8758. -       }      
  8759. +   int rank;
  8760. +
  8761. +   if (dc_optional_string_either("help", "--help")) {
  8762. +       dc_printf("Usage: rank <index>\n");
  8763. +       dc_printf(" <index> The rank index you wish to have. For retail ranks, these correspond to:\n");
  8764. +       dc_printf("\t0 : Ensign\n");
  8765. +       dc_printf("\t1 : Lieutenant Junior Grade\n");
  8766. +       dc_printf("\t2 : Lietenant\n");
  8767. +       dc_printf("\t3 : Lieutenant Commander\n");
  8768. +       dc_printf("\t4 : Commander\n");
  8769. +       dc_printf("\t5 : Captain\n");
  8770. +       dc_printf("\t6 : Commodore\n");
  8771. +       dc_printf("\t7 : Rear Admiral\n");
  8772. +       dc_printf("\t8 : Vice Admiral\n");
  8773. +       dc_printf("\t9 : Admiral\n\n");
  8774. +       return;
  8775. +   }
  8776. +
  8777. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  8778. +       if (Player != NULL) {
  8779. +           dc_printf("Current rank is %i\n", Player->stats.rank);
  8780. +       } else {
  8781. +           dc_printf("Error! Current Player not active or loaded\n");
  8782. +       }
  8783. +   }
  8784. +
  8785. +   dc_stuff_int(&rank);
  8786. +  
  8787. +   // parse the argument and change things around accordingly
  8788. +   if (Player != NULL) {
  8789. +           scoring_bash_rank(Player, rank);
  8790. +   } else {
  8791. +       dc_printf("Error! Current Player not active or loaded\n");
  8792.     }
  8793. -   dc_printf("Usage\n0 : Ensign\n1 : Lieutenant Junior Grade\n");
  8794. -   dc_printf("2 : Lietenant\n3 : Lieutenant Commander\n");
  8795. -   dc_printf("4 : Commander\n5 : Captain\n6 : Commodore\n");
  8796. -   dc_printf("7 : Rear Admiral\n8 : Vice Admiral\n9 : Admiral");
  8797.  }
  8798.  
  8799.  void scoreing_close()
  8800. diff --git a/code/weapon/beam.cpp b/code/weapon/beam.cpp
  8801. index abfe402..a6009ba 100644
  8802. --- a/code/weapon/beam.cpp
  8803. +++ b/code/weapon/beam.cpp
  8804. @@ -36,6 +36,7 @@
  8805.  #include "globalincs/globals.h"
  8806.  #include "cmdline/cmdline.h"
  8807.  #include "parse/scripting.h"
  8808. +#include "debugconsole/console.h"
  8809.  
  8810.  extern int Cmdline_nohtl;
  8811.  // ------------------------------------------------------------------------------------------------
  8812. @@ -119,20 +120,22 @@ float b_whack_small = 2000.0f;    // used to be 500.0f with the retail whack bug
  8813.  float b_whack_big = 10000.0f;  // used to be 1500.0f with the retail whack bug
  8814.  float b_whack_damage = 150.0f;
  8815.  
  8816. -DCF(b_whack_small, "")
  8817. +DCF(b_whack_small, "Sets the whack factor for small whacks (Default is 2000f)")
  8818.  {
  8819. -   dc_get_arg(ARG_FLOAT);
  8820. -   b_whack_small = Dc_arg_float;
  8821. +   dc_stuff_float(&b_whack_small);
  8822.  }
  8823. -DCF(b_whack_big, "")
  8824. +DCF(b_whack_big, "Sets the whack factor for big whacks (Default is 10000f)")
  8825.  {
  8826. -   dc_get_arg(ARG_FLOAT);
  8827. -   b_whack_big = Dc_arg_float;
  8828. +   dc_stuff_float(&b_whack_big);
  8829.  }
  8830. -DCF(b_whack_damage, "")
  8831. +DCF(b_whack_damage, "Sets the whack damage threshold (Default is 150f)")
  8832.  {
  8833. -   dc_get_arg(ARG_FLOAT);
  8834. -   b_whack_damage = Dc_arg_float;
  8835. +   if (dc_optional_string_either("help", "--help")) {
  8836. +       dc_printf("Sets the threshold to determine whether a big whack or a small whack should be applied. Values equal or greater than this threshold will trigger a big whack, while smaller values will trigger a small whack\n");
  8837. +       return;
  8838. +   }
  8839. +
  8840. +   dc_stuff_float(&b_whack_damage);
  8841.  }
  8842.  
  8843.  
  8844. @@ -1254,10 +1257,9 @@ void beam_render(beam *b, float u_offset)
  8845.  
  8846.  // generate particles for the muzzle glow
  8847.  int hack_time = 100;
  8848. -DCF(h_time, "")
  8849. +DCF(h_time, "Sets the hack time for beam muzzle glow (Default is 100)")
  8850.  {
  8851. -   dc_get_arg(ARG_INT);
  8852. -   hack_time = Dc_arg_int;
  8853. +   dc_stuff_int(&hack_time);
  8854.  }
  8855.  
  8856.  void beam_generate_muzzle_particles(beam *b)
  8857. @@ -1479,10 +1481,9 @@ void beam_calc_facing_pts( vec3d *top, vec3d *bot, vec3d *fvec, vec3d *pos, floa
  8858.  
  8859.  // light scale factor
  8860.  float blight = 25.5f;
  8861. -DCF(blight, "")
  8862. +DCF(blight, "Sets the beam light scale factor (Default is 25.5f)")
  8863.  {
  8864. -   dc_get_arg(ARG_FLOAT);
  8865. -   blight = Dc_arg_float;
  8866. +   dc_stuff_float(&blight);
  8867.  }
  8868.  
  8869.  // call to add a light source to a small object
  8870. @@ -3446,12 +3447,11 @@ int beam_will_tool_target(beam *b, object *objp)
  8871.  }
  8872.  
  8873.  float beam_accuracy = 1.0f;
  8874. -DCF(b_aim, "")
  8875. +DCF(b_aim, "Adjusts the beam accuracy factor (Default is 1.0f)")
  8876.  {
  8877. -   dc_get_arg(ARG_FLOAT);
  8878. -   beam_accuracy = Dc_arg_float;
  8879. +   dc_stuff_float(&beam_accuracy);
  8880.  }
  8881. -DCF(beam_list, "")
  8882. +DCF(beam_list, "Lists all beams")
  8883.  {
  8884.     int idx;
  8885.     int b_count = 0;
  8886. diff --git a/code/weapon/corkscrew.cpp b/code/weapon/corkscrew.cpp
  8887. index 9552ff0..c84195f 100644
  8888. --- a/code/weapon/corkscrew.cpp
  8889. +++ b/code/weapon/corkscrew.cpp
  8890. @@ -15,6 +15,7 @@
  8891.  #include "io/timer.h"
  8892.  #include "freespace2/freespace.h"  // for Missiontime
  8893.  #include "object/object.h"
  8894. +#include "debugconsole/console.h"
  8895.  
  8896.  
  8897.  
  8898. @@ -293,41 +294,25 @@ DCF(cscrew, "Listing of corkscrew missile debug console functions")
  8899.  
  8900.  DCF(cscrew_delay, "Change the delay between corkscrew firing")
  8901.  { 
  8902. -   dc_get_arg(ARG_INT);
  8903. -   if(Dc_arg_type & ARG_INT){
  8904. -       Corkscrew_missile_delay = Dc_arg_int;      
  8905. -   }
  8906. -
  8907. +   dc_stuff_int(&Corkscrew_missile_delay);
  8908.     cscrew_display_dcf();
  8909.  }
  8910.  
  8911.  DCF(cscrew_count, "Change the # of corkscrew missiles fired")
  8912.  { 
  8913. -   dc_get_arg(ARG_INT);
  8914. -   if(Dc_arg_type & ARG_INT){
  8915. -       Corkscrew_num_missiles_fired = Dc_arg_int;     
  8916. -   }
  8917. -
  8918. +   dc_stuff_int(&Corkscrew_num_missiles_fired);
  8919.     cscrew_display_dcf();
  8920.  }
  8921.  
  8922.  DCF(cscrew_radius, "Change the radius of corkscrew missiles")
  8923.  { 
  8924. -   dc_get_arg(ARG_FLOAT);
  8925. -   if(Dc_arg_type & ARG_FLOAT){
  8926. -       Corkscrew_radius = Dc_arg_float;
  8927. -   }
  8928. -
  8929. +   dc_stuff_float(&Corkscrew_radius);
  8930.     cscrew_display_dcf();
  8931.  }
  8932.  
  8933.  DCF(cscrew_twist, "Change the rate of the corkscrew twist")
  8934.  {
  8935. -   dc_get_arg(ARG_FLOAT);
  8936. -   if(Dc_arg_type & ARG_FLOAT){
  8937. -       Corkscrew_twist = Dc_arg_float;
  8938. -   }
  8939. -
  8940. +   dc_stuff_float(&Corkscrew_twist);
  8941.     cscrew_display_dcf();
  8942.  }
  8943.  
  8944. @@ -354,11 +339,7 @@ DCF(cscrew_shrink, "Shrink the radius of every other missile")
  8945.  
  8946.  DCF(cscrew_shrinkval, "Change the rate at which the radii shrink")
  8947.  {
  8948. -   dc_get_arg(ARG_FLOAT);
  8949. -   if(Dc_arg_type & ARG_FLOAT){
  8950. -       Corkscrew_shrink_val = Dc_arg_float;
  8951. -   }
  8952. -
  8953. +   dc_stuff_float(&Corkscrew_shrink_val);
  8954.     cscrew_display_dcf();
  8955.  }
  8956.  
  8957. diff --git a/code/weapon/emp.cpp b/code/weapon/emp.cpp
  8958. index ea4e79c..b1cff29 100644
  8959. --- a/code/weapon/emp.cpp
  8960. +++ b/code/weapon/emp.cpp
  8961. @@ -26,6 +26,7 @@
  8962.  #include "iff_defs/iff_defs.h"
  8963.  #include "network/multimsgs.h"
  8964.  #include "network/multi.h"
  8965. +#include "debugconsole/console.h"
  8966.  
  8967.  
  8968.  
  8969. @@ -637,13 +638,12 @@ float emp_current_intensity()
  8970.  DCF(zap, "zap a ship with an EMP effect")
  8971.  {
  8972.     int shipnum;
  8973. +   char ship_str[NAME_LENGTH];
  8974.  
  8975. -   dc_get_arg(ARG_STRING);
  8976. -   if(Dc_arg_type & ARG_STRING){
  8977. -        shipnum = ship_name_lookup(Dc_arg, 1);
  8978. +   dc_stuff_string_white(ship_str, NAME_LENGTH);
  8979. +   shipnum = ship_name_lookup(ship_str, 1);
  8980.  
  8981. -        if(shipnum >= 0){
  8982. -           emp_start_ship(&Objects[Ships[shipnum].objnum], 500.0f, 10.0f);
  8983. -        }
  8984. +   if(shipnum >= 0){
  8985. +       emp_start_ship(&Objects[Ships[shipnum].objnum], 500.0f, 10.0f);
  8986.     }
  8987.  }
  8988. diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp
  8989. index f9c6917..e445c53 100644
  8990. --- a/code/weapon/weapons.cpp
  8991. +++ b/code/weapon/weapons.cpp
  8992. @@ -47,6 +47,7 @@
  8993.  #include "parse/scripting.h"
  8994.  #include "stats/scoring.h"
  8995.  #include "mod_table/mod_table.h"
  8996. +#include "debugconsole/console.h"
  8997.  
  8998.  
  8999.  #ifndef NDEBUG
  9000. @@ -6665,75 +6666,137 @@ void weapon_maybe_spew_particle(object *obj)
  9001.  /**
  9002.   * Debug console functionality
  9003.   */
  9004. -void pspew_display_dcf()
  9005. +void dcf_pspew();
  9006. +DCF(pspew_count, "Number of particles spewed at a time")
  9007.  {
  9008. -   dc_printf("Particle spew settings\n\n");
  9009. -   dc_printf("Particle spew count (pspew_count) : %d\n", Weapon_particle_spew_count);
  9010. -   dc_printf("Particle spew time (pspew_time) : %d\n", Weapon_particle_spew_time);
  9011. -   dc_printf("Particle spew velocity (pspew_vel) : %f\n", Weapon_particle_spew_vel);
  9012. -   dc_printf("Particle spew size (pspew_size) : %f\n", Weapon_particle_spew_radius);
  9013. -   dc_printf("Particle spew lifetime (pspew_life) : %f\n", Weapon_particle_spew_lifetime);
  9014. -   dc_printf("Particle spew scale (psnew_scale) : %f\n", Weapon_particle_spew_scale);
  9015. -}
  9016. +   if (dc_optional_string_either("help", "--help")) {
  9017. +       dcf_pspew();
  9018. +       return;
  9019. +   }
  9020.  
  9021. -DCF(pspew_count, "Number of particles spewed at a time")
  9022. -{ 
  9023. -   dc_get_arg(ARG_INT);
  9024. -   if(Dc_arg_type & ARG_INT){
  9025. -       Weapon_particle_spew_count = Dc_arg_int;
  9026. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  9027. +           dc_printf("Partical count is %i\n", Weapon_particle_spew_count);
  9028. +           return;
  9029.     }
  9030.  
  9031. -   pspew_display_dcf();
  9032. +   dc_stuff_int(&Weapon_particle_spew_count);
  9033. +  
  9034. +   dc_printf("Partical count set to %i\n", Weapon_particle_spew_count);
  9035.  }
  9036.  
  9037.  DCF(pspew_time, "Time between particle spews")
  9038. -{ 
  9039. -   dc_get_arg(ARG_INT);
  9040. -   if(Dc_arg_type & ARG_INT){
  9041. -       Weapon_particle_spew_time = Dc_arg_int;
  9042. +{
  9043. +   if (dc_optional_string_either("help", "--help")) {
  9044. +       dcf_pspew();
  9045. +       return;
  9046. +   }
  9047. +
  9048. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  9049. +       dc_printf("Particle spawn period is %i\n", Weapon_particle_spew_time);
  9050. +       return;
  9051.     }
  9052.  
  9053. -   pspew_display_dcf();
  9054. +   dc_stuff_int(&Weapon_particle_spew_time);
  9055. +
  9056. +   dc_printf("Particle spawn period set to %i\n", Weapon_particle_spew_time);
  9057.  }
  9058.  
  9059.  DCF(pspew_vel, "Relative velocity of particles (0.0 - 1.0)")
  9060. -{ 
  9061. -   dc_get_arg(ARG_FLOAT);
  9062. -   if(Dc_arg_type & ARG_FLOAT){
  9063. -       Weapon_particle_spew_vel = Dc_arg_float;
  9064. +{
  9065. +   if (dc_optional_string_either("help", "--help")) {
  9066. +       dcf_pspew();
  9067. +       return;
  9068.     }
  9069.  
  9070. -   pspew_display_dcf();
  9071. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  9072. +       dc_printf("Particle relative velocity is %f\n", Weapon_particle_spew_vel);
  9073. +       return;
  9074. +   }
  9075. +
  9076. +   dc_stuff_float(&Weapon_particle_spew_vel);
  9077. +
  9078. +   dc_printf("Particle relative velocity set to %f\n", Weapon_particle_spew_vel);
  9079.  }
  9080.  
  9081.  DCF(pspew_size, "Size of spewed particles")
  9082. -{ 
  9083. -   dc_get_arg(ARG_FLOAT);
  9084. -   if(Dc_arg_type & ARG_FLOAT){
  9085. -       Weapon_particle_spew_radius = Dc_arg_float;
  9086. +{
  9087. +   if (dc_optional_string_either("help", "--help")) {
  9088. +       dcf_pspew();
  9089. +       return;
  9090. +   }
  9091. +
  9092. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  9093. +       dc_printf("Particle size is %f\n", Weapon_particle_spew_radius);
  9094. +       return;
  9095.     }
  9096.  
  9097. -   pspew_display_dcf();
  9098. +   dc_stuff_float(&Weapon_particle_spew_radius);
  9099. +
  9100. +   dc_printf("Particle size set to %f\n", Weapon_particle_spew_radius);
  9101.  }
  9102.  
  9103.  DCF(pspew_life, "Lifetime of spewed particles")
  9104. -{ 
  9105. -   dc_get_arg(ARG_FLOAT);
  9106. -   if(Dc_arg_type & ARG_FLOAT){
  9107. -       Weapon_particle_spew_lifetime = Dc_arg_float;
  9108. +{
  9109. +   if (dc_optional_string_either("help", "--help")) {
  9110. +       dcf_pspew();
  9111. +       return;
  9112.     }
  9113.  
  9114. -   pspew_display_dcf();
  9115. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  9116. +       dc_printf("Particle lifetime is %f\n", Weapon_particle_spew_lifetime);
  9117. +       return;
  9118. +   }
  9119. +
  9120. +   dc_stuff_float(&Weapon_particle_spew_lifetime);
  9121. +
  9122. +   dc_printf("Particle lifetime set to %f\n", Weapon_particle_spew_lifetime);
  9123.  }
  9124.  
  9125.  DCF(pspew_scale, "How far away particles are from the weapon path")
  9126. -{ 
  9127. -   dc_get_arg(ARG_FLOAT);
  9128. -   if(Dc_arg_type & ARG_FLOAT){
  9129. -       Weapon_particle_spew_scale = Dc_arg_float;
  9130. +{
  9131. +   if (dc_optional_string_either("help", "--help")) {
  9132. +       dcf_pspew();
  9133. +       return;
  9134.     }
  9135.  
  9136. -   pspew_display_dcf();
  9137. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  9138. +       dc_printf("Particle scale is %f\n", Weapon_particle_spew_scale);
  9139. +   }
  9140. +
  9141. +   dc_stuff_float(&Weapon_particle_spew_scale);
  9142. +
  9143. +   dc_printf("Particle scale set to %f\n", Weapon_particle_spew_scale);
  9144. +}
  9145. +
  9146. +// Help and Status provider
  9147. +DCF(pspew, "Particle spew help and status provider")
  9148. +{
  9149. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  9150. +       dc_printf("Particle spew settings\n\n");
  9151. +
  9152. +       dc_printf(" Count   (pspew_count) : %d\n", Weapon_particle_spew_count);
  9153. +       dc_printf(" Time     (pspew_time) : %d\n", Weapon_particle_spew_time);
  9154. +       dc_printf(" Velocity  (pspew_vel) : %f\n", Weapon_particle_spew_vel);
  9155. +       dc_printf(" Size     (pspew_size) : %f\n", Weapon_particle_spew_radius);
  9156. +       dc_printf(" Lifetime (pspew_life) : %f\n", Weapon_particle_spew_lifetime);
  9157. +       dc_printf(" Scale   (psnew_scale) : %f\n", Weapon_particle_spew_scale);
  9158. +       return;
  9159. +   }
  9160. +
  9161. +   dc_printf("Available particlar spew commands:\n");
  9162. +   dc_printf("pspew_count : %s\n", dcmd_pspew_count.help);
  9163. +   dc_printf("pspew_time  : %s\n", dcmd_pspew_time.help);
  9164. +   dc_printf("pspew_vel   : %s\n", dcmd_pspew_vel.help);
  9165. +   dc_printf("pspew_size  : %s\n", dcmd_pspew_size.help);
  9166. +   dc_printf("pspew_life  : %s\n", dcmd_pspew_life.help);
  9167. +   dc_printf("pspew_scale : %s\n\n", dcmd_pspew_scale.help);
  9168. +
  9169. +   dc_printf("To view status of all pspew settings, type in 'pspew --status'.\n");
  9170. +   dc_printf("Passing '--status' as an argument to any of the individual spew commands will show the status of that variable only.\n\n");
  9171. +
  9172. +   dc_printf("These commands adjust the various properties of the particle spew system, which is used by weapons when they are fired, are in-flight, and die (either by impact or by end of life time.\n");
  9173. +   dc_printf("Generally, a large particle count with small size and scale will result in a nice dense particle spew.\n");
  9174. +   dc_printf("Be advised, this effect is applied to _ALL_ weapons, and as such may drastically reduce framerates on lower powered platforms.\n");
  9175.  }
  9176.  
  9177.  /**
  9178. diff --git a/code/windows_stub/stubs.cpp b/code/windows_stub/stubs.cpp
  9179. index e85f25e..9eaee5e 100644
  9180. --- a/code/windows_stub/stubs.cpp
  9181. +++ b/code/windows_stub/stubs.cpp
  9182. @@ -23,6 +23,7 @@
  9183.  #include "globalincs/pstypes.h"
  9184.  #include "parse/lua.h"
  9185.  #include "cmdline/cmdline.h"
  9186. +#include "debugconsole/console.h"
  9187.  
  9188.  bool env_enabled = false;
  9189.  bool cell_enabled = false;
  9190. diff --git a/projects/MSVC_2011/code.vcxproj b/projects/MSVC_2011/code.vcxproj
  9191. index b116c54..d0b2fa0 100644
  9192. --- a/projects/MSVC_2011/code.vcxproj
  9193. +++ b/projects/MSVC_2011/code.vcxproj
  9194. @@ -529,6 +529,9 @@
  9195.      <ClCompile Include="..\..\code\cutscene\oggplayer.cpp" />
  9196.      <ClCompile Include="..\..\code\Debris\debris.cpp" />
  9197.      <ClCompile Include="..\..\code\DebugConsole\console.cpp" />
  9198. +    <ClCompile Include="..\..\code\debugconsole\consolecmds.cpp" />
  9199. +    <ClCompile Include="..\..\code\debugconsole\consoleparse.cpp" />
  9200. +    <ClCompile Include="..\..\code\debugconsole\timerbar.cpp" />
  9201.      <ClCompile Include="..\..\code\fireball\fireballs.cpp" />
  9202.      <ClCompile Include="..\..\code\fireball\warpineffect.cpp" />
  9203.      <ClCompile Include="..\..\code\gamehelp\contexthelp.cpp" />
  9204. @@ -808,6 +811,9 @@
  9205.      <ClInclude Include="..\..\code\cutscene\mvelib.h" />
  9206.      <ClInclude Include="..\..\code\cutscene\oggplayer.h" />
  9207.      <ClInclude Include="..\..\code\Debris\debris.h" />
  9208. +    <ClInclude Include="..\..\code\debugconsole\console.h" />
  9209. +    <ClInclude Include="..\..\code\debugconsole\consoleparse.h" />
  9210. +    <ClInclude Include="..\..\code\debugconsole\timerbar.h" />
  9211.      <ClInclude Include="..\..\code\DirectX\vasync.h" />
  9212.      <ClInclude Include="..\..\code\DirectX\vdinput.h" />
  9213.      <ClInclude Include="..\..\code\DirectX\vdplay.h" />
  9214. @@ -1097,4 +1103,4 @@
  9215.    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  9216.    <ImportGroup Label="ExtensionTargets">
  9217.    </ImportGroup>
  9218. -</Project>
  9219. \ No newline at end of file
  9220. +</Project>
  9221. diff --git a/projects/MSVC_2011/code.vcxproj.filters b/projects/MSVC_2011/code.vcxproj.filters
  9222. index 932dc5b..8eb6e53 100644
  9223. --- a/projects/MSVC_2011/code.vcxproj.filters
  9224. +++ b/projects/MSVC_2011/code.vcxproj.filters
  9225. @@ -1056,6 +1056,15 @@
  9226.      <ClCompile Include="..\..\code\globalincs\profiling.cpp">
  9227.        <Filter>GlobalIncs</Filter>
  9228.      </ClCompile>
  9229. +    <ClCompile Include="..\..\code\debugconsole\consolecmds.cpp">
  9230. +      <Filter>DebugConsole</Filter>
  9231. +    </ClCompile>
  9232. +    <ClCompile Include="..\..\code\debugconsole\consoleparse.cpp">
  9233. +      <Filter>DebugConsole</Filter>
  9234. +    </ClCompile>
  9235. +    <ClCompile Include="..\..\code\debugconsole\timerbar.cpp">
  9236. +      <Filter>DebugConsole</Filter>
  9237. +    </ClCompile>
  9238.    </ItemGroup>
  9239.    <ItemGroup>
  9240.      <ClInclude Include="..\..\code\ai\ai.h">
  9241. @@ -1855,6 +1864,15 @@
  9242.      </ClInclude>
  9243.      <ClInclude Include="..\..\code\PilotFile\pilotfile.h">
  9244.        <Filter>PilotFile</Filter>
  9245. +    <ClInclude Include="..\..\code\debugconsole\console.h">
  9246. +      <Filter>DebugConsole</Filter>
  9247. +    </ClInclude>
  9248. +    <ClInclude Include="..\..\code\debugconsole\consoleparse.h">
  9249. +      <Filter>DebugConsole</Filter>
  9250. +    </ClInclude>
  9251. +    <ClInclude Include="..\..\code\debugconsole\timerbar.h">
  9252. +      <Filter>DebugConsole</Filter>
  9253. +    </ClInclude>
  9254.      </ClInclude>
  9255.    </ItemGroup>
  9256.    <ItemGroup>
  9257. @@ -1873,4 +1891,4 @@
  9258.        <Filter>Sound</Filter>
  9259.      </CustomBuild>
  9260.    </ItemGroup>
  9261. -</Project>
  9262. \ No newline at end of file
  9263. +</Project>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement