Unfortunately, debugging the RCX is difficult. The key to debugging is to dump information to the LCD, much like you would use a printf or cout statement when programming normally. However, there is a trick to it- remember you aren't in front of an xterm where you can scroll through a list of couts (Unfortunate, isn't it?). As I've already pointed out, there are physical limits to the refresh rate of the LCD. As a result, if you get caught in a loop, your couts will get piped to the LCD faster than the screen can deal with it and it will appear as if the screen is covered with junk. To deal with this problem, you'll need to insert delay loops in the code, effectively pausing the 'bot and the codeuntil the screen can catch up. To insert a delay in the code, use msleep(X) or sleep(X). Alternately, you can insert a wait_event() command, allowing you to look at and contemplate an outputted value until you press a button on the RCX. Depending on the complexity of the code, this might demand a great deal of repetitive button pushing.
I find that a simple function that accepts a string and an int, where the string is an identifier for the int about to be outputted, serves well. This allows you to output the identifier, pause (so you can read it!) and then output the appropriate value to be checked against what you expected. I have also found it useful to make many of my variables universal, so that I can write a function that will cycle through them based on button presses I call while a program is being run. It's bad programming form, but you can always get rid of that when you are satisfied that it works. Similarly, though I have not yet attempted to make this work, it should be possible to make a program pause and continue based on button inputs, while cycling through variables during each pause. This would, of course, require a bit of patience- you would have to check a flag after every function call that you'd wish to check variables after.
Now that LNP is better documented, it is also possible to use it to dump debugging information to your PC. For more details, read the section called Debugging.
This section is included for a variety of reasons: historical interest, nod to the work that has been done, etc... Unfortunately, neither of these work with 0.2.x. May be worth trying, though, if you have a lot of time to fix things up for 0.2.x. The code for both are very well organized, so you may want to check them out if you really, really need an emulator.
For some code problems, running your code in emulation on a PC may help with debugging. Mario Ferrari and Marco Beri have written a LegOS emulator for Windows PCs called emuLegOS. The program is available at http://www.geocities.com/~marioferrari/emulegos.html. A tk based port is also available, which should run on most Unix machines. There are three main issues to consider when looking at emulegOS:
Instead of LegOS's native threading, the emulator uses the pthreads library, which may hide threading problems in your code or in LegOS.
Certain other cross-platform issues may be obscured by the code port, for example, your platform is 32-bit, while LegOS is not, and emuLegOS (or any other emulator, for that matter) cannot catch that type of error on your part.
Depending on how complex and thorough you want the emulation to be, you may have to write emulation for the mechanical aspects of the robot. For the most part, inputting raw values to the sensors should be sufficient. If, however, you would like the program to mimic the full mechanical behavior of your robot (complicated switches and the like) then you may have to write some simple code to mimic those behaviors.
Clearly, none of these should be show-stoppers. I merely point them out to make users aware that certain issues may not be debuggable with an emulator.
There is a program called legOSSim that I can't find the link to right now :)