Tuesday, April 23, 2013

Stuck on Segfault

This time I really and truly wanted to get a links browser build running on the zipit with ttf fonts instead of the fuzzy built-in fonts.  Unfortunately a nasty segfault halted my forward progress like a brick wall.  I swear I'm almost there.  Really.  But apparently not in the mood for a serious debugging  effort.

Before I hit the bricks I made a little bit of progress.  I discovered links apparently has 33 language translations for the menus baked right into the executable, just like the font system.  I removed all but English and French for a 500K RAM savings at runtime and a 100K savings on the jffs.  Not too shabby.  I also devised a simple way of loading one or more of the excised translations at runtime from a shared lib using dlopen, but didn't code it up yet,

Anyhow, this put my free space on the jffs right up around a megabyte.  Sweet!  So I pressed ahead and cut ties with the internal font, roughed in a ttf system based on the plan9 varfont patch, and found myself with a "tiny" 500K upxed links executable that promptly segfaulted.  Aargh!  So close.  I bet if I swapped out the openssl bloat for the tiny matrix ssl library I could get it down around 300K.  Of course, it doesn't work right now.  There's probably some residual piece of the old font system poking at random memory through a bad pointer that I forgot to prune out.  I'll get it, but i need to step away for a moment.

Maybe some relaxing music might get me back into the swing of things?  Well, actually this has been bugging me since the sound system in my fceu build didn't quite work.  I decided to try and port the SDL Drum Toy to get a better idea of how game sound is accomplished.  So I shrunk up the interface from 640x480 to 320x240 for the zipit and gave it a spin.
Heh.  It sounded even crappier than the Super Mario sound running in fceu on the zipit.  But I stuck with it and learned a few things.  Notably, the first 4 sounds in all of the sample music tracks appear to be loaded from .wav files, and work just fine.  The other 12 sounds are typically synthesized at runtime to create an octave of notes, or a few chords.  These FM synthesized notes are generated on the fly at runtime, but about 10 times too slowly for actual use due to the lack of a floating point unit in the zipit processor.   I think this is basically the problem with the fceu sound code.  It can't create sounds fast enough to use them in a timely manner on the zipit hardware.

When I commented out the DrumToy FM synth code, the tracks played at full speed, albeit with only the 4 digital drum sounds.  So I thought maybe if I converted the FM synthesized voices to digital samples on startup then I could play the full musical track.  I allocated a generous 2 seconds worth of samples to each synth voice and suddenly it was taking 3 minutes to bring up the main screen.  That's not so good.  I also botched the formula because the sampled FM synth notes were pure noise.   But at least the tracks were now playing at full speed.  So instead of synthesizing I borrowed the samples from the NDS bliptracker and used them to replace six of the synthesized voices in the demo1 track.  It sounded weird, but it worked.  It looks like you can probably make full use of all 16 voices in the DrumToy if you can find 12 more decent mono .wav files.

This music stuff is kinda fun so I may tinker with it some more, until I feel like taking on the segfault.  There must be some simple integer only synth code out there somewhere, right?  Didn't we have different notes on the PC speaker way back when DOS ran off a flippy floppy?  I may even have a 5 inch floppy in the attic with that sort of code on it.  Too bad I got nothing to read it.

I see there's quite a bit of sample code here.  And this has some fast integer sine functions, with arm assembler code!  Just what the doctor ordered.  The DrumToy FM synth boils down to a few floating point multiplies and two sine calls per sample.  If I can just convert it all to fixed point, that function might just do the trick.

There's also an interesting thread on MilkyTracker at the dingoo forum.  Hmm...

Yeah, so that turned out to be a relatively easy build for the zipit.  It takes almost 30 seconds to load, but seems to work ok.  However it requires the z2mouse which makes it somewhat cumbersome to use.  I might take a look at the keybinding code someday to make it easier to control.  Although I'm not sure how much I can do.  It seems to have a function for every single key on a full PC keyboard.  So any sort of "fix" would just be a trade off for a slightly more usable set of keys.

Since I don't particularly like the dpad "mouse", I thought it might be a good idea to try and dig up something mouseless.  I ran a search for ncurses trackers, but most of that stuff appeared to be rather old.  I built the ancient funktrackerGOLD and managed to play it's example songs, but it reqires an 80 character wide terminal, which forced me to load this nearly unreadable Atari font.
It also sounds like the music is being played underwater.  Is that really the way 8bits used to sound?  No, it's not.  Turns out the mixer code in funktracker uses doubles.  The individual instruments actually sound just fine when played manually via the the single octave on the z row of the keyboard.  I did some experiments reshaping the display for a bigger font, and fixed some nasty stack overrun bugs caused by string overflows.  I'd say this has promise, if I can convert the mixer code to integers.


Update: 

I've spent some time in the DrumToy code and made a little bit of progress.  The integer sine functions seem to work ok.  It can now synthesize the 12 FM notes on the fly, which is pretty cool.  The small errors introduced by the integer math may be changing the tone of the notes somewhat, but it's hard to tell because I've found a bigger problem.  The tempo isn't working right on the zipit.  At some point I noticed the 4 wav sounds seemed to stutter and hang around too long, which got me looking at the code for maintaining the tempo.  It's starting to look like the DrumToy was programmed with a fairly powerful PC in mind.

I'm not sure exactly where the tempo problem originates, but I suspect there's too much wasteful math happening in some of the inner code loops where it should just be moving data out to the audio device.  I did some experiments with reducing the graphics overhead and that quickened the tempo quite a bit, but still not quite up to full speed.  I also did an experiment with no notes playing, not even the wav notes, and it still failed to keep up with the expected 120 beats per minute.  That should never happen.  So I've gotta fix this before I go back and  attempt to smooth out the FM sounds by tweaking the location of the decimal point in the integer math.

Update 2: 

 Heh.  Apparently there was some more sneaky floating point math (that I completely missed) in the saturation_process function.  I commented that out and now it runs at the correct speed.  So it's back to tweaking the integer math in the FM synthesis code.  Gotta find me a few more bits of precision for those low, low notes in the demo1 track.

Actually all of the integer math notes were sounding a bit flat, even to my tin ear.  What's up with that?  I dug up a cheap guitar tuner gizmo and verified it.  They are indeed flat.  Whereas the tuner says the floating point math is generating the true notes.  Hmm, maybe I should go back to double precision floats for the initial frequency calculations, and save the integer math for the runtime sample generation?  Or maybe the integer sine function loses precision as the number of cycles increases?  I don't know, so I think I'll go back and retest it with some additional (more realistic) sample points.

Update 3:

I solved the problem with the flat notes.  It was accumulating errors in the integer math, which pushed all the frequencies off by a few cycles per second.  Now it sounds halfway decent, and the guitar tuner gives it the thumbs up too.  It still needs lotsa work with the location of the decimal point in all of the integer multiplies.  I think there are parts of the code where I'm down to a single bit of precision -- the sign bit -- but it's only supposed to be a "toy", right?  So it'll have to do for now.

Here's a nice blurry video.  Enjoy.


Here's some DrumToy executables for IZ2S and OpenWRT, with the integer FM synthesis source code included.

drumtoy-fm-iz2s.zip
drumtoy-fm-wrt.tgz
drumtoy-fm-wrt-bleeding-edge.tgz

And here's a milkytracker package for IZ2S.


The openwrt package should have shown up in the nightly builds by now.  It's in mozzwald's repo but not yet in the chainxor repo, which probably calculates "nightly" in Australian.

Sunday, April 14, 2013

A File Manager for SDL?

I'd really like to stay focused on converting the flipclock and the links browser from png to ttf fonts, but sometimes the distractions just sorta pop up outta nowhere.  Way, way down on my todo list is a requirement for some sort of file manager for iz2jffs.  Now I don't need it myself because I'm old and the command line was the only game in town when I started using computers.  But I've seen plenty of folks struggling to find their way around when presented with a command prompt.  So when I stumbled on a file manager written in C and SDL on a raspberry pi forum, I figured I had to stop and take a look.   I tweaked a few lines of code to shrink up the display into something a bit more zipit sized, and ended up with this.
It still needs work to make it usable on the zipit, but it shows promise.  Plus it's only about 25k after upxing so it could easily fit on the jffs.  However, first I should decide if it makes more sense to add some basic file manager functions to gmenu2x instead.  Based on the grey function buttons in the image above, there really isn't all that much missing from the gmenu2x base code.

So I took another look at Dingux Commander which has a more polished look, shown here browsing the iz2jffs home directory in the left panel, and the mounted filesystems on the right.
But it's C++, and at 115K it's not such a great candidate to put on the jffs.  However, I thought maybe I could simply fold the code for the split panel view and the file manager functions into the gmenu2x C++ code base without increasing the bloat by all that much.  And as it turns out, folding the Dingux Commander code into gmenu2x (with minimal changes to make it build) only adds about 14K to the total after upxing.  So I guess I should probably provide an executable, and think about rolling another release of the jffs.

Here's a tar file with a new gmenu2x executable and that nice striped background image.  To keep it simple I used the ttf font and icon images from the gmenu2x default skin instead of the ones from Dingux Commander.   If you try it, you should see a shiny new File Manager icon in the applications folder, right next to the Explorer icon.

gmenu2x-cmdr.tgz

After getting the basics working I did some more work on the code to make it fit in better on the jffs.  I altered a few of the key bindings and turned on blended text for a smoother, more readable look.  You can see here its using the smoothed gmenu2x font and the icons from the default gmenu2x theme.  Looks nice.
 
 I also patched the Dingux Commander text file viewer to reuse the gmenu2x code that I created for viewing Latin15 text files.
Finally, I merged the Commander text input code with the gmenu2x input code to enable Latin 15 input via the zipit keyboard instead of the on screen keyboard for the mkdir and rename functions.  Altogether it seemed like a fairly useful addition to the jffs, so I rolled out yet another iz2jffs5 release.


And now I can get back to the ttf stuff.  I took a quick peek the plan9 links-varfont hack and it looks like 90 percent of the conversion from png font to ttf can be done by replacing 3 functions in dip.c:  g_print_text(), g_text_width(), and g_char_width() with the equivalent SDL_ttf functions.  I still need grep for "ifdef PLAN9" and evaluate the rest of the diffs for subtle issues, but it doesn't look too painful...