Race Condition Solved

It was a race condition. If a program attempts to alter one of the DS’ DMA addresses whilst that DMA channel has an operation in progress, the DMA channel goes bonkers and doesn’t carry out either operation. This generally isn’t a problem when we work with VRAM, but the SuperBitmap works with main memory which is notably slower. The SuperBitmap’s DMA instructions were treading on each other’s feet.

I’ve added a new macro into woopsifuncs.h - “DMA_Active()“. This returns true if the DMA channel is still active, and false if not. All of the SuperBitmap functions now wait until the DMA channel is inactive before releasing control of the DS back to the rest of the code, which finally seems to have solved the problem. I hope.

I’ve also added DMA_Copy2(), DMA_Force2() and DMA_Active2() macros, which are identical to the original functions except that they work with the second DMA channel. The original functions work with the third channel (there are four channels, but they are named using a zero-based convention and the “first” channel is correctly termed the “zero” channel).

Having the SDL version available is a massive help when trying to track down tricky bugs. The first thing I’ve done with it is get the MultiLineTextBox working with the ScrollingPanel. The debug console can now be scrolled up to reveal previous lines of text; it stores up to 50 lines in its buffer. There are a couple of newly-introduced bugs in the textbox, though - vertical alignments other than “top” don’t work, and scrolling at a particular pace seems to cause the occasional line to be incompletely drawn.

Some neat Xcode features I’ve discovered:

  • Built-in SVN client. Haven’t tried it yet, though.
  • Word completion, browser address bar style.
  • Hit “Escape” to bring up a Visual Studio-esque word list.
  • Breakpoints!
  • The “restart” button in the debugger - which resets the exe back to its initial state - is a great idea.
  • Variable display is always visible by default in the debugger; no mucking about hovering over things in order to work out what their values are.
  • The “fix” button in the debugger compiles any changes you’ve made to the code and patches the exe as it is running - no need to restart and get back to the same state. Superb.
  • The debugger’s callstack browser.
  • Code folding.
  • Generated class diagrams.
  • MallocDebug! Excellent idea.
  • Leaks! An even better idea. I found one leak in the TextViewer, but (astonishingly) everything else seems water tight.

There’s loads of good stuff in here. The “Instruments” panel is a spectacularly good feature, especially when you remember that Xcode is a freebie with the OS. Digging around in all of these new toys has left me wondering how I’ve managed to write 500K of code without a debugger.


Jeff on 2007-12-29 at 00:32 said:

With respect to the DMA_Active() macro, etc, I was going to say just dump PALib’s wrappers altogether and use the ones provided by libnds.

ie, in <<nds/dma.h> there are dmaCopyWords(), etc all of which take a DMA channel number.

However, I think they (libnds) have things around the wrong way - given what DMA does, you should not wait AFTER you start the operation, you should wait BEFORE. By waiting before, the operation, you ensure that you only wait if the hardware is “still doing the previous request” - if you prime it then go on doing other processing in parallel (with the limitation that memory is still tied up), you stand a good chance of getting a few more instructions in before you submit your next request, at which time the DMA hardware will probably be finished, whereas if you wait afterwards, you introduce mandatory delays that may well be avoidable.

ant on 2007-12-29 at 12:13 said:

Good point. Tch, those libnds guys.

(Hurriedly rushes off to move the while() loops to a different location.)