Oldskooler Ramblings

the unlikely child born of the home computer wars

Archive for the ‘Programming’ Category

Internal conflicts

Posted by Trixter on March 15, 2008

My work-in-progress tracker is my first object-oriented program. This has obvious advantages, such as making a fundamental change in the “abstract” portion of a chunk of the program, and having that change “inherited” by all of that chunk’s “descendants”. For example, I created a “screen” object with descendants for CGA, EGA, monochrome, VGA, and VESA. There was a bug in the cursor handling. I found it (turned out to be a bug in the ROM BIOS, if you can believe that), fixed it, and POOF all of the EGA/VGA/etc. objects now had the fix. From one change. Programming like this is somewhat intoxicating and it results in extremely readable and portable code.

On the other hand, OOP programming results in slower code. There are many C++ and Lisp/Smalltalk programmers out there who will defend to their grave this is not so, but they aren’t coding on a 5MHz machine like I am. (Yes, I am truly programming ON THE HARDWARE ITSELF, not cheating and using a fast PC to develop.) On such a slow machine, I can actually compare different techniques and can notice — sometimes visibly to the naked eye! — how OOP results in slower code than non-OOP. This is mostly due to the fact that nothing in an OOP program is “static” — it’s dynamic, which is best illustrated thusly:

Static program: I want data. I know exactly where the data is. I load the data. I process the data. I put the data back exactly where I found it.

Dynamic/OOP program: I want data. I don’t know where the data is, but I know someone who does. I ask them. They point me to another location. I go to that location. That location has a note saying “the data doesn’t live here any more; you can find them at their new location X.” I go to location X. There is my data! I load the data. I then want to process the data, but my engine was removed and replaced with a note saying “your engine was relocated over at Y.” I go to Y to pick up my engine. I fire up the engine and process my data. I travel back to X to put back my data.

Essentially, pointers no longer point to data or code, they point to other pointers. On fast machines, this double- and triple-pointer loading is no big deal. On an old slow machine where one byte takes 4 cycles to access (as opposed to today’s machines where EIGHT bytes can be accessed in ONE cycle, at clock cycles 800 TIMES faster than me), it adds up quickly. Real world example: My first attempt at repainting the pattern display was asking the song object for every single note in the pattern, then painting each one as I got it. It took two seconds to paint the display. So my optimization was to ask the song object to GIVE ME ONE ROW OF SONG DATA RIGHT NOW, DAMMIT and I process the entire row at once and paint the row. Now it repaints in about 1/10th of a second, which is doable for now. I am angering the OOP gods by doing this. I can hear their displeasure every time it rains.

The obvious tradeoff is flexibility. Let’s put my craptastic illustration skills to work again, this time explaining why OOP is a good thing: Let’s say I want to make something to eat. I have a recipe. I follow the recipe. I get a chocolate cake. I then wish to make apple pie. I change the word “chocolate” to “apple” in my recipe, then “cake” to “pie”. Here is what happens:

Static program: I get a chunk of food matter made of solid apples shaped like a cake and covered in chocolate frosting.

Dynamic/OOP program: I get an apple pie.

So where’s the internal conflict? My project is to create a music program that must be both flexible AND fast. Leaning toward the latter can completely screw up the advantages of the former.

My goal is to have actual music output before I go to bed tonight. Local time is 9:30pm. Better figure it out soon.

Posted in Programming | 10 Comments »

I can see it in my head

Posted by Trixter on March 15, 2008

I ran across a wonderful quote the other day regarding programming. It almost perfectly describes what exactly I enjoy about programming and why:

Programming…is an act of creation. From a simple thought, and the arrangement of a few words and symbols, a reality is created that did not exist before.

No other activity can keep you in the moment the way that writing software can. At each step, one hundred percent of your concentration is applied to the solving of the current problem. Time disappears.

A well written program is a work of art. From conception to final presentation, the activity is that of an artist – the embodiment of a dream world expressed as an interactive experience for the user. — Peter Jennings

I can see MONOTONE in my head; how it works, how it sounds, and what it is like to use it. I hope I can finish it this weekend.

Posted in Programming | 3 Comments »

Slowly, Come, Together

Posted by Trixter on March 4, 2008

In the last two weeks, I have achieved the following in my quest to finish MONOTONE before arriving at Block Party:

  • Gotten the flu (took up three days right there)
  • Wrote a completely customizable abstract input routine (complete with keyboard configuration utility — with tipsheet writer!) because some composers will throw a hissy fit if the basic interface isn’t exactly like ${FAVORITE_TRACKER}
  • Wrote a keyboard interrupt handler (complete with human-readable labels so that “410Ah” reads like “Ctrl+LShift+Alt+F7”) because you never know when some hissy-fit composer will demand the use of Ctrl+LShift+Alt+F7
  • Wrote instantaneous-fast (not an exaggeration) text routines, including multiple virtual screens that use hardware video pages where available

…and I haven’t sounded a single note yet. But you can actually watch the pieces slowly come together now, and it’s pretty damn fun writing from scratch what is essentially turning out to be a miniature operating system.

Next up: The main framework request handler/dispatcher and a finalized abstract Song object (and MONOTONE-specific descendant). Hopefully both tomorrow night, or I’ll have to stop development to work on my presentation :-/

Posted in Demoscene, Programming | 3 Comments »

How I Learned to Stop Worrying and Love the Project

Posted by Trixter on February 21, 2008

One of the things that contributed significantly to MindCandy 2 being delayed for 18 months was self-inflicted implosion. I got so hung up in the project — worrying about what to do, how to do it, when to do it, who was waiting for it, what was affected by it, etc. — that I self-destructed and sought out anything that would help me avoid working on it.

Oh, I wanted to work on it. I love capturing video, especially from older computers doing their thing. I love processing it without touching the picture detail; I love compressing it to within an inch of its life without affecting picture quality. I love distributing it. And I especially loved the subject material. But left unchecked, my mind tends to enter a recursive death-spiral feedback loop during moments of stress and I just spin my mental wheels.

I started to get that hung up over my Block Party plans and obligations. Should I attend? If so, what should I bring? Should I give a talk? If so, on what? Should I bother with a compo entry? If so, what compo? Is it worth going if none of my very close friends will be there? If so, who will I talk to? What talks should I attend? Ahh! Aaaaaaahh!!

Five weeks ago, I was in #blockparty telling s_tec how much I enjoyed the invtro, and after a brief conversation, he innocently stated something that reminded me, after so many years, why I love the scene and all its related offshoots:

[14:49] <__Trixter> Almost makes me want to write a demo again :) but I'm not sure I will. I can't compete with the big boys and this hunk of junk is much slower than my imagination is
[14:50] <s_tec> So? Making demos isn't about winning, it's about making.

It is indeed. Thank you for the reminder; it was cathartic.

With my head cleared, I was able to sort out all of my thoughts, organize them, and get them down on paper (well, into a text file). I have a very clear direction on what I want to accomplish and how to accomplish it. Whether I get it done in time for Block Party ’08 or not, I make daily progress. This is a good thing. The experience, like all fun programming, is not unlike relaxing in a trance-like state punctuated by occasional moments of pure exhilaration.

I am working on creating a nearly useless piece of software. Only a handful of people will ever use it. It serves no practical purpose. But it is mine, created with my bare hands, where nothing like it existed before in the hardware space it commands.

For the curious, here is the some insight into my madness: MONOTONE development notes

Posted in Demoscene, Programming | 4 Comments »

Scope Creep

Posted by Trixter on February 11, 2008

One of the side effects of designing a tracker completely from scratch, using the best software design I can muster, is that everything is virtualized. A song is an object; the player engine is an object; the output device is an object. I’m probably going to make the editor an object itself, if just to keep the source consistent.  The nice thing about objects is that they can be abstracted and used as “parents” for descendant objects. So I have done just that for the internal speaker output. So that leads to some good news and bad news:

The good news is that the tracker will probably come with basic support for the Tandy/PCjr sound chip, and Adlib, and heck probably the CMS as well, out of the box, all in addition to the internal speaker.  This is because once the parent object is done, it’s easy to create a descendant for each output device.  And it will make it easier to add more complex internal speaker support in the future, such as mixing 3 or 4 voices realtime for “true” multichannel output from the speaker.  Just don’t expect the Adlib to sound better than the rest — I have a common denominator to target, and it ain’t 9-channel FM instruments.

The bad news about all this is that the tracker is still mostly in my head and not on paper. Which means I may only have a tracker to enter into the wild compo at Block Party instead of a demo. Or neither, considering that the presentation I’m giving takes precedence over compos :)

If I were never releasing the code, I could’ve hacked something together by this time already.  But I am, and I want people to be impressed by the code as much as music (democoder background, remember?  Both form and function are equally important :-)

Posted in Demoscene, Programming, Vintage Computing | 4 Comments »

My experience is killing me

Posted by Trixter on February 2, 2008

I taught myself Pascal in high school. I was not admitted to the AP course my high school was offering due to my overall GPA, so I taught myself to 1. spite the arrogant jerk of a teacher who denied me, and 2. follow along with the course so I could spend time with my friends. I had been taught other languages (LOGO when I was 12, and BASIC when I was 13) so I wasn’t a stranger to programming. What I was a stranger to, however, was discipline.

My early code, which includes my early demo coding, is sloppy. Oh, the code is nice to look at and doesn’t contain spelling errors, but it is incredibly sloppy. Instead of using REP MOVSW to copy memory around, or even Turbo Pascal’s move() procedure, I would copy one array to another byte by byte. Instead of sorting an array by inserting an array set into a sorted binary tree and then copying it back to the array (heapsort), I would loop through the array and swap crap as necessary (bubblesort). Instead of learning how to use pointers, I would try to trick the compiler into giving me multiple data segments (which had the side effect of bloating the executable). Essentially, I lacked experience, insight, and wisdom — and my programs were buggy and slow as a result.

Today, nearly 20 years later, that is not the case. I still program in Turbo Pascal, but I use pointers/heap, objects, inheritance, and especially in-line assembler in places that need it. I understand proper data structures a lot better now (still struggling with tries, but I’ll get it eventually).  I write my code as if I am delivering it to someone else to maintain.  I can’t say that I am ashamed of anything I’ve written past 1997.

I mention all this because the PC Speaker tracker, something that most people bang out in a day, has taken over two weeks and I haven’t written more than 50 lines of code.   What I have done, however, is:

  • Spent 3 hours writing up various design and structure ideas in a notes file
  • Spent 2 hours last night laying in bed trying to visualize object-oriented tracker design while preventing playback performance from turning to shit (answer: a Song object that controls entering and retrieving note/effect data into the song, and a Player object that retrieves song data one row at a time… still thinking about this one, since a single object makes more sense, but would be harder to virtualize playback methods for other output devices)
  • Spent an hour researching the frequency and amplitude characteristics of Vibrato (not just the human voice, but woodwinds and stringed instruments) so I could be sure to make the best use of the effect bits I have available (answer: most pleasing vibrato has a frequency within 4 to 7Hz and amplitude of about 10 cents)
  • Spent an hour revisiting various tracker formats, looking for ideas on how to pack notes+volume+effects into two bytes (answer: 7 bits for note, 3 bits for effect, 3 for effect 1st parm, 3 for effect 2nd parm)

…but no code.  Yet.

I believe it was the demogroup Silents who proclaimed, “If you can’t do it better, why do it at all?”  That is simultaneously democoding’s greatest motto, motivator, and curse.

Posted in Demoscene, Programming | 5 Comments »

Fine, I’ll do it myself

Posted by Trixter on January 27, 2008

All (and I really do mean all) of the hardware info for low-level PC programming available on the internet today is for ATs and later. Which didn’t help me debug my keyboard handler, as I’m on an XT and the behavior is different.

So I got fed up with looking and decided to just locate the BIOS’ own keyboard handler and see what it’s doing:

c:\>debug
-u f000:0d78
F000:0D78 50            PUSH    AX
F000:0D79 53            PUSH    BX
F000:0D7A 51            PUSH    CX
F000:0D7B 52            PUSH    DX
F000:0D7C 56            PUSH    SI
F000:0D7D 57            PUSH    DI
F000:0D7E 1E            PUSH    DS
F000:0D7F 06            PUSH    ES
F000:0D80 FC            CLD
F000:0D81 E88EEC        CALL    FA12
F000:0D84 E460          IN      AL,60
F000:0D86 93            XCHG    BX,AX
F000:0D87 E461          IN      AL,61
F000:0D89 8AE0          MOV     AH,AL
F000:0D8B 0C80          OR      AL,80 <--Hey, that's
F000:0D8D E661          OUT     61,AL <--new!!
F000:0D8F 86E0          XCHG    AH,AL
F000:0D91 E661          OUT     61,AL
F000:0D93 FB            STI
F000:0D94 93            XCHG    BX,AX
F000:0D95 B44F          MOV     AH,4F
F000:0D97 F9            STC

So, after reading the scan code from port 60h like on ATs and later, the PC/XT is also finding it necessary to acknowledge the scancode by setting bit 7 on port 61. Thanks for nothing, intarweb!

This is an example of why I tell my co-workers at my Unix sysadmin job that my old DOS knowledge from 1983 helps me in all of my computer work: Because basic troubleshooting skills are basic troubleshooting skills. Computers are pretty much the same; if you train yourself to think a certain way, it will lend itself to other computer problems.

If this post seems incoherent and not an example of my best writing, that’s because I just got finished playing my first game of Team Fortress 2 and my vision is still blurred. The last online FPS I played, Counter-Strike, was in 2004… I’m way out of practice and still quite disoriented.

Posted in Programming, Vintage Computing | 2 Comments »

Back to the Future

Posted by Trixter on January 25, 2008

I couldn’t save my old XT keyboard (enter key died, and that’s pretty much the #1 most important key on the damn thing) so it has been tossed into the spare parts bin. My remaining keyboard, however, survived my pokings and I have a functional XT keyboard again. My last, but beggars can’t be choosers.

Thanks to a functional keyboard, I started working on MONOTONE again, starting with the interface (the design docs are done — yes, design docs — hey, stop laughing!) except that I was immediately sidelined by my custom keyboard handler.

A keyboard handler, for the uninitiated, is a little routine that “replaces” the “hold-key-down-and-watch-it-repeat-after-a-short-delay” behavior with “hold-key-down-and-it-stays-down-without-beeping-incessantly” behavior. This is good behavior, if you want to make your keyboard act like a piano. But my trusted old handler code locked up the machine after the first keypress.

Here is the code in question, which I had been using since 1994:

Procedure New9handler; Interrupt;
Var
  b: Byte;
Begin
  port [$20] := $20; {send end-of-interrupt to PIC}
  b := port [$60];   {read scancode from keyboard}
  If b < 128
    Then kbd [b] := True
    Else kbd [b And 127] := False;
End;

On keyboard interrupt, grab a friggin’ character and stuff it in a bitmask array. Easy as pie. Yet the XT locked up, so I am clearly doing something that the XT is allergic to (or, more likely, forgetting to do something). So now I get to research early XT keyboards/signals and try to figure out what I’m doing wrong. Luckily, I have a lot of programming books to consult; here are the ones I’m going to take to bed:

  • Compute’s Mapping the IBM PC and PCjr by Russ Davies
  • The Undocumented PC by Frank Van Gilluwe (founder of V Communications — thanks for Sourcer, Frank!)
  • Sam’s IBM PCjr Assembler Language by David C. Willen (why a PCjr-only book? Because eventually monotone will support PCjr — ssh, keep it a secret!)
  • Compute’s Beginner’s Guide to Machine Language on the IBM PC and PCjr by Christopher D. Metcalf and Marc. B. Sugiyama
  • Assembly Language Primer for the IBM PC & XT by Robert Lafore

Overkill, but I want to check them all so that I can get all the info on handling a keyboard interrupt and then pick out what I need.

I know all this seems stupid and unnecessary, and makes me seem like a freak, but honestly it is the reason over the years I have gravitated towards older and slower platforms to code for fun on. It’s the same reason people still code demos on the Commodore 64 and other legacy platforms: They are fixed in nature, which means you can truly discover the absolute fastest way to accomplish a particular task on them. It’s impossible to do this on a modern winbox, because winboxen are moving targets. It also explains perfectly why modern demos have evolved in the last decade the way they have, but that’s a topic for another day.

PS: The last book by Robert Lafore is the best book you can read to learn assembler on an IBM PC. It teaches you the basics by making you assemble, by hand, in DEBUG. It sounds incredibly scary and hardcore, but it’s actually very fun!

Posted in Demoscene, Programming, Vintage Computing | 6 Comments »

My love/hate relationship with the demoscene

Posted by Trixter on September 1, 2007

I haven’t watched many modern demos in the last 10 years; I usually watch maybe 1 or 2 a year.  My demoscene friends are always shocked when I tell them that, given my past involvement with all things sceneish.  In fact, they’re always shocked, no matter how many times it comes up.  I’m going to try to explain why, briefly, and then hopefully either I will change, or it will never come up again.

In a nutshell, I feel shame and self-loathing when I watch modern Windows demos.   Before that completely confuses you, I’ll hurriedly explain that I always regretted not having the time, skill, intelligence (my math has always been poor), and inclination to create Windows demos.  So when I watch one, I am reminded of how I have failed at that particular aspiration.  I have succeeded at others, but watching a 64K from Fairlight or Farbrausch just gets me depressed.  Yes, I’m screwed up.  The better and more impressive the demo/intro/4k is, the worse I feel.  I know it’s not rational.

So now you know.  This also conveniently explains why I have actually gone backwards in my democoding (I started out on 386+SB+VGA and my latest efforts are geared toward an 8088+PC speaker+CGA) instead of most people, who go forwards.  For example, I’m writing a small utility as a favor to a friend, but it needs to support long filenames in Windows XP and memory over 640K.  Regardless, I’m writing it in DOS, on the XT, because I feel safe and comfortable doing so.  Once it runs within the restrictions of DOS, I’m going to port the code over to WinXP and compile it with a WinXP compiler.

Related topic change: We’ve started talking about MindCandy volume 3.

Posted in Demoscene, Programming | 5 Comments »

Answers

Posted by Trixter on July 3, 2007

Several times in my life, I’ve asked a question that nobody could answer. Sometimes I wait patiently and the answer comes one decade later (such as a walkthrough to Tass Times in Tonetown) or even two decades later (the solution to Hack). Other times, my need for information is too great and I research it myself (8088 Corruption) or architect a solution that can provide me the answer (MobyGames). The latter is a lot of work — I greatly prefer the former, as does everyone. But it doesn’t happen often, and sometimes I write off the entire cause and forget about it.

Today, however, I had one of those moments. I’m a compression geek, with a focus on high-performance decompression. I’ve always wondered how well real-time disk compression products like Stacker, Drivespace, Doublespace, SuperStor, EZDrive, etc. performed. How fast were they at compression? Decompression? How much compression did each achieve on a set of test data? Well, today I stumbled across this:

Real-time Data Compression Algorithms’ Benchmarks

After everyone is in bed tonight, I am setting aside an entire hour with a comfy chair to sit in and a pop to just… soak it all in.

Posted in Programming, Vintage Computing | 4 Comments »