# Friday, April 16, 2010

Tonight, I worked some more on Ubox. Since having been introduced to demos, there has been one effect I’ve always wanted to try coding – the LED-sign style scroller. In theory, it’s easy enough – plot pixels. However, I tried to take it a step further.

My first attempt involved testing copying one array of integers to another, column by column, to simulate the effect of scrolling. While this worked, I quickly realized how inefficient it is. To store the 26 letters of the alphabet as arrays of integers, size 8x8 would require on a 32-bit machine, 4 x 64 x 26 = 6656 bytes, or around 6KB. Doesn’t sound like a lot of memory? It might not be these days, but it’s inefficient as hell. After doing some thinking, I realized that for the scroller, I only wanted two colors – a light red and a dark red. With this in mind, I realized I could do some primitive compression. If we have 8x8 scroller character data, we need to store 64 bits, or 8 bytes of information per character. That works out to two 32-bit integers on a Win32 machine. With this in mind, I cut the space requirement from 6656 bytes to 208 bytes.

To implement this, I built a separate helper program in C#. Enter the worlds worst monochrome graphics editor.

image

Yes, it’s done in WinForms. Yes, I know how to use WPF. Yes, the program is a total hack. But it works. Basically, the checkboxes represent what one would expect to be an “on” state. Output gives me the integer array representing the character data. For instance,

int stuff[53] =
{
0x66663C3C, 0x66667E66, 0x7E82827E, 0x7E82827E, 0x6063C78, 0x783C0606, 0x42427E3E, 0x3E7E4242, 0x3E023E7E, 0x7E3E021E, 0x3E023E7E, 0x202021E, 0x6067E3C, 0x7C7E4676, 0x7E666666, 0x6666667E,
0x18187E7E, 0x7E7E1818, 0x3730FCFC, 0x1E3E3237, 0x1E366606, 0x66361E0E, 0x6060606, 0x3C7E0606, 0xD6FEEEC6, 0xC6C6C6C6, 0xCFC7C3C3, 0xC3E3F3DB, 0x66667E1C, 0x3C7E6666, 0x6666663E, 0x606063E,
0x66667618, 0xD8FE7676, 0x46467E3E, 0x66361E3E, 0x606063C, 0x3C60603C, 0x18183C7E, 0x18181818, 0x66666666, 0x387E6666, 0xC3C3C300, 0x183C66C3, 0xC3C3C3C3, 0x66FEDBDB, 0x183CE7C3, 0xC3C3663C,
0x3C666666, 0x18181818, 0x30607C7E, 0x7E3E0C18, 0x0, 0x0
};

…represents my horribly-drawn 26-character-plus-space alphabet.

Next came the implementation. I keep track of the current “column” being displayed in the scroller, along with the ASCII string being displayed. The ASCII string is used to plot each character.

  1: for(int i = 0; i < 96; i++)
  2: {
  3:   // Drawing routine for pixel scroller.
  4: 
  5:   //  PSet(xLet + (x << scale), 50 + (y << scale), pixDt[2], pixDt[1], pixDt[0], screen);
  6: 
  7:   int currCol = (col + i) % len;
  8:   char letter = scroller[currCol / 8];
  9:   if(letter == 32)
 10:   {
 11:     for(int y = 0; y < 8; y++)
 12:     {
 13:       // col
 14:       PSet(xLet + (i << scale), 125 + (y << scale), 140, 0, 0, screen);
 15:     }
 16:   }
 17:   else
 18:   {
 19:     for(int y = 0; y < 4; y++)
 20:     {
 21:       int realLetter = letter - 0x41;
 22: 
 23:       // Idea: top half is in MSB of stuff[realLetter]
 24:       // bottom in LSB of stuff[realLetter + 1]
 25: 
 26:       int t1 = ((8 * y) + (currCol % 8));
 27:       int t2 = stuff[realLetter * 2] >> t1;
 28:       Uint8 g1 = (t2 & 0x1) == 0x1 ? 255 : 140;
 29:       Uint8 g2 = ((stuff[(realLetter * 2) + 1] >> ((8 * (y + 4)) 
 30:         + (currCol % 8))) & 0x1) == 0x1 ? 255 : 140;
 31:       // col
 32:       int x1 = xLet + (i << scale);
 33:       int y1 = (y << scale);
 34:       int x2 = xLet + (i << scale);
 35:       int y2 = ((y + 4) << scale);
 36: 
 37:       y1 = 125 + y1;// * cos((double)sAngle*3.14/180.0);
 38:       y2 = 125 + y2;// * cos((double)sAngle*3.14/180.0);
 39:       PSet(x1, y1, g1, 0, 0, screen);
 40:       PSet(x2, y2, g2, 0, 0, screen);
 41:     }
 42:   
 43:   }
 44: }
 45: 

That’s the entire source listing for the scroller. The horrible mess of bit-shifts and modulo translates the stored integer into a simple 0x1 or 0x0 for display.

The result looks like this:

Ubox3

Friday, April 16, 2010 1:36:20 AM (Eastern Daylight Time, UTC-04:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, April 14, 2010

Ubox – Enter the Hello World

Ubox1

Ubox-Preview

Music was totally ripped from the Razor 1911 Chipdisk #3. I plan on changing that. The bouncing head is Bob Barker from Robot Chicken. Totally not posting until I find a way to not have to deal with DLL hell. The source is 463 lines long, including whitespace, written in C++ (so it’s no speed demon). I think for a hello-world sort of demo it’s not bad at all. Just need to watch more demos and get inspiration for this.

Did I mention this is only my second completely unmanaged C++ application that isn’t trivial? (The first was my Physics project for grade 12 – a GameBoy Advance ROM. That was some serious fun to work on.)

Wednesday, April 14, 2010 4:23:19 AM (Eastern Daylight Time, UTC-04:00)  #    Disclaimer  |  Comments [0]  | 

Today, after studying for a CS exam for four hours straight, I decided that it would be a good judgment call to write some code. After all, there’s only so much theory one can absorb until code calls. So, I decided to write my first (official) demo. I’m still working on it, and want to compose my own music to it (and make it suck a little less), so it’ll be released later.

I ran into a fun snag along the way, though. I used the SDL libraries to power the graphics of the demo. One library, SDL_Gfx, is not distributed precompiled – you have to compile it yourself. Fortunately, the author includes a Visual C++ Project file that builds just fine. Now, I’ve done some SDL work in the past and had built SDL_Gfx a while ago.

At this point, some readers might see where this is going. As I put some of the hacking finishing touches on the demo, I sent it out to a couple of friends. Of course, it didn’t run on either machine. One was Windows 7, one was Windows XP, and both failed with the same error: The application was unable to start correctly (0x0150002).

A little digging, and the problem pointed to a few solutions – reinstall Windows (yuck), install Visual C++ Express 2008 (double-yuck), or redistribute the debug DLL for Visual C++ 2008 (triple-yuck). This seemed odd to me; I had compiled the demo as a release, non-debug Windows EXE. Why on earth would it need the debug runtime?

Further digging in the event log brought us this error: "Activation context generation failed for "c:\…\release\SDLGFX.DLL". Dependent Assembly Microsoft.VC90.DebugCRT, processorArchitecture="x86", publicKeyToken="1fc8b3b9a1e18e3b", type="win32", version="9.0.21022.8" could not be found. Please use sxstrace.exe for detailed diagnosis."

After a couple of hours of fiddling with manifest files, swearing at SxS, and no luck with the various builds, I stared at the path above. SDLGFX.dll. Then it hit me.

I had built SDL_Gfx as a Debug library in Visual C++ 2008. Crap.

Some swearing and frantic coding later, it works, and runs on other machines. The moral of the story? Always check to make sure your library build type matches your solution type.

I just wish I could have that two hours of my life back.

Wednesday, April 14, 2010 4:12:11 AM (Eastern Daylight Time, UTC-04:00)  #    Disclaimer  |  Comments [0]  |