(opens in same window)
(opens in new window)
(likely 404 error)
April-June 2003 (oldest-to-newest)
I've been playing Zelda quite a bit, although I'm not
very far into it yet. The game is quite an experience.
I also did some work on my Time Pilot '84
fan page. It's
been bugging me that I've let it sit for so long.
Also, I have some NUON lovin' coming your way soon. I've
been sitting on the next version of Chomp for a while and
it's about time I released it. Not much will be different.
The only major additions will be an in-game level editor and
a few more tournament levels.
Just clearing the deck of all the little things so I can
get focused on some real game programming.
We helped some friends move on Saturday. It took seven
hours and had the worst weather we've seen in months. It
rained pretty hard for a while. Murphy's Law I guess.
I just found a minor bug in Chomp so I will fix that
before releasing it. Also, I need to write up some decent
documentation for the level editor.
Want to take a first look at the level editor documentation? I still
need to fix any awkward or confusing wording. However, it's
The next Chomp is pretty much ready to go. The high
score page is ready to accept codes for version 1.4. Since
no game mechanics changed the scores will be merged with
those from version 1.3.
I couldn't duplicate the bug I saw before so I'll wait
and see if others encounter it. It's not a show stopper -
just a minor annoyance. I fixed a couple other bugs in
the process of tinkering.
I also created a couple more tournament levels. One in
particular will have you cursing my name, heh heh. I need
to make sure that it's possible to beat even the default
high score. I couldn't do it in the two times I tried
Riff had a great suggestion that will make users of the
emulator happy. You'll be able to print out the mazes you
create in the level editor, making it a simple cut-and-paste
to get them into the "levels.h" file. On a real NUON doing
printf's hangs the system, but on the emulator they'll be
redirected to the stdout capture window.
Before release I want to put in one more tourny level to
make it a nice round 10. Maybe add some more wall
it is (572kB). Visit the main
page for the latest. The big item is the level editor,
but there are also four new tournament levels and a few
more graphic tile sets.
As always, post your
high scores. And feel free to send me any levels or
graphics you create for inclusion in updated Chomps.
Some time soon I will release an update that is more
emulator friendly. The new source code is also
Oh and happy birthday Sis!
to Chomp v1.4 is now available.
Looks like BC has thrown down the gauntlet on the
Chomp levels. Anyone care to step up?
I just entered my high scores for Chomp. My hat goes off to Riff and BC for
their top scores. I'll have to work harder on those. That
level 5 score is amazing Riff!
While playing I encountered one bug and one oddity. The
bug happened when I died (time ran out) while in power pill
mode. The game crashed and I had to reboot. I'll investage
The oddity is that the ghosts seem faster some times than
others. They are supposed to be a bit slower than the
player, but I have played levels where they are just as fast
as me. I haven't pinpointed a possible cause, but that
definitely needs fixing since it imbalances the tournament
levels. All scores are still valid, but you may have a
more difficult time than necessary if you get the fast
This weekend was one of the more fun ones I've had in a
while. Very few errands to run and only a couple house
projects. That left plenty of time for Zelda and
I got stuck in Zelda a week or so back. So I gave up on
the dungeon and instead took the opportunity to get my
sailing chart all filled in. With that done (it took longer
than I thought) I went back to the dungeon in question. I'm
ashamed to say I remained stuck and had to look up on
Game FAQs how to progress. After smacking my head and saying
DUH I was off again. The game just keeps getting cooler.
How I've missed those two purple words. I fixed the
player's thrust sprites so they now appear correctly. One
bug involved computing tpage
coordinates incorrectly. Fixing that made the sprites
show up, but they were red rather than blue. A second bug
involved reversing the order of RGB, which would explain
the color confusion.
Now I'm trying to fix a graphical corruption bug in the
player messages. This is the text that appears in the
lower left corner to tell you things like "Target Opened"
or "CD Track 9". I have the bug isolated. I know what
causes it. I just don't know why.
I allocate memory for a 160x12 buffer for one message
sprite. Then another gets allocated that's 160x1 (the
height increases to 12 as it scrolls onto the screen).
Writing to the second buffer is causing corruption in the
first, which is weird since the second one comes after the
first in memory. It's a strange bug for sure.
I finally finished updating the
archive pages to
the new site's format. It's only taken me a year :P
Also, I'm working on a search feature for the site.
There have been a couple times when I know I've written
something, but don't want to go digging through the
archives for it. It'll probably help me more than you.
I asked one of the NUON software guys and got an answer
to the graphical corruption problem. Turns out there
is a restriction on the height of bilinear buffers.
They must be a multiple of 8, or 16 if the cluster bit is
set. That fixed the corruption. Woo! Thanks Eric!
Update: Riff pointed out that this restriction
is actually documented. It's in the BIOS doc in the
section "Video Functions" (10.2.2). Not a very good place
to put it if you ask me. It should be in the "Memory
Management" or "DMA Functions" section.
Here's a photo I dug out. It's from the VM Labs booth
at GDC in 2000. Click for a bigger version. More photos
coming your way soon.
Fixed a bug that was keeping the time countdown from
displaying. There was a problem in the code that detects
when a sprite has changed and needs to be regenerated. So
I guess the sprite was being displayed, but it was
always clear. This image also shows the player thrust
sprites. Click for a larger image.
There are a few more things to get fixed on this first
level before I start playing further into the game. First,
the player's lasers don't fire. Second, the HUD stuff isn't
displaying. I may have just disabled it a while back - I
can't remember. Third, I really want to fix how all the
sprites are rotated slightly.
Figured I need to hurry up and finish Zelda as there are
other games waiting to be played. I finally finished the
Earth Temple. Very fun! And my wife came up with the way
to beat the boss for me.
Is anyone going to post some new Chomp scores? It
doesn't matter if they don't beat the high score. Heck,
my scores for levels 8 and 10 didn't. I just wanted to get
my name in there somewhere :)
I've been playing a lot of
lately. I bought the full version of Pinball Dreams and
love it a lot. I like the concept of downloading games.
While boxed retail games are encrypted to only work on the
SM card they came on, the downloaded games are different.
They will work on any card, but are encrypted so they only
work on your GP. Since they're tied to your GP
rather than a specific card, that means you can put them
all on the same SM card along with the free software such
No need to swap cards!
Of course the downside is that if you switch consoles
your games won't work anymore and you have to buy them
again. That's the only thing preventing me from
downloading more. I eventually want to get a version of GP
with the front light. If that means buying a new system
then I don't want to have to pay for all my games again.
I'm hoping they come up with a front light conversion kit
so I can just modify the system I have. Such a thing is
supposed to be in the works, but who knows when it will be
I fixed the lasers so they show up. For some reason my
routine that detects button presses was blindly ignoring
bit 0 of the button field, which just happens to be the
fire button. The routine is identical to the original
Playstation code. I must have had my reasons for ignoring
bit 0, but can't remember them now. This is why I comment
my code much more profusely now.
I also re-enabled the full HUD. As suspected it was
commented out. I think I'm hitting the limit on sprites
or something because with the HUD the planets sometimes
disappear for a frame or two. That's probably why I had
commented it out. Obviously this still needs
The big news is that I've root-caused the reason that
sprites are always slightly rotated. This happens even in
the original sprite library. The sprite routines force the
least significant fraction bit of the "angle" to one. That
means even if you pass in zero it will be set to some small
That was easy to find. Figuring out *why* that's done
was the real problem. If I comment out the part that does
that the sprites no longer show up when at exact 90-degree
multiples. I believe this is due to how the sprite's
bounding box is calculated.
The sprite code gets the four coordinates for the
outside of the non-rotated, non-scaled sprite as shown
in the image to the right. It acquires them in this order
because it makes the code more compact - only one
coordinate, X or Y, changes between any two consecutive
It then applies the rotation and scaling to get the
transformed coordinates. It sorts the four new
coordinates according to their Y position. Then it
determines the bounding box for this new sprite. The
height is obtained by abs(Y1-Y4) and the width by
There's a problem when the sprite is at an exact
90-degree multiple. When the code sorts the points it gets
confused since some have identical Y-coordinates. It so
happens that the points remain in the same order as they
originally were (first image above).
Do you see the problem? When the code computes the
width of the bounding box it does abs(X2-X3) which gets
zero! Thus the sprites do not appear.
I think this should be an easy fix. I had to leave for
work before I could try this so I'll know tonight if it
works. Instead of obtaining the original coordinates in a
clockwise manner like it does now, I'll get them in the
order: top-left, top-right, bottom-left, bottom-right.
This ensures that the coordinates used for computing the
bounding width & height are always taken from opposite
corners. (Or maybe all I need to do is change a
"greater-or-equal" to "greater".)
Here's a shot with the laser and the new lack of sprite
A side benefit of the rotation fix is that the "D" and
"O" from the "Decaying Orbit" on the main menu no longer
have the green pixel corruption. This is good, but makes
me nervous that if I do want to rotate them at some point
that the corruption will return.
This shot also shows how the left and right thrust
sprites act independently. When turning, one side thrusts
more than the other.
I'll release the updated sprite library once I get a
chance to test it on more apps.
Saturday was another Game Day so I spent most of it at
a friend's playing strategy board games. It's nothing like
the shindig on
but still a good afternoon of fun.
Then Mother's Day was spent with the in-laws at Zachary's Pizza.
The best pizza I've ever had. Of course I've never
been to Chicago. It's difficult to imagine pizza getting
I almost have the updated Chomp ready to go. I just need
to get an audio problem worked out. The game detects when
it's being run on the emulator and skips all the sound
calls to avoid locking up. You can enable sound later in
the Options menu. This is preparing for the future when
the emulator can do sound so you won't have to download a
new binary. Anyway, the problem happens when you enable
sound manually. The call to AUDIOInit() happens just fine,
but the first sound played afterwards hangs the game.
On Decaying Orbit I figured out why some sprites were
dropping out. The game was running out of video memory.
Every sprite that's drawn must be converted to a NUON-native
format. This consumes memory, and since there were so many
different sprites I was running out.
Originally I never deallocated the memory of unused
sprites in order to keep the speed up. Deallocating a
sprite means if it is used again later it needs to be
reallocated and reconverted.
So I added a count that keeps track of how much video
memory I'm using. If the amount of free memory ever gets
low I deallocate some sprites. I also added some code to
keep track of which sprites have been used recently so
that I only deallocate those that haven't been used for a
I'm hoping this will work fine for all cases. However,
I may be in trouble if some scenes require a lot of
sprites simultaneously. This shouldn't happen, but we'll
I can't remember the last time I updated the site so
often. Hopefully I can keep it going.
Riff and I have been bouncing mails back and forth trying
to get Chomp to run faster in the emulator. He's come up
with a couple great ideas so it may be a while before I
get them in and bug-free and release a new version.
The audio problem from last time is fixed. Riff came
up with the solution just by speculation. The sprite
library comm bus handler was not behaving properly. It was
consuming audio packets from MPE0, which is bad. This only
happens when AUDIOInit() is called after SPRInit() because
of the order the comm bus handlers are installed.
Chomp now detects when you're running on the emulator
and mutes all sound. You can re-enable sound in the
Options menu. Of course, this will crash with the current
version of the emulator, but it's ready for whenever the
emu can handle it.
I also fixed the two bugs mentioned
back in April.
I just got back from viewing the new Matrix flic. My
company took the whole hardware team out to watch it. If
ATI really wanted to get a leg up they could have taken out
that theater :).
As for the movie, the action sequences are absolutely
awesome, but the exposition tends to drag, especially
towards the end. Still overall I liked it and will be
seeing it again with the wife this weekend. I require a
repeat viewing just to understand what the heck was
Might as well release all these at the same time :)
The new sprite library has the comm bus handler fix and
some assembly optimization.
Chomp has the fix for the hang when you run out of time
in a tournament level while in chase mode. It also fixes
the problem with the ghosts speeding up from level to level
in tournament mode (they should be constant). Plus it now
works in the emulator. It detects when you run on the
emulator and disables audio as well as only using one sprite
rendering MPE. It prints out some useful messages to
STDOUT as you go. Tournament scores obtained by using the
emulator are invalid since it would be absurdly easy to
get the high score given the slow speed.
The DO demo has the sprite rotation fix, player thrust
and lasers, and the pause menu. It currently hangs when
you finish the level.
Figure I should add info about future plans. The sprite
library is just begging for more optimizations. The nice
thing is this will benefit everyone that uses it. I'll
need to jump through some significant hoops to get Decaying
Orbit up to speed and this is the main area in which to
Chomp will likely receive another update that increases
its speed in the emulator. Riff has a version that uses
the overlay channel for the sprites while leaving the
(largely unchanging) maze for the main channel. Not having
to do the YCrCb-to-RGB conversion every frame is a great
boost. He also has another new idea cooking for further
Decaying Orbit is in dire need of some speed. I'm now
shooting for 30fps at hi-res 640x480. I'll update the game
code so everything is twice as fast to make up for the lack
I liked the movie a lot better the second time. There
is a good story in there - they just don't convey it too
well. A repeat viewing let me catch everything I missed
the first time. Plus I remembered to stay for the preview
of Revolutions at the end of the credits. I am looking
forward to that one very much. Between that and Return of
the King, it will be a good holiday season.
I did a bit of optimizing. The framerate is up to 12 fps
so it's a slight improvement. I removed the need for
clearing the screen by making the star background opaque.
Since they fill the screen anyway why bother clearing it
to black first?
I also did what I thought was a good optimization in
the sprite library. It had zero effect, unfortunately.
I finished Zelda last night. What a completely awesome
game. My gosh I don't know how anything's going to top
I think there's some terrible inefficiency in the sprite
library regarding DMAs. Direct memory access (DMA) is how
an MPE reads and writes data in main memory. Since each
MPE only has a few kB of memory locally the program
needs to do a lot of DMAs to read/write the frame buffer,
sprite textures, etc.
A properly coded game engine will make an effort to
double buffer DMAs so it can be loading the next set of
pixels while processing the current one. It looks like
the sprite lib did that at some point, but it has been
commented out. In the current implementation whenever the
lib fires off a DMA it waits for the transfer to finish
completely before continuing. Lots of time is lost doing
I will try to put back the double buffering. If I'm
right, this should speed things up considerably.
I added some performance monitoring code to the sprite
lib and took a snapshot during the first level of Decaying
Orbit. The sprite lib is wasting about 600,000 cycles
waiting for DMAs to finish at various points in the
rendering loop. Given that at 60 fps one frame only gets
900,000 cycles of processing time that's quite a bit.
However, since I'm getting about 12 fps right now that
means the whole scene takes about 4,500,000 cycles to
render. Reducing that by half a million won't have a
dramatic impact -- it might get me to 14 fps. However, it
is definitely something that should be addressed if I want
to get the game to an acceptable speed.
Another potential bottleneck I didn't check is how much
time the rendering MPEs sit and wait for the main game loop
to start them running.
Adding double buffering to the sprite lib is proving to be
quite a nuisance. The problem is that multiple parts of the
lib do DMAs to read and write pixels. There is a big DMA
that reads in the source pixels from the sprite image, a
smaller DMA that reads pixels from the frame buffer for
blending & transparency, and another that writes new pixels
back to the FB.
At one point the code must wait for one of the smaller
DMAs to finish before proceeding. Since DMAs are executed
in order (for the most part) and the one it's waiting for
was started after the big one, waiting for the small one
to finish means waiting for the big one to finish too.
I think there is a way around it. It will involve
rearranging a decent chunk of the sprite drawing code.
I never intended to get to know the sprite lib so much
My wife and I played golf again this past weekend. I
had the best round ever and to cap it off got my first
birdie ever! The actual putt to make the birdie wasn't
that long - three to four feet maybe - but my nerves made
it feel like it was the putt to win the US Open. I'm
thankful that my pitch shot got it so close to the hole
since I'm pretty bad at putting. My final score was a 108,
which averages out to a double bogey round.
Slowly but surely I'm adding double buffering to the sprite
lib. I'm starting to run out of both instruction RAM and
data RAM in the MPEs. Thankfully most of the work involves
shuffling things around. There's not a ton of brand new
code to write. However I did have to add another source
tile buffer of roughly 1kB. I'm lucky the lib had enough
room to fit it - the data RAM is only 4kB to begin with.
Work continues on double buffering the sprite lib. There
are two places that I will add double buffering: the source
tile reads, and the dest buffer reads.
The source tile is the actual sprite image data that
gets used to render the sprite. Double buffering this will
have the most dramatic impact since it is used by every
sprite type and is by far the bottleneck in the original
sprite lib. The lib reads 256 scalars per tile and the MPE
sits idle waiting for the read to complete. Given that the
bus can only transfer at most one scalar per clock we're
talking at least 256 clocks wasted per tile.
Double buffering destination reads will only impact
those sprite types that rely on reading the frame buffer to
do transparency. Actually most game sprites use this since
they are not perfectly rectangular. Any odd-shaped sprites
must combine with the background so you don't get an ugly
black box around them.
I'm really worrying about MPE RAM space. I have less
than 256 bytes left in both code and data RAMs. I need
to leave some room in data RAM for the stack. The most
worrying thing is the instruction RAM since it will impact
whether I can do everything that I want. I put in some
performance monitoring code a while back so I can take that
out if need be. It's going to be tight.
I am nearly done with the first stage of double
buffering. This may also be the last stage since I ran out
of instruction space. I removed the performance monitoring
code as mentioned earlier, and subsequently filled up the
space it freed. Once I get this working 100% I'll go back
and see if I can optimize things to reclaim some of that
So far I haven't seen a significant speed up. After I
get everything clean I will do some analysis to find out
how much, if any, this helped. I'll be severely
disappointed if this was all for naught.
So no game progress will be made until next week.
I've been spending a lot of time on my MailWasher Pro
filters. The amount of spam I get seems to be rising so I
had to do something. While it has its limitations, MWP
works very well to detect spam if you have the right
filters. Originally I used someone else's filters that
detect key words in the content such as "viagra" or "free
cable". This works fine most of the time, but needs
constant tuning as the exact wording each mail uses is
So I started from scratch and wrote my own filters.
Mine are designed to detect spam without looking at the
actual content. Luckily most spammers make it rather easy.
Predictable forged email addresses, gibberish at the end of
messages, markers at the end of subjects, and comments
within words are all fairly easy to detect.
One of my goals is to have zero false positives. I
occasionally get emails from random people about
Decaying Orbit or Time Pilot '84 and I
don't want those to get filtered accidentally. Right now
MWP does not have the ability to auto-delete filtered
messages so I'm in no danger of losing valid mails just
yet. But if (and I hope when) they do add that feature I
want to be able to use it to kill the spam before I even
Making these filters is fun too! It's like a form of
programming. Everything is done with regular expressions
so you can do some very powerful, but complicated,
searches. Thankfully I found
RegExp, which helps construct the expressions. There
are also a couple good regexp testers on the web. This one
is good since it has unlimited space for the expression
and the text. This one
has the nifty feature of highlighting the portion that
matches, although it has a character limit for the
I finally found and fixed (what I think is) the last
bug in the new sprite lib. That is until I start tinkering
with it again. Regardless, now I can focus on figuring out
why I'm not seeing any frame rate improvement with the
double buffering. There should be at least a little. I'll
compare the number of cycles wasted waiting for DMAs to
complete with the previous implementation.
The second part of my double buffering scheme (the
destination reads for transparent sprites) might be
unnecessary since it seems to already be doing it.
So I compared the cycles wasted waiting for DMA between the
original libsprite and the new one. Turns out the new
implementation is waiting less, but not as less as I
I improved things by removing a few instances where the
lib was waiting for DMA unnecessarily. I've seen the
frame rate count get up to 14 whereas before it was a rock
Reading in the source tile just takes so darn long that
the lib still spends a lot of time waiting. I'm thinking
the solution will be to reduce the tile size. Right now
they are 16x16 which corresponds to 256 scalars, and
translates directly into 256 clock cycles, minimum. Even
though I fire off the DMA early and do work on the MPE in
the meantime, it's still so long that the MPE gets done
long before the DMA.
So I'm gonna try reducing the tile size to 12x12 or
8x8. This will make the lib process more tiles per sprite,
but I'm hoping this will be offset by not having to wait
for the DMA. This will have the side benefit of freeing
up a significant chunk of data ram (16x16=1024 bytes, 12x12=576 bytes, 8x8=256 bytes). Since it is possible to
execute code from data ram I can use that space when I run
out of instruction ram again.
Not to mention the fact that, as it is now the spritelib
violates the recommended coding style. It's a no-no to
DMA more than 64 scalars at once since it hogs the bus.
Using the spritelib while accessing a DVD might cause
dropped packets, which can hang the system.
I have recently come to the realization that achieving
30fps at 640x480 in Decaying Orbit will not be possible.
I did some math based on the total number of pixels likely
to be drawn and the number of cycles per pixel. Even with
all three MPEs rendering it just won't cut it.
So I'm left with a couple possibilities. Both involve
reducing the resolution to 320x240, unfortunately.
- I could halve the resolution of every sprite.
Meaning the play field would be as you have seen before.
All the sprites would stay the same size on the screen,
just a bit more pixelated. I haven't decided if I would
do this at runtime in the library or just downsample them
all by hand.
- I could keep the resolution of each sprite and only
make one quarter of the screen visible. So whereas before
the first level was all contained within one screen, it
would now be stretched across 4 screens due to the
resolution change. This would double the size of each
sprite on the screen.
The problem with #2 is how to deal with the opening
title screen and main menu since it's not possible, nor
desireable, to scroll around.
#2's easier, but I think #1 is better. It will keep
the game largely the same as it was. It'll just look a
I believe #1 will be easier (see yesterday). All I have to
do is knock down the screen dimensions and halve the X- and
Y-scales of all sprites. Scaling them down isn't as good as
creating new images at the lower resolution, but it will get
me up and running more quickly.
Man I hope this doesn't end up looking like poo.
With the sprite lib about as good as I can get it I've
turned my attentions once again to our favorite pill
munching machine. Riff had some ideas a while back that
would significantly improve performance in the emulator.
I can finally get around to implementing them.
Look for 1.4F to be released sometime soon. The F is
for "Fast Emulation". Yeah, that's it.
If you have any levels you've created with the level
editor feel free to send them my way. I'll include them in 1.4F.
I updated the
high score page
so that you may no longer use versions 1.3 or 1.4 to
submit tournament scores. Those versions don't detect if
you're using the emulator, and I don't want to mix scores
achieved on a real system with ones from the emulator.
The emulator is slower than real life so it's much easier
to get a higher score. I hadn't disabled them sooner
because the emulator has only recently been able to run
them without crashing.
This web page and all other pages on this site are
© 1999-2007 Scott Cartier