(opens in same window)
(opens in new window)
(likely 404 error)
January-March 2008 (oldest-to-newest)
I realized recently that I hadn't posted the source code to Nuance that Riff's father graciously sent. So here it is.
I don't think this is the most recent version. That remains trapped on a USB key that Riff used to carry around with him. Unfortunately the key stopped working. Hopefully this is good enough to get someone started.
I also want to take the opportunity to officially recognize Mike's work on the emulator through this NUON Community Award. It is one of my deepest regrets that I am not able to give it to him directly. Mike's father accepted it on his behalf.
I hope that some enterprising coder can take up the torch and continue the work that Mike started.
I recently completed Hotel Dusk: Room 215 for the DS. It's an odd game - very usual from your standard gaming fare. It doesn't have any aliens, you don't shoot anything (aside from a non-interactive flashback), and nothing explodes. It is an adventure game where story is paramount. And it is utterly fantastic.
I had started the game some time back, but due to my DS running battery, and my subsequent loss of a couple hours of play time, I shelved it. I started up again some time later, playing for only five minutes here or fifteen minutes there. (The DS is perfect for this sort of thing.) And then it was done and I was left extremely satisfied.
I'm sure I will parrot a lot of other reviews of the game, but it must be said. The art style is unique. The characters are believable and well written. The plot is compelling. I spent the first half of the game wondering when it would introduce the demons or some other obvious antagonist that so often populate the games of today.
No demons. Just you walking around talking to people, learning their stories and solving some light-weight puzzles. The conversations are frequent, but thankfully they are the game's highlight due to the excellent writing. I really felt like Louie, Rosa, and the others were real people. Awesome.
It won't appeal to everyone, but if you're looking for a good interactive story I can't recommend it enough.
I finally figure out a way to trick EditStudio (ptu!) into giving me a good export of the last video blog entry. Huzzah! It involved exporting the movie to the DV format, which amounted to over 2GB for about thirteen minutes worth. Then I used AutoGK to compress that down to under 100MB so I could upload something reasonable.
So here it is. Link here for feed watchers (although you really should be using Google Reader, which I recently discovered).
First, it looks like I'm missing a tooth. That's just the lighting. I actually have wonderful diamond-coated teeth.
Here's a timeline for the video so you can skip over the technical part if you want:
- 0:00 - Hello
- 0:29 - Description of a normal line
- 1:23 - Description of a bezier curve
- 3:10 - Drawing a bezier curve - central differencing
- 4:33 - Test bed intro and engine features
- 6:43 - Test bed demos
Brief summary for those that don't want to watch right away. While at VM Labs I started work on a rendering engine that I hoped to use to create a game. I wanted to move into game development and they allowed me to work on this on the side.
The renderer is based on the concept of drawing bezier curves. Further, the curves can be grouped together in what I call enclosures and free curves. Enclosures are a continuous sequence of curves that loop around beginning to end. The inside of an enclosure can be assigned a color or texture. Free curves are merely continuous sets of curves that don't connect at the end.
The math behind the renderer isn't too complicated. I used this article on Gamasutra to explain central differencing. I certainly can't wrap my head around all the fancy pants bicubic patches, nurbs, or other stuff that's in use today. Thankfully reducing the equations to two dimensions and three control points significantly simplifies things.
There is another technique called forward differencing that can be used to tesselate bezier curves. It is explained more here. Unfortunately the technique requires you to pick a step size to tesselate. You would need to ensure that the step size you pick is small enough that you hit every pixel on the line, but not so small that you perform too many unnecessary calculations. There might be a way to predict a good step size. If I ever revisited this renderer I would investigate it more because forward differencing claims to be much less compute intensive than central differencing.
Anyway, enough tech talk. To test the various features of the engine I created two test beds. Download and burn to try them for yourself (uses the bootloader to pack both). Be warned they are not 100% stable, especially if you do anything extreme.
Download (794 kB)
Here's the controls for the various modes in each testbed.
- Testbed #1
- General controls that work in most modes
- A - change modes
- NUON - debug information (hold down)
- Dpad up/down - Curve width
- C-Up - Toggle antialiasing on curves
- C-right - Toggle number of rendering MPEs (difficult to tell)
- C-left - Toggle fill on enclosures
- C-down - Solid colors
- There are others, but are either for debug or don't work properly
- Mode 1 - Enclosure with antennae
- Stick - move object
- Start+Dpad up/down - scale object
- Start+Dpad right/left - rotate object
- Start+A - cycle fill mode through solid color, big texture, and small texture
- Start+stick - move texture within enclosure
- Start+C-up/C-down - Scale texture up/down (small texture only)
- Start+C-left/C-right - Rotate texture (small texture only)
- Start+L - Animate the object (not mentioned in the video)
- Mode 2 - Two (boring) objects
- Stick - move one of the objects
- Mode 3 - Smiley sprite
- Stick - move sprite
- Start+C-up/C-down - scale sprite
- Start+C-right/C-left - rotate sprite
- Start+A - toggle sprite on/off
- Start+Up - toggle translucency
- Start+Down - toggle bilinear filtering
- Start+L - toggle debug dots (shows each tile that is rendered)
- Start+Dpad-right/Dpad-left - scale translucency
- Mode 4 - Letter B
- Stick - move letter
- Start+C-left/C-right - rotate letter
- Start+C-up/C-down - scale letter
- Testbed #2
- Mode 1 - Two (less boring) objects
- Stick - move blue object
- Start+Up/Down - adjust translucency of blue object
- Start+Right/Left - adjust translucency of red object
- Start+C-right - toggle translucency of blue object
- Start+C-left - toggle translucency of red object
- Start+A - cycle through solid/texture for each object
- Mode 2 - Smiley sprite
- Same as mode 3 in testbench 1
- Mode 3 - Smiley sprite
- Same as mode 4 in testbench 1
- Mode 4 - Many objects
- Start+C-up/C-down - Increase/decrease number of objects by one
- Start+C-left/C-right - Increase/decrease number of objects by ten
- Start+A - Cycle through fill modes
- Start+L - Animate objects
Every interview of or talk by Jonathan Blow reinforces my belief that this guys knows his stuff when talking about indie gaming.
At the same time -- "game" is not a good word for what some of us do, and "video game" is even worse.
So when I start out trying to explain "I try to make progressive video games"... (feeling of ickiness comes upon listener as soon as I say 'video games')... "that are meaningful and try to provide growth-oriented experiences," it ends up being this 15-sentence spiel and I am losing the whole time. At the end I almost never get out of the negative numbers, back up to 0. If I were to say "I'm a fireman" or "I manage a branch of a bank" or "I am a writer of Hollywood screenplays", I would usually be looked upon much more positively.
And that is a large bummer for people who do this kind of work.
Full interview here
Yeah baby, I'm back. I connected the dev system to the good old HDTV and fired up Robot Ron for the first time since I made that video entry. And that was the first time I'd run it since I got it to compile just before I moved houses way back in 2006.
The first bug was some crash in a _vprintf routine, which I'd never heard of. Turns out I was using printf without including stdio.h. Duh. I don't know what version of printf it was trying to use, but it was obviously the wrong one. Fixing that gets the Yaroze Scene splash screen. Then it crashes immediately again. I haven't debugged that one yet.
So what caused this return to active development? I have lots to tell. Stay tuned.
I was able to get Robot Ron to play last night. It's dog slow, as is typical of the initial stages of a port, but it runs. The meat of the work has always been in the optimization and I'm sure this one will make that an understatement.
The first bug fixed was a stupid one where my Yaroze library and the Robot Ron source both had a variable with the same name. The variable was for the controller buttons so the game thought some buttons were constantly held down.
The next bug was a simple one caused by bad math when computing the sin/cos lookup table. The original used the Yaroze floating point version of sin(). I ifdef'ed it to use the NUON fixed point version. I didn't shift the result as much as I should have.
After that fix the title screen came up. I can see the same graphical glitches on the title screen as is present in Breakdown. I'll have to get to the bottom of that some day. I'm guessing some DMA command is misbehaving every now and then when the system is under load. The problem disappears when I pare the number of sprites down.
The next bug was in my Yaroze library again. For some reason I wasn't clearing button status for unconnected controllers. Robot Ron queries both controllers so it was returning a bad value and thinking the buttons where held down (again).
Fixing that allowed me to start the game playing. The analog stick moves as expected. You can't shoot yet as that requires the second analog stick on the dual shock. I'll likely map that to the second controller so you can John Woo the game with a controller in each hand. I'll still need some way to play the game with a digital pad & buttons for those that don't have two controllers or (gasp) only have a single digital controller.
And now begins the process of profiling and optimizing the game to get it up to speed. I have no doubt that I will need to halve the frame rate to get it running acceptably. I did this with Decaying Orbit. To keep the game speed from halving as well involves changing the game's source so that it runs the main loop logic twice for every screen update.
I've been doing some optimizations and in the process getting myself reacquainted with my Yaroze Library and Libsprite code.
The first bottleneck happened to be just the process of adding the sprites to the display list. The game adds over 200 sprites each frame, which obviously takes a while. I added a way to force a sprite to remain in the display list until explicitly removed. That way the main code only needs to update the sprite for its new position, rotation, scaling, etc.
Of course rendering 200+ sprites takes quite a long time too. The next bottleneck was/is the actual drawing of said sprites. That's still a work in progress.
One neat thing is that the Yaroze library can print out information on every sprite that is rendered. You see its coordinates, coloring, translucency, etc. It also tells you the renderer that is being used. The dynamic renderer loader is described in this post. (From over four years ago!) Looking at some of the output it was evident that some sprites were not using the renderer I thought they should. Investigation lead me to find that the default sprite has brightness slightly higher than normal (134 instead of the default of 128). Changing this back to 128 made the code choose the expected renderer.
One of the renderers does a basic blit from source to dest. It can only be used if the sprite has no scaling or rotation, and also if the sprite is small enough to fit entirely within local RAM. I added it for Invs to speed up drawing all those tiny invaders. Before, "small enough" was defined as less than 256 pixels total. I want to expand that to hopefully support up to 32x32, or 1024 pixels. That will allow a considerable number more sprites to use the renderer. Especially tiled backgrounds...
I've been thinking about how to automate the scaling of a game's speed to a specified frame rate *without* making it appear to run slower. So you would have a game running at X frames per second and want to change it to X/2, but still want it to run at the same speed. This means it needs to do the same amount of main loop logic, but only display every other frame (for twice as long). The side effect of course is that objects will move twice as far per frame, although since the number of frames is half it will still move at the same velocity on average. Things should just appear more choppy.
The goal is to be able to take these Yaroze games and tell the library to run it at a slower frame rate if I'm having trouble getting it to run full speed. I did something similar in Decaying Orbit whereby I halved the framerate from 60 to 30 fps in order to get the game running smoothly. It was a painful process and I want something more general so I don't have to hack up the source to every game.
Fortunately, I implemented something very similar to handle the fact that the Yaroze games from the UK are expected to run at 50 fps, but NTSC televisions run at 60 fps. I have a method to automatically display the same frame twice at certain intervals to keep the game at an average of 50 fps so that it doesn't run 20% faster in the US. In fact you could pass in any target frame rate you want and it will try to achieve it as best as it can. If you want to run the game at, for instance, 47 fps then it will come up with a set of parameters that will get close (46.67 actually). It's quite a general solution that I wrote a while back and I just recently dove through the code to understand it again.
The difference between this and the original proposal is that in going from 60 fps to 50 fps I am *intending* to slow down the game to match the original. The automation of frame rate reduction on top of that should be done *without* any apparent speed difference in the game. This means the game logic must be potentially run more than once for every time the screen is drawn.
Thing is I think it will be a pretty simple change. The routine that handles the 60-to-50 conversion can be modified slightly and called twice. Once to get the pattern to compensate for the display refresh rate (60-to-50) and again to get the pattern to further reduce it to the desired rate (50-to-25 or whatever). This second pattern would be used to tell the library how many times to run the game logic while ignoring draw commands. The combination of the two patterns tells the library how many vsyncs to wait between each frame swap.
Even though I aborted my attempt to put the NUON dev system in an Atari 2600 shell I still wanted to move it out of the big honking ATX housing that it was in.
Given that the dev system motherboard is designed to align with ATX screw holes I figured a Micro ATX case might do the job nicely. It's surprisingly difficult to find desktop uATX cases, but I did end up locating a few options. I went with this one. Mostly because I like how the front cover flap could hide the DVD drive when not in use (which is like 100% of the time).
The bad part is that after getting it I found that the 5 1/4" bay is just a hair too short to fit the dev system's DVD drive. I'm talking another 1/8 inch and it would fit. I went so far as to remove plastic from the drive in an effort to make it fit. In the end I left it out, but I may try to mount it later by removing the bay housing and mounting the drive directly to the case.
The power button on the front of the case is wired to the reset on the dev system, which is handy for when my laptop loses connection. I don't know why it happens, but haven't found a way to get it working again without a hard reboot. Thankfully it doesn't happen too often.
I used the Mini-ITX power supply because the one that came with the case was too loud.
The only other thing I wish I could do is relocate the controller ports to the front - maybe even where the USB
front panel connectors currently reside. Normally I don't need to plug/unplug controllers, but the last couple weeks I've been testing all of the ones that Riff's dad sent and it's quite a pain to need access to the back. The problem with moving the ports is that the NUON controller connector is proprietary and so finding a new set would be hard. One option is to remove the ones already on the dev system board, but I hesitate to go down that road. Another is to cannibalize a NUON DVD player to reclaim the ports, but that seems a waste. I'll probably just live with them where they are.
I'll post some pics when I get it all done.
I have the title screen for Robot Ron running at full speed now. Well, technically the render time per frame oscillates above and below 20 ms so I may do a spot more of optimization to get it at a consistent 50 fps.
The next part is the "Get Ready" screen before each level. It is dog slow due two main things. First, the star background is drawn as single-pixel lines. Thankfully I added point plotting for Decaying Orbit and can easily reuse that here. The more difficult issues are the large rectangles. I pointed them out at about 1:56 of the Robot Ron video blog post. Writing a special case renderer that handles boxes will speed things up a bunch.
Is anyone interested in playing around with this? I could post a version that you can burn to a CD and try yourself.
Edit: I also added a link to the authentication tools to the left nav bar.
I'm working on optimizing the "Get Ready" screen before each level. To get it running full speed I have written two new renderers for the sprite lib. One is a clear renderer that erases the screen and then adds stars. This will be used for the background and remove the need to draw 90 separate single-pixel sprites for the stars. The other is a dedicated box renderer so that boxes no longer need to be drawn using sprites.
I got the clear renderer mostly working and it shaved off almost 30ms per frame (used to be 75ms, now is around 45ms). The cool thing is I can go back and add this renderer to Decaying Orbit so that it no longer has static backgrounds. Huzzah!
The box renderer isn't debugged yet, but should provide a similar speed boost I would think.
Most recently, however, I dived back into the sprite library source. I want a couple small features and have hit the code size limit. The assembly has to fit in 4kB because that is the amount of iram on each MPE. I was pretty much hitting the limit, but now after some investigations I have reduced it somewhat. I shaved off about 100 bytes. This may not seem like much, but it provides more than enough room to do what I want.
One of my goals with the code reduction is to add performance monitoring as a permanent feature. In the past I could optionally include it using ifdefs. However, due to the code size hitting the limit I was no longer able to include it. Now that I've reclaimed some space I want to put it back permanently so that I can use it to tune the sprite library.
This web page and all other pages on this site are
© 1999-2007 Scott Cartier