#
# Notes on game development. Or something.
#

I realized recently that I should try breaking the process of
building a game engine into discrete chunks that could be
completed in "about half an hour" a day. I realize that some of
these chunks will actually take appreciably longer than that,
but the idea is the same.

Anyway, I also decided that a simple 2d overhead maze thing
would be simple enough to complete in a week of hacking (or
less, depending). And there are a few ways to go from there,
should I decide to build on it. One is to knock off Chip's
Challenge. Another is to knock off the old Mac game Dungeon of
Doom. A third is to make it smooth-scroll instead of jump-scroll
and knock off Zelda.

The basic idea is simple, the art assets amount to four 32x32
bitmaps at whatever color depth, the control logic should be
easy to implement. Assuming that I don't end up sitting down and
knocking it all out in a day once I break it down into small
pieces, it should keep me going for a week or something.

The obvious steps are:
  1. Open a fixed-size window and handle closing it and such.

*    a. Register a window class.

*    b. Create, Show, and Update a window.

*    c. Add in the main event loop.

*    d. Do something useful in the window procedure.

  2. Draw a single game tile (the player character?) in the
     middle of the window.

*    a. Draw up a tile in Paint.

Bleh. It looks like the easiest way to manage the bitmap is to
encode it as a resource, but that means creating a resource
directory and whatnot. And the resource directory format is
semi-complex.

And the image file I'm working with had to be saved from Paint
as a 256-color bitmap, which makes the palette data the same
size as the bitmap bits... and it only really uses four or five
colors, and the data could probably be profitably RLE-encoded.

There is no support for 4-color bitmaps. It goes from monochrome
to 16-color bitmaps. The RLE-encoding will likely require a bit
of trial and error to understand, especially for the 16-color
variant.

The alternative for right now is to use LoadImage() to pull it
from a file. That supposedly doesn't work on NT, but the help
file I'm using predates Win2k, let alone XP.

*    b. Use LoadImage() to read the tile up from a file.

I had accidentally deleted the little codefrag I was using to
check for failed API calls, so I recreated it as a
function... and forgot the (inst or eax eax) bit. Then I built a
hex-to-ascii-string converter for using GetLastError() and
MessageBox() to supply some failure information... and it was
giving me an error code of 00000000, which is basically no
error... And then I realized that I'd spent all this time when
the error was in the error detection code. Whoops. At least I
have the conversion routine now.

*    c. Create a compatible dc to our main window during
        creation and select the loaded image from step b into
        it.

*    d. Draw the bitmap during WM_PAINT handling with BitBlt.

Needed to load the image before creating the window. WM_CREATE
handling happens right then rather than once the message loop is
entered.

  3. Draw a section of a maze sufficient to fill the window.

*    a. Create maze tiles for a wall and floor.

*    b. Load the maze tiles and select them into their own DCs.

So, want to hear a really bad joke? SBCL's MOV instruction
definition, when handed a FIXUP, treats it as an EA with a
displacement of that FIXUP. This is completely different from
how any other instruction behaves. Now channelling the Small God
of Rage. The easiest workaround for now will be to emit the code
by hand.

*    c. Write a function to draw a given tile at a given set of
        x,y coordinates.

As an optimization, we might consider laying out all of the
bitmaps into one larger bitmap, in a single vertical
column. That would make finding a given bitmap straightforward,
while reducing the number of bitmaps and DCs we need to have
lying around. As a further optimization, we could do this at
build-time. Something to consider, at least.

*    d. Lay out a simple maze and wedge it into the data section
        somehow.

*    e. Write a function to render a chunk of the maze starting
        at 0,0 in the top-left corner of the window.

*    f. Parameterize the function to load from saved x and y in
        the data section.

*    g. Draw a player sprite over the top.

  4. Handle arrow keys to move around the maze.

*    a. Write a function to find the tile for a given X, Y
        coordinate in the map.

*    b. Catch WM_KEYDOWN events and report the key code.

*    c. Break out the four direction keys to their own code
        paths.

*    d. Retrieve the map tile for the location to move to.

*    e. If the destination is not a wall, update the saved
        location and invalidate the window.

  5. Detect when the player moves onto the exit and declare
     victory then.

*    a. Create new tile for exit.

*    b. Add new tile to loader.

*    c. Place new tile in map.

*    d. Detect player moving onto exit.

*    e. Output victory message when player moves onto exit.

  6. Bind the tile images into the execuable somehow.

*    a. Nevermind. The examples of Avernum and Cave Story are
        clear. Graphics data doesn't need to be in the exe.

Complicating this would be the fact that I'm building the
toolchain at the same time. A certain amount of work needs to be
done there before I can really start with the game proper. For
example, some of the section sizes are hardcoded, the test
program is embedded in the assembler sources, there's no support
for data or code alignment, etc.

Here we have:
* 1. Move the test program out into a separate file.

* 2. Make a wrapper function that intializes the assember, loads
     a given program file or files, and then generates the
     linkage information and spits out an executable.

* 3. Add support for recording structure type layouts.

* 4. Add some notion of an argument frame, and an easy way to
     reference arguments to a function.

  5. Add some notion of a local stack frame, and an easy way to
     reference structure fields within the frame.

  6. Parameterize more of the PE header information as needed.

  7. Add support for arbitrary alignment of code and data
     fragments.

  8. Add a proper MZ-stub.

  9. Rebuild foreign fixup process to only import fixups that
     are actually referred to instead of all defined
     fixups. This will allow us to build a "standard library" of
     import definitions.

The critical steps for before I start in on the game are the
first two. The third and possibly fourth steps may come into
play while building the game itself. The fifth step is more for
the sake of completeness than anything else.

# EOF
