Finger info for phaethon@icculus.org...



Raw source and immediate archive at http://www.icculus.org/~phaethon/plan/

Entries are currently sorted in: Newest First

Syntax (time and date in UTC, my local timezone is PST/PDT):
[YEAR].[MONTH].[DAY] <space> ~[APPROX. HOUR] <space> <space> [SUMMARY]
<empty line>
[CONTENT]
<empty line>
<empty line>



2003.05.09 ~11 Patents, a moment of zen

US Patents System -- a non-market government instrumentation designed to
promote free-market competition by forbidding free-market competition.


2003.04.03 ~01 USB solid-state storage devices

Is it just me, or do those little USB solid-state storage mechanisms (those
small enough to hang on a keychain) eerily hint at Star Trek-style isolinear
chips?

On a related random thought, these things are small enough that, if they were
to be cheap enough, could be used as, say, business cards, the way shaped
mini-CDs can be used to hold business-card data. Or as a means of distributing
resumes. Flash the info to a solid-state device of a couple MB that's about
the size of a stick of gum, distribute. Recycle. etc.


2003.03.19 ~07 BAFO BF-120 IrDA<->USB dongle

So, I went to Fry's Electronics (in Manhattan Beach, the one with the
Hawaii theme -- coincidentally, also the smallest of the Fry's stores)
to get a new fuse to replace the one I blew in my multimeter (a cheap-o
one that only measures up to 250mA; I tested the current through two
full batteries in series (400mA) for a split second). This led to that,
and for the next few hours I kind roamed around the store floor looking
at this and that.

As I started to wind down on whatever hell this phenomenom is called (I
think it's the same one that induces women to wander for hours through
clothing stores without buying a single article), I finally stumbled
across the only IrDA-over-USB doohickey in the entire store. A BAFO
BF-120 IrDA dongle. It's a IrDA dongle that connects via USB, instead
of connectors on the mainboard that directly wire to IrDA controllers.
I basically bought the thing on impulse, with intent to use the existing
TV/VCR/cable/etc. remote controls we have at home to control my PC.
Should that fail, plan B is to use the IrDA for Palm syncing.

The BF-120 comes in three variants, apparently each with a different
IrDA chipset, if the packaged manual is any hint. The dongle has a
label on the flatter surface, towards the USB plug, that indicates the
particular Windows driver to install (so I assume the three different
labels indicate three different chipsets). A synthesis of information
from /proc and the web revealed that (a) if the label reads "V6102F",
it's a SigmaTel Ir4200 (STIr4200) chip, (b) there is no existing driver
in linux for the STIr4200 chip, (c) the full technical specs for the
STIr4200 (down to the physical packaging!) are available with little
fuss. These docs should suffice for writing a driver.

My options at this point were (A) return the doohickey and hunt for
another IrDA dongle, (B) wait for someone else to write the missing
drivers, (C) write the damned thing myself.

I was about to go with A when our dear local Mr. chunky mentioned he has
the same device. Bought at the same store. But at different times. I
switched over to option C, partly as a challenge. I printed out the
docs, and have been mulling over the 22 pages of it for 3 hours, at the
time of this writing.

If only I knew how to program Linux drivers...

It's learnin' time.


2003.03.18 ~10 OES UI

The last three (four?) days I worked on overhauling the ui system for
Orbital Eunuchs Sniper (http://www.icculus.org/oes/). For one thing, I
was annoyed at the existing menus not working. Secondly, I wanted a
platform to prototype a ui for my q3 mod (the one done in Scheme).

Mainly because of the Scheme slant, I used S-expressions for storage
format. For quite a while, I knew of the existence of sfsexp
(http://sexpr.sourceforge.net/), but didn't have much practice actually
using it. To cut my teeth on sexpr, I started on something smaller, the
preferences file in OES. The original preference format was binary, a
memory dump of a C struct. I'm a strong believer in the unixian way of
plain-text configuration files. As an added bonus, the preference file
only held four settings, so the preferences could be simplified into a
four-member association list. Reading would involve a simple one-level
traversal of the list, and then picking the pairs out of each member of
the list. This little exercise gave me a sufficiently half-clued idea
of how to use the sexpr data structs.

Afterwards, I took on the menus system. The initial idea was to
parallel the menu system in Q3TA, involving text files that describe the
initial state of the gui, then letting the system rip loose with a C
core. The first goal was to have the buttons react to the mouse, focus
and clicking. The first incarnation checked the mouse location every
time the screen was redrawn, checking if a button was in focus or not.
The ui system walked down the widgets heirarchy to propagate click
events, checking each widget's clickability, mouse location, and name to
react to mouse clicks. This method was really nasty, since button
actions were hard-coded according to their name, embedded in the ui
functions (broken encapsulation).

I think I went through four rewrites of the data structures for the
widgets. What I wanted in the data structure was a simplified
query/modify interface to widget properties. Initially, I wanted to
directly modify the sexp structs describing the widgets, in the form of
alists, but I couldn't quite figure out how to modify the structs
decently, either to add a key/value pair or to modify one. The data
structures I finally settled on involves a singly-linked list of structs
holding a key/value pair, which I found to be more easily modified than
the sexp structs. A couple of support functions translates the sexp
structs into the linked list.

After the buttons started reacting to clicks properly (starting game,
quitting, etc.), I worked on purifying the encapsulation of the ui
system. Namely, to separate the OES-specific data and actions from
ui.cpp. The goal was to make the ui system capable of being a drop-in
component into another project.

One interesting progress I notice in retrospect is my gravitation
towards a signals system as used in gtk+ and SWING, away from the
"cascading events" style. Initially I couldn't comprehend the signals
system, and partially as a result had a general distaste for it at
first. For one thing, I didn't like, and couldn't handle very well, the
notion of multiple paths to a widget (one via parenting heirarchy, and
one via signals, etc.). OTOH, what I found out is that using a signals
system greatly expanded the capabilty of the ui system. I don't know if
it's something intrinsic within the signals system or if it's a
"perspective" thing, like taking a different slice of The Whole General
Mishmash of widgets.

As a hack, the extent of signal-handling within the ui system itself is
emitting yet another signal. There is C instruction to handle signals
not understood by the widgets in the ui system. So, for example,
handling of the Escape key (which was added fairly late in development)
to backtrack through menus was done by connecting the toplevel (menu)
widget to the "esc" signal; the "esc" signal is generated by pressing
the Escape key (from the ui input handler); the toplevel widget re-emits
the signal "go-main" upon receiving "esc"; no widgets understand
"go-main", so this signal is handed off to the C handler, which does a
series a string checks to figure out what the signal is, then rearranges
menus accordingly (in the case of "go-main", bringing the menu named
"main" to the foreground).

This signals system is still better than recursively stepping through
child widgets and repeating events to all of them. For one thing,
signalling doesn't need to worry that some widget that doesn't
want/like/know an event won't stop the entire event-propagation loop.
For another, CPU cycles aren't wasted on widgets that don't care about a
particular signal.

The advantages of a signals system are probably common knowledge to
developers of ui systems, but I'm scribbling all this down for my own
future reference.


2003.03.13 ~04 Triseism - standalone Q3VM interpreter

http://www.icculus.org/triseism/

Standalone Q3VM interpreter. Most of the workings of a stack-based
machine became clearer when I brushed up on Forth. And Forth didn't
make much sense until after I learned Lisp. After learning lisp, the
idiosyncrancies of python became understandable.

Q3VM sets aside 64KB total for stack. Forth uses two stacks. If Q3VM's
stack is split in two (which I'm not absolutely certain on, but makes
sense), to mirror the two Forth stacks, this gives a limit of 32KB for a
stack frame. This limit is enforced by q3lcc at compile time, and I've
always wondered why 32KB in particular. Looks like the run-time stack
is involved.

Some of the emulation techniques I borrowed from my experience on PHFC,
the CUSP emulator. And from hacking on q3asm, the opcodes were fairly
transparent. I created and compiled many very simple programs to see
the translations of C source into Q3VM asm.

The Q3VM syscalls are a bit of a zinger. For one, I can't possibly
implement ALL the syscalls -- this would basically lead to rewriting Q3.
The other problem is that Q3 has three sets of syscalls, one each for
game (server-side), cgame (client-side), and ui (client-side menus).
I'm thinking of using a dlopen() system to optionally load one set of
syscalls over another. Splitting off the syscalls package would also be
helpful in utilizing triseism as a general-purpose sandboxed VM.

The other problem I'm having is the mysterious two words allocated on
the (return) stack upon entering a procedure. Local storage starts
after these two words, so the two words are likely involved with the
return process.

I'm thinking of distilling triseism into a library. One of my
motivations for finishing this was an acquaintance's desire for being
able to load a .qvm in another app, as one would open a dll.

In other possibilities, since the opcodes of the Q3VM are now very
clear, it should be possible to compile Lisp directly to qvm bytecode,
bypassing any C translations or C compilation, i.e. foo.l -> foo.qvm.
Also, I'm certain gcc and the gnu toolchains to can be hacked to compile
directly to .qvm.

Implementing a dll system within Q3VM is doable, but would probably need
changes to the .qvm format. The current .qvm format discards the symbol
table, precluding any dynamic symbol resolution.

Since triseism is developed independently of Q3 proper, triseism isn't
bug-for-bug compatible with idsoftware's Q3VM. This means triseism may
not mimick every tiny detail of Q3VM down to the fiddling of bits.
Triseism may help in tracing an execution path through a Q3 mod, but
without debugging symbols, there isn't a simple way to link an
instruction location with its matching line of C source.


2003.02.05 ~09 snes9x console

http://www.icculus.org/~phaethon/snes/console.html

I started on this hack the day before shuttle Columbia disintegrated.
Motivation to hack this up came from several places. Primarily, I
wanted arbitrary bindings of the buttons on my gamepad (Thrustmaster
FireStorm Dual Analog 3) for use in snes9x. A strong impetus came from
ZSNES and its GUI. I liked the immediacy of changing key binds and
fiddling with options in zsnes. In snes9x, changing options meant
saving game state, quitting, futzing with command-line options,
starting, and restoring state.

Another source of inspiration was Brad Jorsch's control-remapping patch,
which is applied to the Debianized snes9x package. I thought the
configuration file for that to be rather clumsy, and it didn't bind
joystick axes and buttons.

The notion of a console came from Quake (1, 2, 3) and Unreal Tournament
(pre-2003). I settled on mimicking Quake's console since (a) I am
familiar with Quake III's console, and (b) snes9x lacks the underlying
objects, widgets, and language system to mimick Unreal's console. Also
Quake's console is based on a command language, simpler than Unreal's
more advanced Algol-family language. I mimicked most of the
functionality and commands found in Quake's console, with various
extensions of commands and cvars appropriate for snes9x.

The cvars that affect emulator settings are not directly tied to their
associated C++ variables. Rather, there are explicit calls to
synchronize the values between cvars and their variables. Somewhat
inefficient, but saved massive refactoring.

FlightGear has an interesting configuration system. A key binding
describes how a particular "FlightGear property" is modified. For
example, swapping values with another property, incrementing the
property by a certain amount, or _conditionally_ setting the value of
one property based on the value of another property, at key press or key
release. Bindings for (analog) joysticks are described in the same
syntax, but describes a formula for translating the joystick position
into a property value, using a scaling factor, an offset value, and a
"dead-zone" range.

Anyway, FlightGear's binding of analog joysticks inspired me to figure
out a way to incorporate axis-handling in the new snes9x console. I
spent much time thinking over keys, input, and key states. Often, the
state of a key is treated as a boolean, as either true (pressed) or
false (released). I thought of an axis of a directional (digital) pad
as being one key with three possible states: 0, positive, and negative
(i.e. left and right do not occur at the same time on a joystick). In
the case of an analog axis, there would need to be continuous values on
either side of 0. At first, I considered using floating-point values,
i.e. -1.0 for one end, +1.0 for the other, and fractional values to
represent intermediate axis positions. Well, due to some inconsistency
in the cvars mechanism at the time with float-point values, I wanted to
stay away from floats. That's when I remembered joystick calibrators
worked with integers, where 32767 represented maximum and -32767
minimum. So I went with integer-only values for a key state. For
regular keys, the state would still be 0 or 1, but for axes, would be a
value from -32767 through +32767.

In Tribes 2, a key is bound to a function -- a key handler. This
function is passed one parameter, a value of either 0 or 1, indicating
whether the function was called because the key was released (0) or the
key was pressed (1). I never dealt with joystick handling in Tribes 2,
but a reasonable extension would be an axis-handler function being
passed a value indicating the axis position.

Quake III supplies commands linked to action primitives, in a "start"
and a "stop" flavor. For example, "+attack" means start firing, and
"-attack" means stop firing. If a key is bound simply to just
"+attack", when the key is released, Quake III automagically runs the
command "-attack" (i.e. replaces the '+' with a '-'). The '+'-'-'
swapping is apparent with a simple test: "/bind SPACE +crap". Hit Space,
and the Q3 console complains about not finding "+crap" nor "-crap". The
complaint about "-crap" happens when Space is released.

A while ago, in an attempt to extend the Q3 console capability to be
more shell-like, I added an "alias" capability. This capability allowed
a cvar to run as a command without need for an explicit "vstr". The
basic idea was, for some alias named "foo", to prefix it with an
ampersand, "&foo". Should the Q3 engine fail to understand a command
(and pass it off to Q3VM code), the VM code tries to find a cvar
matching the unknown command's name, but with a leading ampersand.
Then, on a successful match, runs the cvar's content as a command.

I took this idea over to the snes9x console. The primary goal was to
have a bind named "+turbokey", defined entirely in terms of commands
(instead of C++ code). This alias would then be bound to Tab, such that
holding down Tab puts the emulator into "fast-forward mode" (skipping
boring/useless/pointless parts of a game), and releasing Tab returns the
emulator to "normal" speed.

Most of the keynames were ripped from Quake III. Q3 basically goes off
on its own naming system for high-bit key, so there had to be a way to
map the host key to Q3's (or rather, snes9x console's). This comprises
the most massive patch to files outside of the console/ directory --
just mapping host keys to s9xconsole keys.

I didn't want to mimick FlightGear's axis handling completely. One
problem I have with FlightGear's joystick handling is the complexity
involved in trying to control the throttle properly with an
auto-centering joystick (i.e. a little push to increase a little, big
push to increase a lot, instead of the throttle every time the joystick
auto-centers). The Tribes 2 style was more attractive, but that meant
having some primitive form of conditional and flow control.

That got nasty. I don't want to get into it, other than the commands
for conditional and flow control are more reminiscent of assembly than
any kind of HLL.

I implemented a primitive form of multitasking to deal with rapid-fire
(press, release, repeat, but if the console doesn't yield to the rest of
the emu, the emu never gets to see the buttons) and a primitive form of
multithreading to deal with infinitely-looping commands. Also, as part
of rapid-fire, I had threads record the key that initiated the thread.
Then the thread manager kills off all threads associated with a key
whenever its state changes (e.g. killing rapid-fire loop on release).

Originally I had a cvar named "axisval" that records the axis position
for the AXISn "keys" (analog axes). One AXIS bind could make several
comparisons to the cvar, but then the multithreading meant another AXIS
bind would then change value of "axival", before the first thread manage
dall its comparisions. Race condition. I resolved this by attaching
the axis number to the end of the cvar name, so that each AXIS bind has
its own associated cvar (instead of one cvar shared across them all).

So, now, any of the three joysticks on my gamepad (one D-pad, two
ministicks) can emulate the SNES Directional-Pad.


2003.01.22 ~10 Random thought: shell as "action-oriented programming"

Stumbled across this thought while pondering config/rc files.

Object-oriented programming, as in C++, usually has a form of:
OBJECT <delim> METHOD <delim> ARGUMENT1 ARGUMENT2
(object first, a method in that object, arguments to pass to the method)
e.g. foo->bar(0), bonk.oif(quux, quuux, quuuux), $fred->yabba(dabba, doo)

Shell programming, when typed out, usually has a form of:
COMMAND <delim> OBJECT1 OBJECT2 ...
(command first, then objects to operate upon)
e.g. rm -rf /, mv foo bar, touch this that private pubic lockfile

Of course, shell programming can get much hairier. But if shelling can
be considered "action-oriented programming", that'd be some kind of
fit-the-slot counterpart to OOP.

Just a random thought.


Life: No Life found.

Project:
1. Project FI, Quake 3 mod (http://www.icculus.org/fi/)
 a. provide an extensible environment for a Q3 mod. The intended notion is that of "mutators" in Unreal Tournament.
 b. FI:WFC, a more faithful reproduction of Q2WF for Q3 than WFA.

2. QuakeScheme
 * Extensible language for Project FI.
 * Builds on TinySCHEME (http://tinyscheme.sourceforge.net/)
 * Deal with idiosyncrasies of Q3VM not handled by most other Scheme impls.

3. Q3VM libc
 * Implementation of Standard C Library for Q3VM bytecode.
 * Implementation of a subset of Single Unix Specification v2 (SUS v2).
 * Help import third-party library into Q3VM.

4. QS GUI/widget set
 a. Need to research advanced OO and GUI of Scheme derivatives and Common Lisp.
 b. Replication/extension of boxy widgets in Q3TA (Q3 PR 1.27+).
 c. Pie menus -- just to annoy theoddone33.

5. Q3 compilation toolchain
 [X] q3lcc sources (official version out with Q3A SDK 1.32)
 [X] q3asm - get static to work, dammit.
 [ ] q3as - assemble-only (.asm to .o).
 [ ] q3ld - link-only (.o/.a to .qvm).

5. PalmOS stuff
 a. PiNGer (gfx viewer)
  * generalize interface to a "any-gfx" viewer (libpnm?)
 b. ZBoxZ (file manager)
  * beef up its appness: menus, dialogs, pen actions

6. Blender development (http://www.blender.org)


When this .plan was written: 2003-05-09 07:33:29
.plan archives for this user are here (RSS here).
Powered by IcculusFinger v2.1.27
Stick it in the camel and go.