Sean Middleditch » 2003 » September

NVIDIA Driver Update Script

My NVIDIA driver script seems to work. Go me! On boot, if the NVIDIA module can’t be found, can’t be found but won’t load, or if the nvidia-installer –sanity check fails, the installer will be asked to redownload, rebuild, and reinstall the driver.

It’s not really perfect, tho. For one, if the build fails, the user is screwed - the machine will continue trying to boot into X (assuming that’s how your machine is setup, and that is the kind of setup my script’s target user has), and will thus fail quite soon.

The fix there is, aside from just making the driver always build (many times its not the drivers fault - the user may not have kernel source or headers for her new kernel installed), allowing X to bootup with a minimal driver a la Windows’ Safe Mode. Sure, it sucks, and it’s not that great for us techies (we’d rather not waste time booting into a crippled X, but instead go straight to the console and fix the problem, right?), but it’ll let a normal user get online, contact NVIDIA support, etc.

Another problem is if the user doesn’t have ‘net access on bootup. The nvidia-installer utility doesn’t cache the source/package download (bad bad naughty NVIDIA!), so it’ll always try to redownload it. If the user has a dial-up connection, she’s pretty much screwed, since Linux is all wonderful and super and has no built-in dial-up handling like Windows, meaning the user has to get into X, manually bring up the connection, and then reinstall the driver. Except she can’t, because now she’s in X, and it’s not good to mess with X drivers right then.

To make things really super perfect, I’d have to:

a) manually cache the NVIDIA source download, or beg/pray for NVIDIA to add that to their next driver release.

b) magically get all major distros to support a nice standard system-unified way of finding and launching the ‘net connection for dial-up users. (Really, a system API for that would *rule* - any app that needs a ‘net connection can test if one exists, and if not, bring up the ‘net connection, or popup a system-standard “Select Connection” dialouge, a la Windows.)

c) magically get all major distros to support fall-back X mode over SVGA. Would probably also need to modify XFree86 to support this as well - not sure if there’s any roadblocks to this feature in the code or not.

d) magically give all distros a command for ‘fetch the source and/or headers for the currently running kernel’, which will also depend on (b).

Of all those, I can do (a) on my own. (b) is an issue that should be solved completely independently of this script/project, and I’m amazed no one’s done it yet. I’ll have to bring it up on Free Desktop or something, would be an excellent user feature. (c) is something I think a couple distros support, it’s more just something the distro needs to learn to do on their own for their users to be nice. (d) is isn’t going to happen, altho my script could probably have a ‘fetch_kernel_headers’ routine that could be customized for each major distro - use up2date or yum on Redhate, urpmi on Mandrake, yast2 on SuSE, apt-get on Debian, etc. Finding the running kernel is easy, and hopefully all those distros name their header/source packages easily.

Final Fantasy Tactics Advance

This game is quite fun. I didn’t think it so great when I first played it, but its quickly grown on me. I’m also rather proud that I’ve managed to figure out how most of the rather complicated system works without reading a single word of the instruction manual. I, and most people I know, almost never read manuals for games, but this is one of those games you generally should read. Which I probably will, soon, since I’m starting to hit the limits of what I can figure out thru trial, error, and observation. ~,^

The game truly is interesting tho. It seems to have a plot (altho its a cheesy one, so far), very interesting combat system, and is just plain fun. Glad I bought it. Now if only Sword of Mana and Fire Emblem would hurry up and come out… (Sword of Mana especially, I’m drooling over the thought - Secret of Mana on the SNES was one of the best console games ever.)

Oh, and on a game-related note, I got Diablo II for ~$10 today. The poor fools at Media Play put a “mary-kate-ashely-act” price marker on the box, and whatever that is (movie? game? not sure), it only cost $10 versus the $40 all the rest of the boxes had. And of course, if they mismark it, they have to sell it to me at that price. Of course, the guy at the checkout counter didn’t even notice, so I didn’t have to do the usual manager talks, which I guess is good. I love it when stores screw up to my advantage. ^,^

Garbage Collection

My LibSGC package I wrote for AweMUD and Scriptix is getting close to being removed. It simply takes too much effort to use (so much for the S standading for Simple, eh?), and it’s really not at all that efficient. The Boehm-Demer-Weiser libgc would be so much nicer. I just need to find the time to rip out LibSGC and replace it.

Magic Strings

The other related problem (memory management) is string usage. I have plenty of places in AweMUD where I have pointers to a C-style string, usually a substring, and I want to them as arguments to a function. The problem is, it’s really unclean to definte the functions/members as taking a const char* argument, especially when most of the users of the function/method will be using Strings. But, if the function takes a String, then the C string will be pointless copied.

Most C++ string implementations, including the GNU libstdc++ std::string, make use of reference counting and copy on write. With some small tweaks, this system could solve the above problem.

Basically, you’d have three states: a string is in use by multiple objects (refs > 1), the string is unique to the client (refs == 1), or the string is “global” (refs == 0). The global string case is my addition. Basically, the copy-on-write will always copy if the refs are 0. What this allows, tho, is to construct a String object that holds a pointer to a constant C string (be it a string literal, or just some various C string), and which is guaranteed not to modify it.

If the coder tries to assign a global string to another variable, a copy will be made. If the coder tries to modify a global string, a copy is made (just as if there were multiple clients using the string - which is what a global string basically is). The whole idea is, basically, for functions that need a String argument that they aren’t going to modify, you can pass in C strings without worrying about excessive pointless copying (and the memory waste and cache abuse that involves). If the function/member tries to store the string long term (in another String object), it’s copied.

Also, if you have a const char* argument type, and the function/member then tried to store it, you’d be making wasteful copies if the original data came from a String. If a String was used as the argument, storing that string would only require a quick reference count increment. If a C stirng is passed in, converted from the String, then no reference count can be done, so a copy is forced.

Now, my only problem is that I have to make this specialized String class, and then put it in a library (oh joy, yet another string library). I really don’t want to do all that release pain and maintenance for what’s going to be, basically, one header and one small source file. ::sigh::

Serial Port Logging

My fears were well founded, reading from a serial port is going to be more complicated than open()/read(). On the upside, instead of having to code all that, I found a nice package designed for this task. In fact, the README even says it was written for logging information from a phone system, the very reason I need this. ^,^

Of course, the big problem wasn’t really coding it (I’m always ready to learn), but figuring out which all options I need - what baud rate, flow control, etc., since we have no access to the phone system settings or the printer specifications. And we really don’t want to rely on the telecommunications company, they rather suck. ::sigh::

Fedora Linux

Really not liking the direction Red Hat is taking with Fedora. I mean, really, if I wanted a distro stuffed with tons of packages made by random people with no overall goal or plan, I’d use Debian. The great part of Red Hat Linux was that the system was completely packaged and supported by Red Hat, who had clear cut goals and policies.

I can easily see Fedora turning into something like Debian. Which would be horrible. I moved off of Debian for a reason. For starts, there are so many crap packages shoved in that distro, all for no good reason other than because they can. Nobody really needs 4 version of the ‘more’ command, but you can probably find that many in Debian these days. (I know there are at least two I’ve used.) And then you get all the over-engineered insane nonsense they add it to support this mess, like the alternatives system. That thing is about as pointless and unnecessary as it can get. Well, it would be, if you didn’t decide to shove 12 graphical browsers and 20 text ones into one distro. Seriously, pick one of each, and leave it at that. Sheesh.

Also, Mandrake, SuSE, Xandros, Lindows, Lycoris, and just about every other major to semi-major desktop player is super KDE focused, which means I’ve no interest in them. I honestly can’t stand KDE, and rather liked Red Hat (and Debian) as they didn’t try to shove it down my throat. Heck, it bugs me that I even have to have Qt installed because of the redhat-artwork dependencies. ~,^ I guess unless Ximian/Novell comes out with a desktop distro (pleaaase? a Ximian distro would be pure bliss!), I’m going to be stuck with Fedora.

On the upside, things seem to be moving in a positive direction so far. Core utilities are being updated to get rid of a lot of the Red Hat lock-in, a few more useful utilities are being added, and Red Hat is saying they’ll keep a tight rain on development; hopefully things won’t degrade to the Debian/SuSE “too much shit that no one needs, and over-engineered beyond sanity” level of uselessness. Hopefully.

Class

Back to class, after a month of none. I already feel like I’ve forgotten how to study. Drat.

On the upside, the class is Physics. This should mean it’ll be interesting (versus classes like socialogy). Also, unlike most of the classes at my college, where the majority of students are 40+ years of age (its a community college, so many people there are folks coming back to finish degrees or get additional degrees, or doing training for their job), the classes like physics I and such tend to have a higher percentage of people near my age. You know, people going to college for the first time, right after high school. But then, on the downside, I don’t really like anyone my age. Drat! ;-)

Anyways, three nights a week plus lab plus homework, plus 40 hours of work, isn’t going to be fun. I really wish they’d just let me get a Computer Programming degree now and be done with it. (I’ve taken every programming class required, and then some, most of which I ended up teaching the professor in, so all I’ve left now is a year or two of “basics.”) I really should just cut back from work, take more classes per semester, and get this over with. I’m going to be 34 by the time I get my Bachelor’s at this rate.

cm: Your rant is pretty much, “I have to write SQL to get information from a database.” See, the problem is, you have to ask the database somehow. What is it you’d rather do? Hand-craft binary requests? Manually iterate thru each table entry? Invent a whole new language that probably isn’t going to be any cleaner anyhow and very much most likely wont be as powerful?

SQL is a programming language, of sorts. Just like you write in Python or Java or C++ or whatever to work with the raw data in a computer, you use SQL to work with the raw data in a relational database.

Some of your rants don’t even make sense. What do you mean you can’t ask, “table, how many rows?” That’s what the SQL statement “select count(*) from table” does. That translates to, “return the count of the number of entries in the table” - i.e., how many rows. In any decent SQL server, that is going to be optimized away something like “return table->rows.”

Your later ranting about a state and its capitol is also quite silly. If you have that much trouble getting the information, you are either incompetent at designing your database, or incompetent at writing SQL. Or maybe both. The basic schema I can think of for that kind of information might require SQL like “select capitol from states where name=’Vermont’”. I.e., “give me the capitol from the state named Vermont.” How in all the nine hells are you going to make that any simpler?

If you’re using a much more complex schema (and then one should ask why you;ve made it so complex), it might be something like “select name from cities where city_id=(select capitol_id from states where name is ‘Vermont’)”. That’s a bit uglier, for sure, but again, there is no way using any kind of data store to make that simpler, given the schema. That’s basically, “what is the name of the city whose unique numeric ID is the same as the capitol of the state named ‘Vermont’”. Questions like that aren’t intuitive to a human, but it’s only because you designed your database to not be intuitive. If you have a design like that, no matter what kind of data store you use, it’s going to be less than intuitive.

Learn how to design effective and efficient database schemas, and how to actually use SQL properly, and you wont have many problems at all. Write a clean wrapper API in your app, just like you’d do if you were using any other kind of data store, and you wont even have to look at or think about the DB that much anymore. Problem solved.

Aside from that, it’s always possible to clean things up for your use case. Many/most SQL dbs support stored procedures for custom functions. You can easily write an object-oriented API for your data structures that wrap the calls to the database, so you can do things like “state->get_capitol()->get_name()” if that’s what you really want. You have to write those kinds of wrappers no matter what backend you’re using.

I’m an almost happy nVidia user, and thus make use of the bianry only nvidia driver. The only problem I run into with that is when I boot into a new kernel (say, a Redhat errata update) and the driver no longer works. (thanks kernel developers for that wonderful stable ABI!)

I’m thinking, my computer already wastes tons of time rebuilding module dependencies on boot, running that god awful kudzu kludge on boot (Debian’s discover seems so much faster - and probably is), so why not add another init check for the nvidia driver.

basically, the init script would see if the driver exists in the running kernel’s module area, and if the driver actually is loadable. If either fail, it’ll automatically run the nvidia-installer utility non-interactively, which results in either a new binary being downloaded (if nvidia has one for your new kernel) or the source being downloaded and compiled.

the process is definitely slow (especially since nvidia doesn’t cache the download), but then, just how often do users install bran new kernels? and for those that do, they’re generally the ones that are quite capable of managing the building of the nvidia driver all on their own.

the script I’m about to write (seriously!) will most likely be redhat specific, but I’m sure it can be made to be LSB compliant or something. and perhaps I can get nvidia to include it (or somethign similar) in their next driver release, and then just about all the problems users have with driver management with nvidia will be solved.

now just to get the bastards to make the driver stable and actually work. ~,^ my $600 flat panel is getting sick of running over VGA because the nvidia driver freaks out in DVI mode with this thing. ;-)

So, a new coding project has come up at work. Unlike all the web coding projects I’ve done for the last three years here, this one is a bit different.

Apparantly, the phone system spits logs out to a serial printer. This eats a lot of paper and ink, and isn’t easy to sift thru at all. So, the idea is, I make a virtual printer (since we can’t change the phone system due to cost) that reads the ‘printings’ from the serial ports, logs it to disk, and periodically sends it to someone over e-mail.

Damn simple, eh? ;-)

I’m a bit worked up over it tho, as I’ve never programmed a serial port, and don’t really know much about them - do I have to configure baud rate? control flow? etc. We have no control over the phone system’s settings, and the company that maintains it for us is… well, less than great.

I’ve also gone thru three machines trying to get Debian installed. We’ve a stack of “old” Pentium IIIs for stuff like this, but it seems I’ve had the bad run of luck to constantly pick bad ones out of the pile. Grr.

arrr, so it seems none o’ the scurvy dogs at the wharf here are much into the pirate holy day. shiver me timbers, it be durn annoying when ye own boss be tellin ye not to be talking like a pirate. har, he be walking the plank soon enough.

still be delaying me store/ai work on AweMUD. working instead on keel haulin’ the low-level bits of the me code. arrr, stores will be needin’ better money handling code, fer suren.

arrr, what I’d give now for some rum, make this coding be smoother sailing.

arr!

well, my c++ foreach loop is in even better shape. I got rid of the extra typedef that screwed up foreach statements in loops without brackets. basically, instead of doing

typedef typeof(expr) Type; Type::Value …

I’m now using a basic template wrapper class:

template struct _IteratorType { typedef T Type; }

_IteratorType::Value …

Much better. ^,^

Another problem has cropped up, tho, again with typeof(). If you take the typeof() of a type, you get the type. the typeof() a simple expression, the result type. the typeof() a function call, you get the return value (result of the expression consisting of a call to the function).

Alright. sounds good. the typeof() a constructor call, like mytype(some_value)? The type of result of the expression - mytype. Perfect. *but*, the typeof() a constructor with no argument (a default constructor): the signature of the constructor! i.e., the type is that of a method call, not the type being constructed.

That’s not really all that a big deal except when testing. There aren’t many cases where you’d construct an object using no arguments and directly iterator on it - it wouldn’t do anything interesting, except erturn some data you picked at compile time. Much more likely you’ll be constructing iterators with a value (like the test factorial iterator, where you pass the max value to go to). Or you’ll be constructing iterators from a method call on a class, in which call the method call will have the right typeof() value (it’s return type).

Still, tho, it’s quite irritating. I hope typeof(), or something similar, it standardized soon, so we can start expecting compilers to implement it properly. ::sigh::

nymia: what do you mean by your pluggable checkers? a way for a configure script to find other apps installed with autotools? if that’s what you mean, take a look at the pkg-config tool - it’s super spiffy. (

digitalSurgeon: what exactly is the point of your project? Work is underway on the GTK2.4 file selector, and all the development is going on in CVS and the mailing lists there.

Older versions of GTK2 are never going to change (in official releases) since they are maintenance only, stable releases, and changing the dialog can and probably will break some applications.

So, in my quest to put off the two and only two items on my todo list for AweMUD 0.20, I’ve started looking at the ‘dead player’ problem.

See, the plan is, a player will stay in ‘corpse’ form for a while, giving comrades or friendly passersby the chance to resurrect the fallen player. if enough time passes beforehand, the player will melt away, either to rise again in a temple of his/her deity, or in the underworld.

The problem is, we don’t want the room list to just say, “Also in the room: Elanthis.” We might want, “Also in the room: Elanthis’ corpse.” or perhaps to put the corpse in the object list instead.

Also, when the player speaks, or uses a speech-only emote/social command like giggle, we don’t want to say, “Elanthis giggles.” We want something like, “Elanthis’ ghost giggles.” or “The ghostly voice of Elanthis giggles.”

As I see it, there are three possible solutions. (1) Separate a dead player into two separate entities - a corpse and a ghost. (2) Add string parsing commands for things like {name-voice} and {name-body}, and use them everwhere, versus just {name}. (3) Simply special case speech, add a ‘ghost’ type to social descriptions, and make the default name processor spit out “{name}’s corpse”.

(1) seems like the worst idea. It’ll require tons of code to support properly - dragging corpses moves the player, not printing ‘ghosted’ player names in “who” lists and such, etc. I really don’t think I’ll go with this idea. Just listing it because it was the first solution I thought up, and has had the most thinking time put in it. ;-)

(2) The string parsing is workable, but will be a nit of a nightmare. Firest, the variable names need to have variations for when we need no article, the definite article, or the indefinite article. Each and every use of {name} needs to be thought out to decide which of the -voice or -body variations we need. Many pieces of code that currently use the C++ StreamName construct will have to be switched to the more resource intensive string-parsing system. In general, it just isn’t the great of an idea.

(3) I thought of this last, mostly because I’m loathe to special case anything. In reality, tho, the amount of code and logic needed for this scenario is less than either solution 1 or 2, plus it’s far more likely to be correct in all cases. The few places in the code not quite able to deal with the idea now (i.e., when you “tell” to a player, it would probably print you, “Elanthis’ corpse: blah”) can be easily enough fixed, since those places probably should only be using the unadorned player name, and not the “fancy” output of the StreamName construct.

And so, solution 3 it will be. Don’t you all just love me reading my pointless brain dumps? ;-)