<?xml version='1.0' encoding='utf-8' ?>
<!--  If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/  -->
<rss version='2.0' xmlns:lj='http://www.livejournal.org/rss/lj/1.0/' xmlns:media='http://search.yahoo.com/mrss/' xmlns:atom10='http://www.w3.org/2005/Atom'>
<channel>
  <title>Informal Methods</title>
  <link>http://ahefner.livejournal.com/</link>
  <description>Informal Methods - LiveJournal.com</description>
  <lastBuildDate>Fri, 08 Jan 2010 19:05:24 GMT</lastBuildDate>
  <generator>LiveJournal / LiveJournal.com</generator>
  <lj:journal>ahefner</lj:journal>
  <lj:journalid>14248520</lj:journalid>
  <lj:journaltype>personal</lj:journaltype>
  <atom10:link rel='hub' href='http://pubsubhubbub.appspot.com/' />
  <image>
    <url>http://l-userpic.livejournal.com/71615828/14248520</url>
    <title>Informal Methods</title>
    <link>http://ahefner.livejournal.com/</link>
    <width>100</width>
    <height>100</height>
  </image>

<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/17020.html</guid>
  <pubDate>Fri, 08 Jan 2010 19:05:24 GMT</pubDate>
  <title>What happened to the NASM x86 instruction set reference?</title>
  <link>http://ahefner.livejournal.com/17020.html</link>
  <description>Recent versions of NASM appear to have shed the instruction set reference which was traditionally an appendix to the manual. In its place is a completely useless list of instructions with no information about them. This is unfortunate, as I&apos;ve probably made more use of that reference more than NASM itself, and I don&apos;t know of anything suitable to replace it - I keep the Intel manuals around, of course, but it might take 20 seconds to find something in the awkward 700 page PDF files, whereas I can do &quot;info nasm&quot; and find the relevant page via incremental search in a few seconds. Several years ago, when I spent much more time crawling around in x86 machine code, the NASM manual was my first stop whenever I had any questions about instruction encodings (although I found a few errors, and sent patches which probably disappeared into the spam-ridden abyss of the nasm list on sourceforge without being applied). I used it often enough that I had either a script or an alias that would run info and open directly to that section. I don&apos;t know why it was eliminated (I&apos;ll guess the developers didn&apos;t feel like maintaining it anymore), but it&apos;s a shame. &lt;br /&gt;&lt;br /&gt;I&apos;ll have to find an old version of NASM and figure out how to extract this section, as there really isn&apos;t any substitute.</description>
  <comments>http://ahefner.livejournal.com/17020.html</comments>
  <category>coding</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/16875.html</guid>
  <pubDate>Sat, 12 Dec 2009 19:15:29 GMT</pubDate>
  <title>Shuffletron bug: dirent.dt_type</title>
  <link>http://ahefner.livejournal.com/16875.html</link>
  <description>&lt;a href=&quot;http://vintage-digital.com/hefner/software/shuffletron/&quot;&gt;Shuffletron&lt;/a&gt;, despite its toyish demeanor, makes an effort to do certain things correctly and efficiently which are critical to its being useful as a music player. To that end, it bypasses the &lt;a href=&quot;http://fare.livejournal.com/139755.html&quot;&gt;hopeless&lt;/a&gt; Common Lisp &lt;a href=&quot;http://www.lispworks.com/documentation/lw50/CLHS/Body/19_ab.htm&quot;&gt;pathname&lt;/a&gt; system in favor of using strings and POSIX system calls, and sidesteps the increasingly prevalent and often misguided &amp;quot;UTF-8 or bust!&amp;quot; mentality in favor of a more robust Unix-like approach of being encoding-agnostic by passing 8-bit characters transparently.&lt;br /&gt;&lt;br /&gt;In particular, I made a point of ensuring that the library scan (a recursive walk of the directory) completes as quickly as possible, within reason. My benchmark was the combination of find and grep, which not only traverses the entire tree but does some useful processing on the result. It&apos;s not possible to reach that speed without writing excessively low-level Lisp code, but I got close enough that I was happy with the result. It may sound surprising for a task like directory traversal, but any cute processing your Lisp&apos;s filesystem interface does - consing/converting strings, decoding characters, building pathnames, converting C structures into nicer Lisp structures, etc. - quickly eats away at this peak performance. Those system calls run a lot faster than I first expected, once the relevant kernel caches are warmed up.&lt;br /&gt;&lt;br /&gt;I&apos;ve been playing with &lt;a href=&quot;http://fuse.sourceforge.net/sshfs.html&quot;&gt;sshfs&lt;/a&gt; this evening and wanted to try using it to access my music library on the other side of the planet from a local Shuffletron instance (with appalling but sufficient latency and bandwidth, despite ostensibly being multi-megabit connections on both sides). Oddly, Shuffletron couldn&apos;t find any files - it said the library was empty. I soon recalled a potential corner I had cut in the filesystem scanning code.&lt;br /&gt;&lt;br /&gt;While scanning the directory tree, you have to figure out whether each entry is a file, directory, or something else. Originally I had done this by calling stat and checking the st_mode field (I&apos;d borrowed the functions from some code that had other reasons to stat the file). While converting the code from sb-posix to &lt;a href=&quot;http://common-lisp.net/project/osicat/&quot;&gt;osicat-posix&lt;/a&gt; for portability to &lt;a href=&quot;http://trac.clozure.com/ccl&quot;&gt;CCL&lt;/a&gt; (and beyond!), I cleaned it up to use the struct dirent.d_type field instead, obviating the call to stat. man 2 stat says this about the d_type field:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Other than Linux, the d_type field is available mainly only on BSD systems.  This field makes it possible to avoid  the  expense  of  calling stat(2)  if  further  actions  depend  on the type of the file.  If the _BSD_SOURCE feature test macro is defined, then glibc defines the  following macro constants for the value returned in d_type:&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;It&apos;s available on Linux (except for old versions)? Great, my program only works on Linux anyway, I&apos;ll use it! So went my reasoning. I had some misgivings on account of  the note &amp;quot;If  the  file  type  could  not  be determined, the value DT_UNKNOWN is returned in d_type,&amp;quot; but it seemed to work well enough, and figured I&apos;d just move on rather than write the extra eight lines (!) of code to deal with what appeared to be an obscure case. &lt;br /&gt;&lt;br /&gt;With sshfs, I finally found that obscure case. The dtype is always set to DT_UNKNOWN, and shuffletron can&apos;t get past the root directory of the library. Despite having written a (&lt;a href=&quot;http://ahefner.livejournal.com/14789.html&quot;&gt;simple&lt;/a&gt;) FUSE filesystem myself, it isn&apos;t immediately clear how you can make that work from the filesystem&apos;s side, but it is clear that it was time to add a fallback to calling stat. Having done so, Shuffletron now happily scans my music library over sshfs, which would be great, except that it also takes something like 15 minutes walk the directory tree (even using find!), because every directory appears to involve several trips over the internet. Hundreds of directories times a few seconds each.. not good (this same thing annoys me when copying multiple small files via SCP, incidentally). Just goes to show that presenting something (a computer many thousands of miles away)  as something it&apos;s not (a local filesystem) can only work so well. If only there were an interface (is there an interface?) to indicate the desired access pattern, so that sshfs could pull all that information quickly in a single batch and keep it in its cache.&lt;br /&gt;&lt;br /&gt;This little fix will be present in the forthcoming Shuffletron 0.0.5 release, along with other great features that I&apos;ve been dutifully testing since July or so. :)</description>
  <comments>http://ahefner.livejournal.com/16875.html</comments>
  <category>shuffletron</category>
  <category>coding</category>
  <category>linux</category>
  <lj:security>public</lj:security>
  <lj:reply-count>3</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/16479.html</guid>
  <pubDate>Fri, 11 Dec 2009 15:28:00 GMT</pubDate>
  <title>Game Design Essentials: 20 RPGs</title>
  <link>http://ahefner.livejournal.com/16479.html</link>
  <description>&lt;p&gt;Although it&apos;s nearly half a year old, I only decently happened upon John Harris&apos;s article &lt;a href=&quot;http://www.gamasutra.com/view/feature/4066/game_design_essentials_20_rpgs.php?print=1&quot;&gt;Game Design Essentials: 20 RPGs&lt;/a&gt;. It discusses the evolution of the CRPG/JRPG genres from war gaming and paper role playing games, surveying many the most influential early series in the genre.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I&apos;m a relative newcomer to the roguelike genre. Aside from some childhood exposure to &lt;a href=&quot;http://www.youtube.com/watch?v=JCsQsKaMAek&quot;&gt;Gateway of Apshai&lt;/a&gt; (a crude action game with Rogue influences), I didn&apos;t play any roguelike games until taking up &lt;a href=&quot;http://en.wikipedia.org/wiki/Nethack&quot;&gt;nethack&lt;/a&gt; sometime in 2006 or 2007. Subsequently the genre has made a big impression on me, providing a solution to certain major problems in game design. Harris appears to agree, as he writes about Nethack:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;Nethack is a roguelike, and so I&apos;m required to say something about one of those games&apos; most controversial features: permadeath. (Okay, I admit it -- I&apos;ve been leading up to this.) Since Ultima and Wizardry, but unlike pen-and-paper games to this day, players are allowed, and even encouraged, to save games and return to them if things go badly, a design characteristic that makes it almost impossible for anything really bad to happen to the player&apos;s characters.&lt;br /&gt;&lt;br /&gt;I make no secret the fact that I consider this one of the most pernicious aspects of CRPG gaming, that permanent disadvantages acquired during the course of play cannot be used by a designer because the player will simply load back to the time before the disadvantage occurred. Admittedly, the prevalence of this attitude comes from some older games that could easily be made unwinnable if the player wasn&apos;t careful.&lt;br /&gt;&lt;br /&gt;However, it&apos;s reached the point where &quot;adventuring&quot; in an RPG rarely feels risky. Gaining experience is supposed to carry the risk of harm and failure. Without that risk, gaining power becomes a foregone conclusion.&lt;br /&gt;&lt;br /&gt;It has reached the point where the mere act of spending time playing the game appears to give players the right to have their characters become more powerful. The obstacles that provide experience become simply an arbitrary wall to scale before more power is granted; this, in a nutshell, is the type of play that has brought us grind, where the journey is simple and boring and the destination is something to be raced to.&lt;br /&gt;&lt;br /&gt;Nethack and many other roguelikes do feature experience gain, but it doesn&apos;t feel like grind. It doesn&apos;t because much of the time the player is gaining experience, he is in danger of sudden, catastrophic failure. When you&apos;re frequently a heartbeat away from death, it&apos;s difficult to become bored. &lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Later, he strikes at the heart of why roguelike game mechanics are so compelling:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;The theory I have about the engagingness of roguelikes is that they are a form of random narrative generator. The ups and downs of the player&apos;s progress becomes that of the story of the character, who has a relatively plain backstory in order to allow the player to invest more of his own personality into him. Most of these stories end in death, but so do our own, and it makes the few stories that make it to the end even more memorable.&lt;br /&gt;&lt;br /&gt;The randomness and difficulty of the game, additionally, help to take responsibility for the failure away from the player. The player knows it&apos;s hard so any progress he makes is a sign of valor and heroism, instead of poor decision-making or foolish risk-taking. These kinds of stories aren&apos;t made up by a script writer; they come from the player&apos;s own actions, so they feel more &quot;real.&quot; &lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Also, on JRPGs and Final Fantasy&apos;s decent into absurdity:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;All RPGs traffic in abstractions. To some degree, an RPG can only be as successful as the extent to which he causes the player to ignore how arbitrary it all is. One of the signs of the aging of the JRPG genre is how its games have, recently, become less careful about how blatantly made-up their various systems are.&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;I&apos;m a huge fan of the original Final Fantasy and became less fond of each successive game in the series, for roughly the same reasons that lead me to claim that Wing Commander 1 is far better than its sequels. Both franchises could be described as &quot;stagnant and wallowing in its own cinematic pretensions,&quot; as Harris says of Final Fantasy. The intrusion of increasingly overwrought stories steal ownership of the character(s) from the player and destroys replayability.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;If that sounds like your thing, give the article a read. It&apos;s quite long. I enjoyed it, and can&apos;t wait to read the rest of the series.&lt;/p&gt;</description>
  <comments>http://ahefner.livejournal.com/16479.html</comments>
  <category>games</category>
  <lj:music>NWA, &quot;Fuck tha Police&quot;</lj:music>
  <media:title type="plain">NWA, &quot;Fuck tha Police&quot;</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/16148.html</guid>
  <pubDate>Fri, 11 Dec 2009 14:34:00 GMT</pubDate>
  <title>Attempting to be grown up..</title>
  <link>http://ahefner.livejournal.com/16148.html</link>
  <description>&lt;p&gt;I&apos;ve long searched for poignant phrase to capture how I feel about a certain style of programming. I&apos;ve finally spotted one courtesy of &lt;a href=&quot;http://www.dadhacker.com/blog/&quot;&gt;Dadhacker&lt;/a&gt;: &quot;an attempt to be &amp;ldquo;grown up&amp;rdquo;. From &lt;a href=&quot;http://www.dadhacker.com/blog/?p=1082&quot;&gt;this post&lt;/a&gt;:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Someone had read the Software Patterns book, because about every third source file implemented a factory; I&amp;rsquo;m pretty sure there were factories for making factories. Now there are perfectly good reasons to write factories, fine and &lt;em&gt;wonderful&lt;/em&gt; reasons to have abstract instantiation, but what was going on in the bulk of this company&amp;rsquo;s code was fear, realized with indirection and thousands of lines of creative procrastination, and an attempt to be &amp;ldquo;grown up&amp;rdquo; with stuff copied from a popular book on design without doing any actual design.&lt;/blockquote&gt;</description>
  <comments>http://ahefner.livejournal.com/16148.html</comments>
  <category>inane</category>
  <category>coding</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/15993.html</guid>
  <pubDate>Tue, 07 Jul 2009 07:56:19 GMT</pubDate>
  <title>Nesemu release 4</title>
  <link>http://ahefner.livejournal.com/15993.html</link>
  <description>I&apos;ve pushed out a new version of my NES emulator sources, flushing out the last six months of accumulated changes. It has been so long that quite honestly have no idea what most of the changes are versus the previous release, except that they don&apos;t improve emulation accuracy at all (in fact, I suspect it has been steadily regressing since release 2. &lt;br /&gt;&lt;br /&gt;I intend for this to be the last release with an ambiguous license. Right now I&amp;nbsp;am constrained by the terms of the M6502 code, which has some &amp;quot;no commercial use&amp;quot; clause in it, preventing me from applying my preferred MIT-style license. I began writing a replacement 6502 core with no strings attached, but that effort has taken a six month hiatus. Rewriting the CPU&amp;nbsp;core will also get me one step closer to cycle-accuracy - close enough that if I were really serious about it, I&apos;d have to rewrite the video... again. Bleh.&lt;br /&gt;&lt;br /&gt;Here are a few changes I&amp;nbsp;do remember:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Keyboard input now works correctly when there&apos;s no joystick connected&lt;/li&gt;&lt;li&gt;Stripe recording (see http://ahefner.livejournal.com/13165.html)&lt;/li&gt;&lt;li&gt;&amp;quot;Screenshot movie mode&amp;quot; (toggled by Control-F12)&lt;/li&gt;&lt;li&gt;FUSE&amp;nbsp;filesystem support, disabled by default (see http://ahefner.livejournal.com/14789.html)&lt;/li&gt;&lt;/ul&gt;The source tarball lives here:&amp;nbsp;http://vintage-digital.com/hefner/software/nes/nes-emu-4.tar.gz&lt;br /&gt;&lt;br /&gt; Also, I&apos;ve started including the git repository in its tarball, tripling its size. I think this is terribly inconsiderate, but I deleted the old git repository on the web server, so I&amp;nbsp;feel like I&amp;nbsp;have to back it up somewhere. I&amp;nbsp;still don&apos;t understand these mixed messages from the git enthusiast crowd, where on the one hand they claim that pushing to a central repository isn&apos;t really done, but then go off and appear to use github for exactly that purpose. Whatever. They are strange people.&lt;br /&gt;</description>
  <comments>http://ahefner.livejournal.com/15993.html</comments>
  <category>nes</category>
  <category>git</category>
  <category>emulation</category>
  <category>8-bit</category>
  <category>linux</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/15783.html</guid>
  <pubDate>Sun, 05 Jul 2009 11:28:41 GMT</pubDate>
  <title>Adventures in Lisp application deployment</title>
  <link>http://ahefner.livejournal.com/15783.html</link>
  <description>&lt;br /&gt;Previously I mentioned my simple music player in CL, &lt;a href=&quot;http://vintage-digital.com/hefner/software/shuffletron/&quot;&gt;Shuffletron&lt;/a&gt;. Shuffletron uses &lt;a href=&quot;http://www.sbcl.org/manual/Saving-a-Core-Image.html#Saving-a-Core-Image&quot;&gt;&lt;tt&gt;save-lisp-and-die&lt;/tt&gt;&lt;/a&gt; on &lt;a href=&quot;http://www.sbcl.org/&quot;&gt;SBCL&lt;/a&gt; or &lt;a href=&quot;http://ccl.clozure.com/manual/chapter4.7.html&quot;&gt;&lt;tt&gt;save-application&lt;/tt&gt;&lt;/a&gt; on &lt;a href=&quot;http://trac.clozure.com/openmcl&quot;&gt;CCL&lt;/a&gt; to create a standalone executable, and is launched by a wrapper script that invokes it with &lt;a href=&quot;http://utopia.knoware.nl/~hlub/rlwrap/&quot;&gt;&lt;tt&gt;rlwrap&lt;/tt&gt;&lt;/a&gt; when available. It depends on several foreign libraries (more than I expected, in fact), and there were an alarming number of problems with the binaries I&apos;d originally posted, all related to these library dependencies. I think I&apos;ve solved them, though not necessarily in an optimal way.&lt;br /&gt;&lt;br /&gt;The first problem, observed and fixed before the publically released binaries, was an issue where &lt;a href=&quot;http://common-lisp.net/project/cffi/manual/html_node/The-Groveller.html&quot;&gt;cffi-grovel&lt;/a&gt; (on behalf of &lt;a href=&quot;http://common-lisp.net/project/osicat/&quot;&gt;Osicat&lt;/a&gt;) created a shared library with some auto-generated C wrappers for various functions, which the saved executable now expected to reopen at startup. I didn&apos;t realize this until my first user reported it dying at startup with an error about not finding &lt;tt&gt;/home/hefner/clbuild/source/osicat/posix/wrappers.so&lt;/tt&gt;, followed by &amp;quot;a lot of lisp-looking gook.&amp;quot; One solution would have been to include the library with the program and install it where SBCL could find it, but at the time I was opposed to including extra libraries with the program, so instead I took the C source to this library and linked it into SBCL&apos;s runtime executable. This has the unfortunate consequence that I have to build the binaries from a customized SBCL, but it solved the immediate problem.&lt;br /&gt;&lt;br /&gt;The next problem was simple - on machines without the libc6 development package installed, the program failed at startup, unable to load &lt;tt&gt;librt&lt;/tt&gt;. This was a simple matter of Osicat not using the best choice of name by which to load the library, a problem which has since been fixed. To be doubly certain, I modified the build script to close this library before saving the executable, because I wasn&apos;t using any functions from it anyway.&lt;br /&gt;&lt;br /&gt;The most aggravating problems I encountered were with the &lt;tt&gt;libmpg123&lt;/tt&gt; library. Some users reported &amp;quot;undefined alien function&amp;quot; errors whenever they tried to play a song. Others reported a scary error about stack alignment as soon as the problem started. To some extent I haven&apos;t solved these (in the sense that Mixalot users and people building from source may still get bitten by them) so much as hacked around them for the sake of the binary release. There were two basic problems:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;On 32-bit Linux, with newer versions of &lt;tt&gt;libmpg123&lt;/tt&gt; than my Debian-running laptop happens to have, the compile-time choice of large file support breaks binary compatibility with the &lt;tt&gt;libmpg123&lt;/tt&gt; library, wreaking havoc with the FFI bindings. Specifically, if large file support is enabled, a number of symbols change names, e.g., &lt;tt&gt;mpg123_open&lt;/tt&gt; becomes &lt;tt&gt;mpg123_open_64&lt;/tt&gt;. This is irritating and not how I&apos;d have done it (for instance, I don&apos;t think the version number of the shared library changes to indicate the break in compatibility), but I could&apos;ve easily worked around it in &lt;tt&gt;mpg123-ffi&lt;/tt&gt; by detecting which version is present at the time the library is initialized. I very nearly did so, were it not for the following problem:&lt;/li&gt;&lt;br /&gt;&lt;li&gt;On 32-bit Linux, due to the desire to have properly aligned data when using SSE instructions, recent versions of GCC provide support for aligning stack frames along larger boundaries, such as 16 bytes. The mpg123 developers seem to take this support as sufficient justification to ignore the platform ABI, introducing dubious stack alignment checks at every entry point to the library. This is not something I know how to work around from the CFFI binding in a reasonable fashion, so for the time being I&apos;ve given up on adapting to such hostile versions of the library. Fortunately, I&apos;ve absorbed enough trivia eavesdropping on the SBCL hackers on IRC to know that Darwin uses 16 byte alignment for precisely the same reason, so SBCL must support it, and after a few minutes searching I hacked the &lt;tt&gt;align-stack-pointer&lt;/tt&gt; macro in SBCL&apos;s x86 backend to enable the 16 byte alignment on Linux as well, which appears to work around the problem (at the cost of my build environment getting even stranger). I also rebuilt the &lt;tt&gt;libmpg123&lt;/tt&gt; library with &lt;tt&gt;--disable-largefile&lt;/tt&gt; and, just to be thorough, &lt;tt&gt;--disable-aligncheck&lt;/tt&gt;, and set my &lt;tt&gt;CFLAGS&lt;/tt&gt; to &lt;tt&gt;-mstackrealign&lt;/tt&gt;, two measures which I think should&apos;ve sufficed to solve the issue even without a hacked SBCL.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;The 32-bit Linux/x86 binary now includes a rebuilt version of &lt;tt&gt;libmpg123&lt;/tt&gt;, renamed &lt;tt&gt;libmixalot-mpg123&lt;/tt&gt;, with these changes. The 64-bit binary doesn&apos;t have any of these problems, and should Just Work, but you have to provide your own &lt;tt&gt;libmpg123&lt;/tt&gt; as before. My mistake, of course, was using &lt;tt&gt;libmpg123&lt;/tt&gt;, but I wasn&apos;t aware of &lt;tt&gt;libmad&lt;/tt&gt; when I made that choice, and I&apos;m not enthusiastic about rewriting otherwise perfectly working code on account of these issues (although I probably will, sooner or later). My current binaries, in conjunction with Shuffletron 0.0.3 (featuring various minor improvements), should be free of these problems, but still haven&apos;t been as widely tested as I&apos;d like. The lesson to me, obvious in retrospect, is to test these things on a more diverse set of configurations than my own machines (particularly when they all run the same release of Debian), even when it seems so simple that nothing could go wrong.&lt;br /&gt;&lt;br /&gt;</description>
  <comments>http://ahefner.livejournal.com/15783.html</comments>
  <category>lisp</category>
  <category>hacks</category>
  <category>oops</category>
  <lj:music>Gorillaz, &quot;Kids with Guns&quot;</lj:music>
  <media:title type="plain">Gorillaz, &quot;Kids with Guns&quot;</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/15501.html</guid>
  <pubDate>Wed, 01 Jul 2009 07:09:24 GMT</pubDate>
  <title>Miscellaneous Lisp Hackery</title>
  <link>http://ahefner.livejournal.com/15501.html</link>
  <description>Here&apos;s a few things I&apos;ve been working on lately which may be of broader interest:&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://vintage-digital.com/hefner/software/bordeaux-fft/manual.html&quot;&gt;Bordeaux-FFT&lt;/a&gt; is a small library for computing the FFT/IFFT&amp;nbsp;on complex data, originally written by Robert Strandh (and/or Sylvain Marchand and Martin Raspaud), with contributions by Paul Khuong and myself. Last summer I did some audio processing experiments, originally using the FFT&amp;nbsp;code from &lt;a href=&quot;http://common-lisp.net/project/sapaclisp/&quot;&gt;Sapaclisp&lt;/a&gt;. Robert helpfully volunteered his FFT&amp;nbsp;implementation, which I cleaned up slightly and have been cheerfully employing in various audio hacks ever since. Several versions have changed hands through email, &lt;a href=&quot;http://paste.lisp.org/&quot;&gt;lisppaste&lt;/a&gt;, and my web server, so I&apos;ve finally come around to collecting the changes, writing a brief manual, and tarring up a release. It&apos;s surprisingly fast, particularly with Paul Khuong&apos;s &lt;a href=&quot;http://www.pvk.ca/Blog/Lisp/SSE_complexes.html&quot;&gt;recent work&lt;/a&gt; on SBCL, although I don&apos;t know how it stacks up against some of the highly tuned assembly language implementations out there. I use it along with my fledgling &lt;a href=&quot;http://vintage-digital.com/hefner/software/message-queue.lisp&quot;&gt;task queuing&lt;/a&gt; code to grind out batches of FFTs across four CPU&amp;nbsp;cores.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://vintage-digital.com/hefner/software/shuffletron/&quot;&gt;Shuffletron&lt;/a&gt; is a simple music player in CL, with a few interesting features. I&apos;ve been running this program full time for several weeks now as my preferred music player. It snuck on to the &lt;a href=&quot;http://www.reddit.com/r/lisp/&quot;&gt;lisp subreddit&lt;/a&gt; before I really announced it, and I&apos;m sure folks on IRC are already sick of hearing about it, so I won&apos;t say much. I began with plans for a much more ambitious player, with a fancy graphical interface, and wrote the first version of this one Saturday realizing I needed something simple to put the audio code through its paces while I&amp;nbsp;wrote the full player, intending to include this one as an example program with &lt;a href=&quot;http://vintage-digital.com/hefner/software/mixalot/mixalot.html&quot;&gt;Mixalot&lt;/a&gt;. It worked better than expected, so I&amp;nbsp;ended up fleshing out the feature set instead and decided that it was really all I&amp;nbsp;needed. The code is lean and mean.&lt;br /&gt;&lt;br /&gt;I&apos;ve had a number of problems trying to produce redistributable binaries of this which I believe I&apos;ve finally solved (although new binaries are forthcoming). I hope to write about these later.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://vintage-digital.com/hefner/software/mixalot/mixalot.html&quot;&gt;Mixalot&lt;/a&gt; is the audio back-end of &lt;a href=&quot;http://vintage-digital.com/hefner/software/shuffletron/&quot;&gt;Shuffletron&lt;/a&gt;, factored into its own system(s) because it might be useful for other purposes. It includes a mixer which pulls audio from any number of streamer objects and outputs them to ALSA. It also includes FFI definitions for libmpg123 with some helpers for decoding MP3 files and reading ID3 tags, and a streamer class for decoding and playing MP3 files in real time. The libmpg123 portions are usable independently of the audio mixing/output code.&lt;/p&gt;</description>
  <comments>http://ahefner.livejournal.com/15501.html</comments>
  <category>lisp</category>
  <category>audio</category>
  <category>hacks</category>
  <category>music</category>
  <lj:security>public</lj:security>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/15113.html</guid>
  <pubDate>Thu, 18 Jun 2009 00:22:46 GMT</pubDate>
  <title>eMusic misses the mark</title>
  <link>http://ahefner.livejournal.com/15113.html</link>
  <description>I&apos;m a couple weeks behind in noticing the announcement by eMusic of their subscription plans and the imminent arrival of the Sony Music back catalog and its promised roster of vapid radio detritus. The cost, apparently, is that they&apos;re raising prices by 50% across the board (or more like 100% for the longtime members with grandfathered subscription plans from the early days of the service), to roughly $0.40 per song. I&apos;ve been a devoted customer of eMusic for several years now, eagerly burning through 200 downloads at a time on one of the $50/month &amp;quot;Connoisseur&amp;quot; plans for much of that time, yet I thought their prices were already too high. This latest move is too much for me to bear, and I immediately used my remaining downloads and cancelled my subscription.&lt;br /&gt;&lt;br /&gt;Perhaps eMusic feels that access to the wider catalog of music will offset the increased cost. If they think their existing subscribers will understand,&lt;strong&gt; they are gravely mistaken.&lt;/strong&gt; Given the option, &lt;strong&gt;I&apos;d rather Sony Music go out of business, their back catalog be destroyed in a fire, and their CEO &lt;/strong&gt;&lt;strong&gt;choke to death on his breakfast.&lt;/strong&gt; &lt;a href=&quot;http://news.cnet.com/8301-13526_3-10254985-27.html&quot;&gt;This article&lt;/a&gt; puts it nicely:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Most eMusic fans I&apos;ve heard from are real music nuts, and are there to sample a wide range of music from relatively unknown cutting-edge acts, not to download music they could find anywhere. Imagine the clerks in High Fidelity suddenly being told that their favorite mail-order distributor is raising prices, but in exchange will now let them order ABBA and Chili Peppers records just like the chain stores in the mall.&lt;/blockquote&gt;&lt;br /&gt;In my brief investigations so far, I haven&apos;t found another music service that is competitive with eMusic, even (perhaps) at their new price point. I don&apos;t consider that an argument for staying with eMusic rather than defecting to another service, though. Given that I consider $0.40/song roughly twice what I&apos;d call a reasonable price, I instead take it as an argument for not buying music online at all. It isn&apos;t like there aren&apos;t &lt;a href=&quot;http://thepiratebay.org/&quot;&gt;alternatives&lt;/a&gt;.</description>
  <comments>http://ahefner.livejournal.com/15113.html</comments>
  <category>rant</category>
  <category>emusic</category>
  <category>music</category>
  <lj:music>Au Revoir Simone, &quot;The Lucky One&quot;</lj:music>
  <media:title type="plain">Au Revoir Simone, &quot;The Lucky One&quot;</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/14898.html</guid>
  <pubDate>Fri, 29 May 2009 03:35:41 GMT</pubDate>
  <title>Linux Audio..</title>
  <link>http://ahefner.livejournal.com/14898.html</link>
  <description>..is a disaster. If the ALSA developers had any honor, they&apos;d fall on their swords, or hurl themselves from the nearest bridge / tall building. dmix is broken and apparently it&apos;s never going to get fixed, which leaves us the alternatives of either using crappy fly-by-night sound servers to hide the problem, or accepting that more than one application playing sound at a time is just too difficult for Linux in 2009. Nevermind that a few years ago, when I used OSS and the emu10k driver for an SB Live (that is, before the Linux kernel developers deprecated OSS), mixing was happily handled by the driver behind the scenes without the quirks or insanely high (and unpredictable) CPU usage that dmix entails, I wasn&apos;t forced to run half my software though the &quot;aoss&quot; wrapper, and games like Quake 3 and Return to Castle Wolfenstein actually worked with sound. Simultaneously, dmix seems the only way to coax sound out of ALSA that isn&apos;t a complete pain in the ass, but the illusion of workingness is soon shattered the first time you catch it spending 40% CPU to (purportedly) resample from 44.1 KHz to 48 KHz. There&apos;s surely a bug here, as the CPU usage is completely unpredictable, and repeatedly opening/closing the device will yield wildly varying results. &lt;br /&gt;&lt;br /&gt;I hate it. All I wanted to do was write a simple goddamn music player.</description>
  <comments>http://ahefner.livejournal.com/14898.html</comments>
  <category>rant</category>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/14789.html</guid>
  <pubDate>Wed, 20 May 2009 05:49:27 GMT</pubDate>
  <title>Emulator introspection with FUSE</title>
  <link>http://ahefner.livejournal.com/14789.html</link>
  <description>This evening&apos;s hack was to write a FUSE filesystem in my NES emulator. I&apos;ve made it export a virtual filesystem that gives you files for the various RAM and ROM areas of the machine, and you can read and write to them. This could be useful for debugging my homebrew stuff. You can also point a hex editor at the 6502&apos;s RAM and edit bytes to cheat, dd /dev/urandom into video ram to glitch the display, etc. Surely peering inside applications through the filesystem is an extension of the Unix way. Here&apos;s what you get:&lt;br /&gt;&lt;pre&gt;

hefner@lightworks:~$ ls -l /tmp/nesfs
total 0
-rw-rw-rw- 1 root root   8192 Dec 31  1969 chr-rom
-rw-rw-rw- 1 root root    256 Dec 31  1969 oam
-rw-rw-rw- 1 root root  32768 Dec 31  1969 prg-rom
-rw-rw-rw- 1 root root   2048 Dec 31  1969 ram
-r--r--r-- 1 root root     22 Dec 31  1969 rom-filename
-r--r--r-- 1 root root     15 Dec 31  1969 rom-hash
-rw-rw-rw- 1 root root   8192 Dec 31  1969 sram
-rw-rw-rw- 1 root root  16384 Dec 31  1969 vram
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I suppose I could fix the other fields in the stat structure. This is the first time I&apos;ve done an ls -l here to notice. The FUSE examples I started from didn&apos;t bother. :)&lt;br /&gt;&lt;br /&gt;This will appear in the next version of my NES emulator, although I can&apos;t say when that will be. Until I feel like spending an unpleasant hour or several learning to do merging with Git, probably.</description>
  <comments>http://ahefner.livejournal.com/14789.html</comments>
  <category>nes</category>
  <category>hacks</category>
  <category>emulation</category>
  <category>8-bit</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/14395.html</guid>
  <pubDate>Sat, 02 May 2009 19:31:49 GMT</pubDate>
  <title>How Rich Countries Die</title>
  <link>http://ahefner.livejournal.com/14395.html</link>
  <description>It&apos;s a month and a half old, but I&amp;nbsp;enjoyed reading this blog post by Philip Greenspun, &lt;a href=&quot;http://blogs.law.harvard.edu/philg/2009/03/16/how-rich-countries-die/&quot;&gt;How Rich Countries Die&lt;/a&gt;, itself examining the book &lt;a href=&quot;http://www.amazon.com/gp/product/0300030797?ie=UTF8&amp;amp;tag=pgreenspun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0300030797&quot;&gt;The Rise and Decline of Nations: Economic Growth, Stagflation, and Social Rigidities&lt;/a&gt;. I particularly enjoyed this paragraph:&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;margin-left: 40px;&quot;&gt;&amp;quot;A cashflow approach is much more effective for figuring out where we&amp;rsquo;re headed.&amp;nbsp; Money flows out to the folks on Wall Street who bankrupted their firms, to schoolteachers who&amp;rsquo;ve failed to teach their students, to government workers who feel that simply showing up to work is a heroic achievement, to executives and union workers in America&amp;rsquo;s oldest and least competitive industries.&amp;nbsp; If times are tough and money is tight, that means almost nothing is left over for productive investment.&amp;nbsp; What would have been a short recession will turn into a long depression and decades of higher taxes and slow growth to pay for all of the cash ladled out.&amp;nbsp; Special interest groups will continue to gain in power.&amp;quot;&lt;/div&gt;&lt;div style=&quot;margin-left: 40px;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;</description>
  <comments>http://ahefner.livejournal.com/14395.html</comments>
  <lj:music>MC Hawkings, &quot;The Hawkman Cometh&quot;</lj:music>
  <media:title type="plain">MC Hawkings, &quot;The Hawkman Cometh&quot;</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/14094.html</guid>
  <pubDate>Fri, 24 Apr 2009 05:24:06 GMT</pubDate>
  <title>Live Distro Swap</title>
  <link>http://ahefner.livejournal.com/14094.html</link>
  <description>I&apos;ve successfully downgraded my Debian machine from Squeeze (testing) to Lenny. I&apos;d never really meant to upgrade&lt;em&gt; to&lt;/em&gt; Squeeze in the first place, but my machine has been set to track testing for a while now. I was more than a little suspicious when it decided it wanted to download over a gigabyte of new packages, but I&apos;m a fool and I&amp;nbsp;was flailing around trying to get something working, so I&amp;nbsp;figured &amp;quot;what the hell&amp;quot;. Anyway, big mistake. I&apos;ve been able to keep using the machine, but the domain resolver is on the fritz, sshd is seemingly in a coma, &lt;strike&gt;Firefox&lt;/strike&gt; Iceweasel is crashing considerably more often than usual, and my printing (which I&amp;nbsp;only got around to configuring two weeks ago) broke. I&apos;m not bitter, but this is a little more bleeding edge than I&apos;m interested in, so it was time to downshift into Debian stable.&lt;br /&gt;&lt;br /&gt;Apparently people have downgraded systems from testing to stable using APT, but this sounded tricky. Just changing the sources list and doing dist-upgrade doesn&apos;t work, and apparently people who have done this have to pin a bunch of packages and somehow fool it into downgrading. Given that most of the info Google turns up on this is seven years old, I&amp;nbsp;didn&apos;t want to risk it. Normally I&apos;d just do another install into a spare partition, but having had such a smooth ride with Debian for so long (I ran the same install for something like five years, until finally moving on to 64-bit), this is the first Linux machine in years I didn&apos;t bother making such a partition on.&lt;br /&gt;&lt;br /&gt;Instead, I&amp;nbsp;installed Debian stable into a subdirectory (/lenny) using debootstrap, chrooted in to install packages, and prepped the /etc directory.&amp;nbsp;Now I&amp;nbsp;was ready to switch systems. I&amp;nbsp;got the statically linked version of busybox and, while still in X11 with music, Firefox, and IRC going, did the following:&lt;br /&gt;&lt;br /&gt;lightworks:/# mkdir sqeeze&lt;br /&gt;lightworks:/# mv bin emul/ etc lib lib32 lib64 sbin usr var squeeze/&lt;br /&gt;lightworks:/# cd lenny/&lt;br /&gt;lightworks:/lenny# mv bin emul/ etc lib lib32 lib64 sbin usr var /&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;lightworks:/lenny# &lt;br /&gt;&lt;br /&gt;Now I&apos;m running Debian stable. Everything is working just fire, except I&amp;nbsp;had to restart firefox, and install some xfont packages for emacs. This is one of those rare instance where I&apos;m genuinely pleased with my operating system. There&apos;s some loose ends to tie up, like configuring X11 (I&apos;m still running the one from sqeeze; I&apos;ll fix it next time I quit X), and some miscellaneous packages to track down, but at this point I&amp;nbsp;think I&apos;ll declare this stunt a success.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;</description>
  <comments>http://ahefner.livejournal.com/14094.html</comments>
  <category>awesome</category>
  <category>linux</category>
  <lj:music>Lucasfilm Games, Ballblazer</lj:music>
  <media:title type="plain">Lucasfilm Games, Ballblazer</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/14017.html</guid>
  <pubDate>Wed, 08 Apr 2009 19:17:42 GMT</pubDate>
  <title>Distribution of students entering classroom over time</title>
  <link>http://ahefner.livejournal.com/14017.html</link>
  <description>&lt;img src=&quot;http://vintage-digital.com/hefner/misc/students.png&quot; /&gt;&lt;br /&gt;* Including instructor (at t=0)</description>
  <comments>http://ahefner.livejournal.com/14017.html</comments>
  <category>inane</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/13588.html</guid>
  <pubDate>Thu, 02 Apr 2009 20:09:05 GMT</pubDate>
  <title>Managing tasks</title>
  <link>http://ahefner.livejournal.com/13588.html</link>
  <description>&lt;p&gt;I&apos;m fiddling with some C code, experimenting with different approaches to various subtasks, some of which depend on previous tasks. Results are valid only for the duration of the current frame. Performance matters, so I tend to comment pieces I&apos;m not currently working on unless they&apos;re needed. For the time being, the data is often only displayed as debugging output, but sometimes the debug display is turned off, making the computation wasteful. Up to this point I&apos;d been juggling the dependencies manually, calling each computation in order from a central point, but finally I&apos;ve gotten restless to automate things. Here&apos;s some cute C preprocessor fun I bashed out a few minutes ago:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;
struct task {
    char *name;
    int last_time;
    int locked;
    void (*taskfn) (void);
};

#define deftask(name) \
  void task_do_##name (void); \
  struct task name = {#name, -1, 0, task_do_##name}; \
  noinline void task_do_##name (void)

static inline void require_task (struct task *task, int time)
{
    assert(task != NULL);
    if (task-&amp;gt;last_time &amp;lt; time) {
        if (task-&amp;gt;locked) {
            fprintf(stderr, &amp;quot;Fatal: Circular dependency on task \&amp;quot;%s\&amp;quot;.\n&amp;quot;, task-&amp;gt;name);
            exit(1);
        }
        task-&amp;gt;locked = 1;
        task-&amp;gt;taskfn();
        task-&amp;gt;last_time = time;
        task-&amp;gt;locked = 0;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;I interface this with my code and the global frame_number as follows:&lt;/p&gt;&lt;br /&gt;&lt;code&gt;#define using(name) require_task(&amp;amp;name, frame_number)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Next I define various tasks. Some depend on others:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;deftask(track_motion)
{
    .. some code here ..
}

deftask(feature_matrix)
{
  .. more code here ..
}

deftask(grid_alignment)
{
    using(track_motion);
    .. yet more code..
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Code elsewhere also relies on the &apos;using&apos; macro to ensure computations are up to date. The components communicate through global state. If they didn&apos;t, and the style were more functional, I supposed I&apos;d be blogging about how I&apos;d implemented memoization instead. Eventually, I might rig this up to farm the computation out to other threads (though this doesn&apos;t seem like such a huge win unless I go back to eagerly computing things in advance of needing them). I&apos;d need a parallel &apos;using&apos; operator.&lt;/p&gt;</description>
  <comments>http://ahefner.livejournal.com/13588.html</comments>
  <category>programming</category>
  <category>c</category>
  <lj:music>Frank Zappa, &quot;San Ber&apos;dino&quot;</lj:music>
  <media:title type="plain">Frank Zappa, &quot;San Ber&apos;dino&quot;</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/13360.html</guid>
  <pubDate>Fri, 20 Mar 2009 01:54:46 GMT</pubDate>
  <title>Two ways out of a recession</title>
  <link>http://ahefner.livejournal.com/13360.html</link>
  <description>What&apos;s the Federal Reserve&apos;s solution to stimulating the economy?&amp;nbsp;My two interpretations (and I&amp;nbsp;Am Not An Economist), each more or less malicious, and both probably inevitable regardless of which (if either) is intended, are as follows:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Plan A&lt;/strong&gt;:&amp;nbsp;Inject massive amounts of money with the aim of creating a new bubble, letting us coast by with another five or six years of illusory prosperity before it all blows up again in an even bigger and more spectacular fashion, leaving it to the next guy to sort out the mess, just like Alan Greenspan did to Bernanke.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Plan B&lt;/strong&gt;:&amp;nbsp;Destroy the currency!&amp;nbsp;Massive inflation! Double, even triple the price of every imported good. What better way to get more people working than to force them to get second jobs (or first jobs, if they&apos;re wealthy or retired). Let the proles claw their way out of the pit while politicians fight to take credit for &amp;quot;solving the crisis,&amp;quot; and Bernanke rests on the seventh day after reaffirming that his powers of economic destruction are not completely impotent.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Barring some miracle of science, like the invention of cheap and bountiful fusion power, I don&apos;t forsee a economic recovery for the United States. The collusion of corporate interests and a reckless and parasitic government is finally going to kill the host. At best, I can imagine stagnation in the near term. After that, a long and unpleasant decline, punctuated by occasional collapses in the house of cards constructed by government and financial interests, as the delusiion of perpetual exponential growth steadily erodes and eats alive both the financial system and (with its impossibly large debts) the US&amp;nbsp;government. All the while, dwindling supplies of petroleum and nuclear fuel will push the chances of recovery and growth further and further out of reach, until civilization as we know it cracks under the pressure and dissolves. For extra fun, toss in the wild card of destructive climate change, if you believe in that sort of thing.&lt;br /&gt;&lt;br /&gt;This scenario is horrifying, so convince me otherwise. Central bankers and politicians are playing god, and every move they make seems destined to trade the future for their own short term gain. It isn&apos;t necessarily maliciousness, just stupidity, desperation, and shortsightedness. Our leaders are going out screaming and flailing -- in quicksand.&lt;br /&gt;</description>
  <comments>http://ahefner.livejournal.com/13360.html</comments>
  <category>rant</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/13165.html</guid>
  <pubDate>Mon, 16 Mar 2009 06:11:36 GMT</pubDate>
  <title>NES Timelapse Hack</title>
  <link>http://ahefner.livejournal.com/13165.html</link>
  <description>I had a silly idea tonight that for a game like Super Mario Bros. where the scrolling follows the player, and the player is usually in the center of the screen, collecting a single column of the screen per frame and combining them horizontally would produce a sort of timelapse image where the player would be seen as a blurred stripe moving through the scenery, which would be stretched or squashed according to the player&apos;s speed. I think I&apos;ve seen something like this before, but in this era of information overload and the futility of trying to find anything in Google, I figured I&apos;d just go ahead and hack it into my emulator rather than searching for prior art. Here&apos;s an example from Super Mario 3:&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://vintage-digital.com/hefner/hacks/nes/stripe/stripe-smb3.png&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;http://vintage-digital.com/hefner/hacks/nes/stripe/smb3-snippet.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It&apos;s a bit rough (and that&apos;s one of the better portions), but you can see the path of Mario hopping from point to point. I tried this with several games:&amp;nbsp;&lt;a href=&quot;http://vintage-digital.com/hefner/hacks/nes/stripe/stripe-smb1.png&quot;&gt;Super Mario Bros. 1&lt;/a&gt;, &lt;a href=&quot;http://vintage-digital.com/hefner/hacks/nes/stripe/stripe-smb3.png&quot;&gt;Super Mario Bros. 3&lt;/a&gt;, &lt;a href=&quot;http://vintage-digital.com/hefner/hacks/nes/stripe/stripe-ducktales.png&quot;&gt;Duck Tales&lt;/a&gt;, and &lt;a href=&quot;http://vintage-digital.com/hefner/hacks/nes/stripe/stripe-lifeforce.png&quot;&gt;Life Force&lt;/a&gt;. In the latter case the game scrolls at a fixed rate, so you get a sort of shabby automap.&lt;br /&gt;&lt;br /&gt;</description>
  <comments>http://ahefner.livejournal.com/13165.html</comments>
  <category>hacks</category>
  <category>games</category>
  <category>8-bit</category>
  <lj:music>Matti Raekallio, Prokofiev Piano Sonata No. 1</lj:music>
  <media:title type="plain">Matti Raekallio, Prokofiev Piano Sonata No. 1</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/12959.html</guid>
  <pubDate>Tue, 03 Mar 2009 20:35:06 GMT</pubDate>
  <title>Reading the FY 2009 Omnibus Appropriations Bill</title>
  <link>http://ahefner.livejournal.com/12959.html</link>
  <description>&lt;div&gt;Rather than griping about it, I though I&apos;d try to read some of last week&apos;s $410 billion spending bill, and get some idea of where the money goes. The &lt;a href=&quot;http://appropriations.house.gov/FY2009_consolidated.shtml&quot;&gt;Commitee on Appropriations&lt;/a&gt; site contains PDFs of the bill and summaries of each section.&lt;br /&gt;&lt;br /&gt;At a glance:&lt;/div&gt;&lt;ul&gt;&lt;li&gt;$20.5 billion: Agriculture, Rural Development, Food and Drug Administration, and Related Agencies&lt;/li&gt;&lt;li&gt;$57.7 billion: Commerce, Justice, Science, and Related Agencies&lt;/li&gt;&lt;li&gt;$33.3 billion: Energy and Water Development&lt;/li&gt;&lt;li&gt;$22.7 billion: Financial Services and General Government&lt;/li&gt;&lt;li&gt;$27.6 billion: Interior, Environment, and Related Agencies&lt;/li&gt;&lt;li&gt;$151.8 billion: Labor, Health and Human Services, Education, and Related Agencies&lt;/li&gt;&lt;li&gt;$4.40 billion: Legislative Branch&lt;/li&gt;&lt;li&gt;$36.6 billion: State, Foreign Operations, and Related Programs&lt;/li&gt;&lt;li&gt;$55.0 billion: Transportation, Housing and Urban Development, and Related Agencies&lt;/li&gt;&lt;li&gt;$0.1 billion (?):&amp;nbsp; Further Provisions Relating to the Department of Homeland Security and Other Matters&lt;/li&gt;&lt;/ul&gt;Those items sum to $409.7 billion, which sounds right. I foolishly thought I&amp;nbsp;could start my way at the top and work down the list:&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://appropriations.house.gov/pdf/AGFY0902-23-09.pdf&quot;&gt;&lt;strong&gt;Division A - Agriculture, Rural Development, Food and Drug Administration, and Related Agencies&lt;/strong&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Total Funding:&amp;nbsp;$20.5 billion&lt;br /&gt;Major items:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Nutrition for Women, Infants, and Children (WIC): $6.9 billion&lt;/li&gt;&lt;li&gt;Rural Development: $2.7 billion&lt;/li&gt;&lt;li&gt;Agricultural Research: $2.3 billion ($1.1 billion for Agricultural Research Service, $1.2 billion for the State Research, Education, and Extension Service)&lt;/li&gt;&lt;li&gt;Food and Drug Administration: $2 billion&lt;/li&gt;&lt;li&gt;International Food Aid (P.L. 480): $1.2 billion&lt;/li&gt;&lt;li&gt;Food Safety and Inspection Service: $972 million&lt;/li&gt;&lt;li&gt;Conservation Programs: $968 million&lt;/li&gt;&lt;li&gt;Other:&amp;nbsp;$3.46 billion ($20.5 billion minus sum of the above)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Lets take a look a WIC, since it&apos;s the biggest item and there&apos;s an obvious typo in the summary: &lt;br /&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;margin-left: 40px;&quot;&gt;&amp;quot;Nutrition for Women, Infants, and Children (WIC): $6.9 billion, $1.2 billion above 2008, to provide proper nutrition to mothers and their children. Rising food costs and the economic downturn are expected to increase participants to 9.1 billion Americans in 2009 - 400,000 more than 2008.&amp;quot;&lt;/div&gt;&lt;br /&gt;9.1 &lt;strong&gt;billion&lt;/strong&gt; Americans?&amp;nbsp;Perhaps they mean 9.1 million. Just dividing the funding level by 9.1 million people, we get about $758 per participant. I found this &lt;a href=&quot;http://www.fns.usda.gov/pd/37WIC_Monthly.htm&quot;&gt;great table&lt;/a&gt; which sheds a little light on the program. &lt;ul&gt;&lt;li&gt;FY 2008 Participants include 2,153,250 women, 2,222,533 infants, and 4,328,516 (presumably non-infant) children. Total participants: 8.7 million in 2008. So the 9.1 million estimate for 2009 sounds reasonable.&lt;/li&gt;&lt;li&gt;FY 2008 Food costs: $4.5 billion, or $521 per participant per year ($43.42 per month, as the table shows).&lt;/li&gt;&lt;li&gt;FY 2008 Nutrition Service and Administrative (NSA) costs: 1.6 billion.&amp;nbsp; From the link above:&amp;nbsp;&amp;quot;Approximately  			two-thirds of total costs are used to provide nutrition education,  			breastfeeding promotion and support, and linkages to health and  			other client services (e.g.,immunization; drug, alcohol and tobacco  			education; referrals to family and child health social programs).&amp;nbsp;  			The remaining third is used for traditional management functions.&amp;quot;&lt;/li&gt;&lt;/ul&gt;I&apos;ll admit this doesn&apos;t seem too criminally inefficient at first glance, at least by Federal government standards, and if anyone cared what I&amp;nbsp;thought I&apos;d probably be lampooned as public enemy number one for panning a program devoted to feeding children, but 1.6 billion for &amp;quot;Nutrition Service and Administrative costs&amp;quot; gives me pause. Nevermind my skepticism toward Federal attempts to educate and disseminate information, and how far outside the scope of this program some of those things seem, let&apos;s just look strictly at the &amp;quot;traditional management functions&amp;quot;. One third of $1.6 billion is $533 million dollars in management and administrative costs. Assume the management costs are split evenly between the actual food program ($4.5 billion) and the remaining 2/3 of the NSA&amp;nbsp;costs (1 billion). That gives us about 82%&amp;nbsp;of the total, or $436 million, devoted to managing food programs. Divided by 8.7 million participants, that&apos;s an administrative overhead of about $50 per person, which seems a bit steep to me for a program that amounts to mailing someone a check every month. This number is rather hypothetical, so I&amp;nbsp;won&apos;t dwell on it. &lt;br /&gt;&lt;br /&gt;Still, I can&apos;t help but think you could just mail every woman, infant, and child in the program a check for $700 (or monthly allotments if you prefer) and still keep a few tens of millions of dollars on the side for printing pamphlets and running TV&amp;nbsp;commercials educating people on nutrition and whatnot.&amp;nbsp;Perhaps it isn&apos;t politically tenable to redistribute wealth without first sanitizing it through a massive bureaucracy. That&apos;s how the middle class gets its cut, I&amp;nbsp;suppose.&lt;br /&gt;&lt;br /&gt;Moving on, Rural Development: $2.7 billion. This strikes me as outrageous, but I&apos;m having trouble discerning from the bill exactly what it entails. It seems to be some combination of loans, rental assistance, various development subsidies, and the broadband initiative. However it works out, I&apos;m opposed on the principle that people who choose to live far away from major population centers ought to pay their own way and not receive their infrastructure at a massively subsidized discount. In a time of financial crisis, it is not clear to me how pouring money into rural areas is a sound investment in economic growth. Probably doesn&apos;t hurt if you&apos;re a representative trying to get reelected, though.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://appropriations.house.gov/pdf/CJSFY0902-23-09.pdf&quot;&gt;&lt;strong&gt;Division B - Commerce, Justice, Science, and Related Agencies&lt;/strong&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;How odd that they lump law enforcement and science together under the same heading.&lt;br /&gt;&lt;br /&gt;Major justice programs:&lt;ul&gt;&lt;li&gt;Federal Bureau of Investigation:&amp;nbsp;$7.1 billion&lt;/li&gt;&lt;li&gt;Federal Bureau of Prisons: $6.2 billion&lt;/li&gt;&lt;li&gt;State and Local Law Enforcement and Crime Prevention Grants:&amp;nbsp;$3.2 billion&lt;/li&gt;&lt;li&gt;Drug Enforcement Administration:&amp;nbsp;$1.9 billion&lt;/li&gt;&lt;li&gt;Bureau of Alcohol, Tobacco, and Firearms:&amp;nbsp;$1.1 billion&lt;/li&gt;&lt;/ul&gt;Major science programs:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;NASA:&amp;nbsp;$17.8 billion&lt;/li&gt;&lt;li&gt;National Science Foundation:&amp;nbsp;$6.5 billion&lt;/li&gt;&lt;li&gt;National Oceanic and Atmospheric Administration:&amp;nbsp;$4.4 billion&lt;/li&gt;&lt;li&gt;Global Climate Change Research:&amp;nbsp;&amp;quot;Nearly $2 billion&amp;quot;&lt;/li&gt;&lt;li&gt;NIST&amp;nbsp;Research:&amp;nbsp;$819 million&lt;/li&gt;&lt;/ul&gt;Other programs:&lt;ul&gt;&lt;li&gt;Census Bureau:&amp;nbsp;$3.1 billion&lt;/li&gt;&lt;/ul&gt;At this point I&amp;nbsp;gave up in despair. I could spend weeks going over this, and the value of much of it (such as most of the items above) seems impossible to quantify. I don&apos;t think this is the way toward getting a clearer idea how the US&amp;nbsp;Goverment really spends these vast mountains of money. And it probably doesn&apos;t matter, since in a few years the US&amp;nbsp;Government will be insolvent and all of these spending programs will collapse. Still, the summaries are at that site for everyone to read.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;</description>
  <comments>http://ahefner.livejournal.com/12959.html</comments>
  <lj:mood>sick</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/12673.html</guid>
  <pubDate>Mon, 02 Mar 2009 21:55:52 GMT</pubDate>
  <title>Noise Music?</title>
  <link>http://ahefner.livejournal.com/12673.html</link>
  <description>So a post about 8-bit &lt;a href=&quot;http://en.wikipedia.org/wiki/Noise_music&quot;&gt;noise music&lt;/a&gt; at &lt;a href=&quot;http://chipflip.wordpress.com/2009/03/02/noise-music/&quot;&gt;chipflip&lt;/a&gt; came through my Google Reader and, while I&apos;m not sure that it qualifies as such, it made me recall this 67 second music experiment I made with MCKC using just the NES&amp;nbsp;noise channel. It&apos;s kind of neat.&lt;br /&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: center;&quot;&gt;Noisejam (&lt;a href=&quot;http://vintage-digital.com/hefner/misc/noisejam.mp3&quot;&gt;mp3&lt;/a&gt;) (&lt;a href=&quot;http://vintage-digital.com/hefner/misc/noisejam.nsf&quot;&gt;nsf&lt;/a&gt;)&lt;/div&gt;&lt;br /&gt;The textual MML format worked&amp;nbsp; very well for rhythms and experimenting with sound parameters, but I never warmed to it for writing melodies. If I&amp;nbsp;play with NES&amp;nbsp;music again in the future, I think I&apos;ll write my own player routine and compiler instead.&lt;br /&gt;&lt;br /&gt;Also, note that due to the steady deterioration of the Linux platform, recording the above NSF&amp;nbsp;file to create the mp3 took me over an hour, and then only because I&amp;nbsp;gave up and used Windows (although I&amp;nbsp;understand the trend is to make this sort of thing increasingly painful there too). If Debian still provided me with xmms and the NSF-player plugin, this would have taken less than 30 seconds, and I&amp;nbsp;wouldn&apos;t be ranting to whoever will listen about how I&amp;nbsp;want to boil the ALSA&amp;nbsp;developers alive in hot oil.&lt;br /&gt;</description>
  <comments>http://ahefner.livejournal.com/12673.html</comments>
  <category>8-bit. music</category>
  <lj:music>Slick Rick, &quot;Mona Lisa&quot;</lj:music>
  <media:title type="plain">Slick Rick, &quot;Mona Lisa&quot;</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/12368.html</guid>
  <pubDate>Sun, 22 Feb 2009 01:50:37 GMT</pubDate>
  <title>NES DAC Linearity, Part I</title>
  <link>http://ahefner.livejournal.com/12368.html</link>
  <description>In my ongoing adventure tinkering with the NES, one thing I&amp;nbsp;had to try was playing some music through the built-in DAC. It&apos;s 7-bit, and you can get reasonable audio quality if you don&apos;t mind devoting the whole CPU (and quite a lot of memory) to it. I threw together a little demo that plays an 8 second music loop at around 30 KHz. Once the novelty of hearing it work wore off, I&amp;nbsp;noticed the audio was distorted, particularly audible in the cymbols. Once I&amp;nbsp;confirmed it wasn&apos;t just on my own emulator that it sounded distorted, I thought back to implementing my own NES&amp;nbsp;sound emulation, primarily using &lt;a href=&quot;http://nesdev.parodius.com/apu_ref.txt&quot;&gt;apu_ref.txt&lt;/a&gt; as a reference. Toward the end of that document is an equation which models how the sound channels are mixed together, which is obviously not linear. Curious, I made a plot of DAC input versus mixer output (actually, I&amp;nbsp;wrote a 6502 program which writes a ramp waveform to the DAC and captured the output). It&apos;s *extremely* bowed in the middle (see below), explaining the distortion. It was straightforward invert the curve and preprocess my audio accordingly, which improved the audio considerably. &lt;br /&gt;&lt;br /&gt;I get the impression many emulators follow a curve similar to the one described in that document. I tried my test on Nestopia, FCEU, and (of course) my own emulator, and they behave similarly in this respect. On the other hand, Nintendulator seems to mix channels differently, because my original version of the audio test sounds better there. Unfortunately, I&amp;nbsp;haven&apos;t tried this on a real NES yet, because it&apos;s bigger (256KB) than I&amp;nbsp;can conveniently program to an EPROM right now, and&amp;nbsp;I&apos;ve have to build a new EPROM cart to host it even so (my current one only handles 64 KB). I should probably just buy a PowerPak and/or a CopyNES, but I&apos;m still enjoying desoldering donor carts and playing with chips. =p&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://vintage-digital.com/hefner/hacks/nes/audio-test-2-linear.nes&quot;&gt;DAC&amp;nbsp;Music Loop Test (linear version)&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://vintage-digital.com/hefner/hacks/nes/audio-test-2-fancy.nes&quot;&gt;DAC&amp;nbsp;Music Loop Test (adjusted version)&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;If I couldn&apos;t try the full music loop on a real NES, at least I could write some simpler test programs and run them from my EPROM&amp;nbsp;cart. It also occured to me that aside from the nonlinearity due to the channel mixing, there might be some additional nonlinearity inherent in the DAC, significant enough for someone trying to get the best audio they could from the machine, and it&apos;d be interesting to try and measure. For my first attempts at this, I took the approach of generating test signals in software from the NES, recording into my MOTU audio interface from the NES audio output, analyzing the resulting recordings with a little CL code, and finally plotting the results using Octave (shown below).&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&amp;quot;Square rising edge&amp;quot; - a square wave at a few hundred&amp;nbsp;Hz (220?&amp;nbsp;440?&amp;nbsp;I forget.), increasing in amplitude each cycle from 0 to 127. I measured the height of the rising edge. I&amp;nbsp;let this repeat 29 times and averaged the results.&amp;nbsp;I&amp;nbsp;screwed the program up and only captured every other amplitude level (incrementing the amplitude variable on every clock edge instead of just one).&lt;/li&gt;&lt;li&gt;&amp;quot;Pulse 1&amp;quot; - Same idea, ramping up the amplitude of a brief pulse. I&amp;nbsp;measured the height of the largest rising (or rather falling) edge in the viscinity of the pulse. I&amp;nbsp;let this loop for 20 or 30 minutes, averaging out 1,440 samples per amplitude level. The individual ramps didn&apos;t look right, having a curious moire-like modulation as the energy of the pulse fell differently into samples, but it averaged out into a very nice curve. Unfortunately, it was different enough from the previous curve to bother me, although it shared some common features.&lt;/li&gt;&lt;li&gt;&amp;quot;Pulse 2&amp;quot; - I&amp;nbsp;thought I&apos;d try lengthening the pulse, hoping I&amp;nbsp;might get cleaner data. Instead I got the opposite - the resulting curve, even average over 1,300 samples per amplitude level, is extremely jagged and irregular. I haven&apos;t figured out what went wrong here&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://vintage-digital.com/hefner/hacks/nes/nes-dac-plot-2.png&quot;&gt;&lt;img height=&quot;448&quot; width=&quot;627&quot; src=&quot;http://vintage-digital.com/hefner/hacks/nes/nes-dac-plot-2-small.png&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&amp;nbsp;&lt;/div&gt;I&amp;nbsp;can imagine various sources of systematic error that invalidate these measurements, but (ignoring the screwy &amp;quot;Pulse 2&amp;quot;&amp;nbsp;measurements) there&apos;s a really interesting feature apparent. - namely, the jumps occuring around power of two transitions, most prominent in the three highest bits of the DAC&amp;nbsp;input. &lt;br /&gt;&lt;br /&gt;I&apos;d really hoped these measurements would agree, so that I&amp;nbsp;could divide out the affect of the mixer equation and have something like a definitive measurement of the DAC linearity which I&amp;nbsp;could build into my emulator (and use to correct audio for playback on the real hardware). As it is, I&apos;ll have to try again. It would probably make a lot more sense to measure from the output pin on the NES CPU, rather than measuring after it has passed through the final mixing and filtering circuits, but&amp;nbsp;I&amp;nbsp;haven&apos;t tried this yet. Ideally I could program a DC level into the DAC and measure it on the output pin at my leisure. To this end I put together a little DAC test program which lets you select the output level and toggle the signal on and off. This program, along with various other hacks including the signal generators for the three tests above, is on my &lt;a href=&quot;http://vintage-digital.com/hefner/hacks/nes/test2-mmc3.nes&quot;&gt;NES test cart image&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;</description>
  <comments>http://ahefner.livejournal.com/12368.html</comments>
  <category>nes</category>
  <category>hacks</category>
  <category>8-bit</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/12146.html</guid>
  <pubDate>Sun, 08 Feb 2009 06:04:09 GMT</pubDate>
  <title>The Uplift Mofo Secure Copy Client</title>
  <link>http://ahefner.livejournal.com/12146.html</link>
  <description>I&apos;ve been using WinSCP between my Windows and Linux machines more frequently than I&apos;d prefer lately. My observation is that having two panes with lists of files side by side (&amp;quot;Norton Commander style&amp;quot;) can be a horrible interface for copying files with the mouse, because it forces you to be careful where you drop the source file. You perhaps first have to scroll the destination pane down a ways so that you don&apos;t accidentally copy the file into some subdirectory of the intended target (like I&amp;nbsp;think I&amp;nbsp;just did a moment, since the file is nowhere to be seen). Even then, you can get potentially funny interactions, e.g. dropping the copied file on a zip file might store it in that zip file (which I&amp;nbsp;also just did a moment ago). Of course, if there are enough files in the destination directory that you have to scroll, you won&apos;t have a nice safe empty area to drop the file on, so you instead you have to wave the mouse around for a second until you find a position that, for whatever reason, targets the directory itself instead of the files in it, as indicated by the highlighting.</description>
  <comments>http://ahefner.livejournal.com/12146.html</comments>
  <category>inane</category>
  <lj:music>Chrono Trigger OST, &quot;Time Circuits&quot;</lj:music>
  <media:title type="plain">Chrono Trigger OST, &quot;Time Circuits&quot;</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/11799.html</guid>
  <pubDate>Sat, 31 Jan 2009 04:45:21 GMT</pubDate>
  <title>Burn your congressman</title>
  <link>http://ahefner.livejournal.com/11799.html</link>
  <description>I don&apos;t know about anyone else, but I&amp;nbsp;find this bailout business equal parts infuriating, terrifying, and absurd. Their soiution to the popping of an economic bubble is to create a new one using more pretend money?&amp;nbsp;When the bailout money dries up in a couple years, what happens when we discover that the current &amp;quot;downturn&amp;quot; is really a return to normalcy, and they just pissed all that money down the toilet? That malignant tumor centered in Washington, DC, the ultimate single point of failure, will run this country into the ground sooner rather than later. If I&amp;nbsp;had any idea what to do with my modest USD&amp;nbsp;savings, I&apos;d cash out in a hurry.&lt;br /&gt;&lt;br /&gt;Economic stimulus?&amp;nbsp;It&apos;s a shell game.&lt;br /&gt;&lt;br /&gt;Update 2/10/09:&amp;nbsp;I&amp;nbsp;think the stock market agrees with me!</description>
  <comments>http://ahefner.livejournal.com/11799.html</comments>
  <category>rant</category>
  <lj:music>The Presets, The Girl and the Sea</lj:music>
  <media:title type="plain">The Presets, The Girl and the Sea</media:title>
  <lj:mood>pissed off</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/11670.html</guid>
  <pubDate>Tue, 13 Jan 2009 04:29:34 GMT</pubDate>
  <title>NES Palette Tricks</title>
  <link>http://ahefner.livejournal.com/11670.html</link>
  <description>I said I&amp;nbsp;was going to stop working on the emulator, but I couldn&apos;t help it. Falling asleep the other night, I&amp;nbsp;realized I could make my emulator run Blargg&apos;s very cool &lt;a href=&quot;http://nesdev.parodius.com/bbs/viewtopic.php?t=1209&quot;&gt;full palette demos&lt;/a&gt; with a few minor changes. The way these demos use mid-scanline writes are more interesting than they appear at first glance, and emulating it taught me a few new things about the NES&amp;nbsp;hardware.&lt;br /&gt;&lt;br /&gt;These demos demonstrate the full color palette which the NES&amp;nbsp;is capable of - 410 colors - on the screen simultaneously. This is done via the trickery of changing the palette registers mid-scanline, 14 times, in conjunction with using color emphasis bits every several scanlines. The NES&amp;nbsp;color palette is typically cited as containing 52 unique colors, but the aforementioned color emphasis bits allow tinting of the video output, producing additional colors. &lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://vintage-digital.com/hefner/hacks/nes/misc/full-palette.png&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;br /&gt;The CPU&amp;nbsp;does not have direct access to the palette registers, which exist in the PPU address space, therefore the CPU&amp;nbsp;must access them through writes to a pair of address and data registers. The address register is also used by the PPU during rendering, therefore background (and supposedly sprite) rendering must be disabled in order to write to the palette mid-scanline. Writes to the data register autoincrement the address by your choice of 1 or 32 bytes.&lt;br /&gt;&lt;br /&gt;Since rendering is disabled, you&apos;d expect it necessary to continually change the zeroth palette register at $3F00, whch controls the overall background color. If the address register were configured to increment by 1, we&apos;d have to reload the address each time to reset it to $3F00. Adding two absolute store instructions to reset the address would take 8 clock cycles each time. The CPU&amp;nbsp;is very slow compared to the video signal - an NTSC&amp;nbsp;NES PPU&amp;nbsp;outputs 3 pixels during each CPU cycle, so 8 CPU&amp;nbsp;cycles would increase the width of each color cell in the picture above by 24 pixels. They wouldn&apos;t fit on the screen!&amp;nbsp;Alternatively, the 32 byte increment mode (really intended for updating vertical stripes of background tiles) saves us this trouble, because the palette registers repeat every 32 bytes between $3F00 and $3FFF, so each increment leaves us pointing at a mirror of the $3F00 palette register ($3F20, $3f40, etc.) This works until the eighth write, when we wrap around to $0000, which isn&apos;t a palette register at all. At that time, we&apos;d still have to do our two writes to reset the address to $3F00, introducing a wider stripe in the middle of the screen which clearly doesn&apos;t exist in the screenshot above. Or perhaps you could do three writes (the address is latched after the first two), so that you only have to do one write to reset the address, but that&apos;s not what&apos;s going on here.&lt;br /&gt;&lt;br /&gt;So how does it do it? The demo relies on two odd features of the hardware. Most importantly (and perhaps by accident), when rendering is disabled and the address register points at a palette register, that color will be displayed rather than the expected background palette entry (that is, $3F00). This allows the built-in autoincrement by 1 to cycle through which palette register will determine the color at the current raster position. Because this is a post-increment, the display color will always be ahead of the colors we&apos;re writing, so it actually displays the palette entries we programmed on the previous scanline, but this isn&apos;t a problem. Using this approach, unrolling the two instruction loop &amp;quot;stx $2007; inx&amp;quot; allows us to change the color in 4+2=6 CPU cycles, or every 18 pixels, which corresponds to the width of each color stripe in the screenshot. Notice that the color stripes are not smooth, but rather have a rough edge. To the best of my knowledge it is not possible to synchronize precisely with the previous scanline and straighten this out, because the scanline width in pixels (including the horizontal blank) is not an integral number of CPU&amp;nbsp;cycles.&lt;br /&gt;&lt;br /&gt;The other peculiar point, which might occur to anyone familiar with the NES&amp;nbsp;hardware, is that the machine really organizes palettes into groups of three colors (plus a background/transparency color) each, four for background tiles, and four for sprites. Despite having four distinct palettes which can be applied to background characters, normally the first entry of each mirrors the overall background color in the first palette, at $3F00. If that held in this case, one in every four of those color stripes would be the wrong color, which isn&apos;t occurring. So it seems there are three more palette registers ($3F04, $3F08, $3F0C), but during normal rendering they all defer to $3F00, which seems a tremendous waste (unless, of course, you can explain this in a way which doesn&apos;t require these three registers to exist, such as the last written color value getting latched somewhere, but that&apos;s not what the guys who&apos;ve actually done the reverse engineering say). I&amp;nbsp;wonder what the rationale was for designing it that way.&lt;br /&gt;&lt;br /&gt;With respect to the emulator, I realized I only needed to add one or two lines of code to emulate this effect. During normal rendering, my background and sprites are rendered instantaneously at the start of the scanline. If the palette were to change in the middle of that, it would indeed require reworking the video rendering so that you could interleave it with the CPU&amp;nbsp;execution, mindful of timing (being called upon to catch up with the CPU after some number of cycles when a control register is about to be changed). My audio code already works in this way, as does the handling of the color attribute and mono bits (which are filled in a buffer parallel to the current line&apos;s color buffer and combined by the video output filter before the next line). Then I&amp;nbsp;realized I&apos;d overlooked the obvious - you only do these mid-scanline palette tricks when rendering is disabled anyway, so I&apos;m free to fill over the contents of the color buffer using the same catchup mechanism. So it fell out for free.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;</description>
  <comments>http://ahefner.livejournal.com/11670.html</comments>
  <category>emulation</category>
  <category>coding</category>
  <category>8-bit</category>
  <lj:music>Roni Size, &quot;New Forms&quot;</lj:music>
  <media:title type="plain">Roni Size, &quot;New Forms&quot;</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/11322.html</guid>
  <pubDate>Fri, 09 Jan 2009 08:36:42 GMT</pubDate>
  <title>Easy to learn, difficult to master</title>
  <link>http://ahefner.livejournal.com/11322.html</link>
  <description>Eight or nine years ago I wrote a crude NES emulator. It could play some very simple games, including SMB1 (with a glitchy status bar), but not much else. I&apos;d done some earlier homebrew experiments with the NES, which I was able to test only in emulators, but put all that on hold when I switched to Linux as my primary operating system due to lack of usable emulators. So instead, I wrote my own (crappy) emulator.&lt;br /&gt;&lt;br /&gt;Every three or four years, I&apos;ve pulled this code off the shelf and made minor improvements to it. This year over the holidays I really got sucked into it, and whipped the thing into pretty good shape. It can now run much of the commercial and homebrew NES software I&apos;ve tried with little or no issue, and the audio sounds accurate to my ears. It can run fullscreen, use gamepads, and supports save/restore state, so by my standards it&apos;s ready for recreational use, even if (in this era of cycle-accurate emulators like Nintendulator and Nestopia) it doesn&apos;t offer anything new. Just what the world needs, another mediocre NES emulator, right? For this reason, I&amp;nbsp;bestow upon it no frou-frou name, dumping it anonymously onto the net.&lt;br /&gt;&lt;br /&gt;The renderer is scanline-based, except for color emphasis and the grayscale flag, which are tracked with pixel accuracy. This lets me emulate most of the interesting scanline-based effects, like the wavy water in the CMC Wall demo, the nifty copper bars demo, or (my favorite) the light beam effect when you light an orb in Final Fantasy.&lt;div style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;img alt=&quot;&quot; src=&quot;http://vintage-digital.com/hefner/hacks/nes/misc/copper.png&quot; /&gt; &lt;img alt=&quot;&quot; src=&quot;http://vintage-digital.com/hefner/hacks/nes/misc/ff1-orb-light.png&quot; /&gt; &lt;br /&gt;&lt;img alt=&quot;&quot; src=&quot;http://vintage-digital.com/hefner/hacks/nes/misc/wall.png&quot; /&gt;&lt;/div&gt;&lt;br /&gt;Although it&apos;s probably pass&amp;eacute; in this era of exact NTSC composite video emulation (dot crawl, artifacts, and all), I added a neat interlaced scanlines mode entirely for the sake of seeing how this classic highres interlacing demo might look:&lt;br /&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;http://vintage-digital.com/hefner/hacks/nes/misc/moby.png&quot; /&gt;&lt;/div&gt;&lt;br /&gt;I don&apos;t think the effect would work on a real NES. As I&amp;nbsp;understand it, the NES&amp;nbsp;video output is not interlaced (that is, opposite video fields aren&apos;t offset, so you&apos;d just see the two images flickering overtop each other). This might be the first thing I&amp;nbsp;try when I&amp;nbsp;finally get some kind of NES&amp;nbsp;devcart put together.&lt;br /&gt;&lt;br /&gt;Incidentally, if there were an award for Best Graphic Design in an 8-Bit Videogame Title Screen, I think Darkwing Duck would take it. Too bad the game doesn&apos;t live up to the title screen. &lt;div style=&quot;text-align: center;&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;http://vintage-digital.com/hefner/hacks/nes/misc/darkwing.png&quot; /&gt;&lt;/div&gt;&lt;br /&gt;Having spent more time than I care to trying to nail the correct timing and behavior of the MMC3 IRQ counter, I&apos;m thoroughly sick of messing with it for now. Plus, this way I&apos;ll leave plenty left do this time next year when I return to it (precise timing, MMC3 quirks. MMC2 and MMC5, etc). In the mean time, I can play Zelda, Final Fantasy, SMB1-3, and pretty much every NES game I&apos;d actually want to play, perfectly well. I know the hacker machismo of the nesdev community demands you emulate every obscure Japanese game and one-off pirate mapper, but I can think of more interesting things to do. :)&lt;br /&gt;&lt;br /&gt;I also used this project as a guinea pig to learn how to use Git, or attempt to - an effort I would classify as a failure and a waste of hours of time. It&apos;s really astonishing how unintuitive and opaque Git is, and how completely useless every tutorial I&apos;ve seen on the web is (which all explain how to create a repository, make a commit or two, then go off rambling about semi-obscure operations without ever explaining the rest of the things you&apos;ll need to know every single day or presenting any kind of usable workflow). &lt;br /&gt;&lt;br /&gt;All I wanted was a way to push/pull changes back and forth between my desktop and laptop via a copy of the repository on my web server as a backup / public repository. After much pain I think I did figure out the correct magic incantations (pull --rebase, etc.), but with the accumulated frustration, the last straw was noticing that all the web-visible source files were ancient versions, and that a git-status on the server&apos;s repository indicated a backward view of the repository (as if it wanted to commit the ancient version over top the newest work). In fact, I still don&apos;t know how to fix this, and it&apos;s probably easy, but at this point I don&apos;t care. I&apos;m nuking the thing from orbit, because practically anything would be better than having to make three backups of my repository and spend half an hour on google every time I want to use the version control system. CVS would be better. Hell, diff, patch, and some duct tape would be better. Or cp -r. Or pretty much anything that doesn&apos;t have &amp;quot;detached heads.&amp;quot;&lt;br /&gt;&lt;br /&gt;Anyway, I dumped the code at http://vintage-digital.com/hefner/hacks/nes/ for safekeeping (git be damned).</description>
  <comments>http://ahefner.livejournal.com/11322.html</comments>
  <category>nes</category>
  <category>games</category>
  <category>coding</category>
  <category>8-bit</category>
  <lj:music>Mastodon, &quot;Shadows That Move&quot;</lj:music>
  <media:title type="plain">Mastodon, &quot;Shadows That Move&quot;</media:title>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/11072.html</guid>
  <pubDate>Fri, 09 Jan 2009 01:31:48 GMT</pubDate>
  <title>Low-fi 3D</title>
  <link>http://ahefner.livejournal.com/11072.html</link>
  <description>It occurs to me just now that you could write a sweet version of Wolfenstein 3D on an Atari 8-bit (or virtually anything else with memory to spare and allowing scanline tricks).. so long as you don&apos;t mind turning your monitor on its side to play it. :)&lt;br /&gt;&lt;br /&gt;The principle is the same as all the racing games that used per-scanline scrolling changes to depict a curving track, but turned on its side, with walls instead of roads. Each scanline becomes a vertical slice of the display, and you precompute these for the columns of your wall texture at various scaling distances. Back of the envelope calculations suggest that these prescaled textures would consume a lot of memory, so you&apos;d have to settle for very small/simple textures, store them in a large ROM (or precompute them into large RAM, e.g. 320 XE), or compute some of the intermediate scalings at runtime. This leads me to wonder how much time it would take to determine the visible surfaces each frame. Could be interesting.</description>
  <comments>http://ahefner.livejournal.com/11072.html</comments>
  <category>inane</category>
  <category>coding</category>
  <category>8-bit</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://ahefner.livejournal.com/10798.html</guid>
  <pubDate>Sat, 20 Dec 2008 23:58:37 GMT</pubDate>
  <title>One hdsentinel data point</title>
  <link>http://ahefner.livejournal.com/10798.html</link>
  <description>HDsentinel output:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
HDD Device  0: /dev/sda
HDD Model ID : HTS541080G9AT00
HDD Serial No: MPB4AAX6GRTSVF
HDD Revision : MB4IA60A
HDD Size     : 76319 MB
Interface    : IDE/ATA
Temperature  : 31 Â°C
Health       : 69 %
Performance  : 100 %
Power on time: 299 days, 3 hours
Est. lifetime: 726 days
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is a disk in a laptop which consistently corrupts data written to it (e.g. I copied a 4 GB file and only the first 1 GB was readable, it has eaten dozens of mp3 files, etc.) and routinely fails SMART self-tests, which, god willing, I will replace tonight. I&apos;ve tried scrubbing away the bad sectors by reading/writing to prompt the disk to relocate them, but it hasn&apos;t been enough. I don&apos;t think the SMART reporting of this Hitachi disk is very good, though.</description>
  <comments>http://ahefner.livejournal.com/10798.html</comments>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
</channel>
</rss>
