Jan-Mar 1997
Oct-Dec 1997
Jan-Mar 1998
Apr-Jun 1998
Jul-Sep 1998
Oct-Dec 1998
Jan-Mar 1999
Apr-Jun 1999
Jul-Sep 1999
Oct-Dec 1999
Jan-Mar 2000
Apr-Jun 2000
Jul-Sep 2000
Oct-Dec 2000
Jan-Mar 2001
Apr-Jun 2001
Jul-Sep 2001
Oct-Dec 2001
Jan-Mar 2002
Apr-Jun 2002
Jul-Sep 2002
Oct-Dec 2002
Jan-Mar 2003
Apr-Jun 2003
Jul-Sep 2003
Oct-Dec 2003
Jan-Mar 2004
Apr-Jun 2004
Jul-Sep 2004
Oct-Dec 2004
Jan-Mar 2005
Apr-Jun 2005
Jul-Sep 2005
Oct-Dec 2005
Jan-Mar 2006
Apr-Jun 2006
Jul-Sep 2006
Oct-Dec 2006
Jan-Mar 2007
Apr-Jun 2007
Jul-Sep 2007
Oct-Dec 2007
Jan-Mar 2008
Apr-Jun 2008
Jul-Sep 2008
Oct-Dec 2008
Jan-Mar 2009
Oct-Dec 2009
Jan-Mar 2010
Apr-Jun 2010
Jan-Mar 2011
Oct-Dec 2011

July-September 2002 (oldest-to-newest)

3 Jul 2002 - Bye Katie

Always happens. As soon as I peg someone as not being the Mole they get eliminated. Makes sense I guess since all the other players have N-1 other people to decide amongst while she had all N.

This episode was of the tug-at-your-heart-strings variety. So not much Mole activity. I will say this though. If Dorothy is the Mole she is doing a really lousy job of hiding it.

6 Jul 2002 - Level editor

Game Progress I have begun work on an in-game level editor for Chomp. Hopefully this will make it easier for people to create user-made levels. It will be a lot faster than having to recompile (and in open SDK-users case, re-burn) every time you change something.

Right now I have it placing walls and pills. Next is fruit, then Chomp & enemies. Finally I'll add some utilities to make editing less painful. Stuff like automatically mirroring one side to the other, deleting rows and columns, stuff like that.

9 Jul 2002 - More progress

Game Progress So now you can place walls, pills, and fruit. Next up is power pills (simple cut-and-paste) and then the starting positions for Chomperman and the enemies. I also have some useful utilities in the works. You can bring up a menu where you will be able to do such things as delete rows/columns, insert rows/columns, change the maze size, toggle mirroring while drawing for horizontal/vertical, etc.

Still to come is an easy way to test your level. Also, it needs to be able to change the maze into the ASCII characters they represent so that you can copy them down and insert the maze in the source code. Without a memory card interface that's the only way to make your maze permanent.

11 Jul 2002 - And then there were five

Fun episode last night. I'm still surprised how much Dorothy appears to the be the mole. I hope it's just an act, but fear that maybe she just isn't that great at hiding it. I was sorry to see Darwin go. Next to be eliminated is Bribs. He's the last one I'm sure isn't the mole.

  • Al - Maybe - No reason to say yes this time.
  • Bill - Maybe - He had to work to avoid being neutralized. Of course he could have done that as the mole anyway.
  • Bribs - No - He's too honest and it will cost him. He'll be gone in the next two episodes.
  • Dorothy - Yes - The way she acts and doesn't show emotion just screams "mole". Plus she just happend to figure out the combination to the lock. Like maybe the producers gave it to her beforehand.
  • Heather - Maybe - No real reason to suspect her this time.
15 Jul 2002 - Level editor progress
Game Progress Here's a silly little maze I created in about a minute using the level editor. The mirror functions make it so easy. "Undo" doesn't do anything at the moment. Also, while the code is there to add the player & enemy starting points I haven't tested it at all. Once I get that going I can get the "Test" feature working.

I wanted to have this all done this weekend, but was rather busy with other things. Friday night we went to a Giants game at Pac Bell Park. It was our first time there and we were mighty impressed. Baseball is so much more fun watching it in person than on TV. Of course it helped that the Giants won 9-0.

Saturday I got up early for training. I'm always glad when I go, but man 6:15am is too early to be awake. Then we helped someone move Saturday afternoon. Sunday was more fun - mostly because I could sleep in. We hit a bucket of balls in the morning.

All during this weekend I was getting my comic collection organized in preparation for a large round of auctions on eBay. My parents mailed me the last of my comics from the closet in my old room in Virginia (yes, I'm nearly 30). I'm going through them and putting some in new comic bags. I really didn't take great care of them when I was younger. It'll probably take another week or two of preparation before I start the actual auctions. I have well over 500 comics to sell.

17 Jul 2002 - I hate it when I'm right

Well Bribs got offed as predicted. This season is a lot less mysterious than the last. How can anyone watching the show not think Dorothy is the mole? Everything she says and the way she says it points to her being the mole. Yesterday I was reading the message boards on the ABC web site (God help me) and some people were actually picking Bribs. I mean COME ON PEOPLE! Use your brains for once.

  • Al - No - According to this episode, the rest of the players voted him least likely to be the mole. They should know.
  • Bill - No - I'm voting Dorothy all the way.
  • Dorothy - Yes - How can she NOT be?
  • Heather - No - She was much too realisticly distraught over not getting the exemptions.
18 Jul 2002 - It all starts now

I made the first steps to porting Decaying Orbit to NUON. I copied over the directory structure and tried to compile it. After fixing a few fatal makefile and include file problems it compiled normally. That is to say with hundreds of errors. Now begins the long slog going through and fixing them. After that I'll need to write my own functions to emulate all the Yaroze library functions. Let's hope all of this doesn't take two years like it did originally.

21 Jul 2002 - That was easier than I thought

Game Progress Turns out I wasn't seeing hundreds of errors. Rather it was hundred warnings. Since I compiled with the -Wall option it was printing out every single warning it found. I removed that option and fixed one remaining error and it compile successfully.

I created empty dummy functions with the same name as the Yaroze libraries so that it could link correctly. Filling in (and debuging) the contents of those functions will comprise the bulk of the time porting the game.

It's funny going back and looking over the code you wrote years earlier. I have since changed the way I name variables, structures, and other constructs. I'll try to change as little as possible, but it'll be tempting to do an overhaul of the code.

One thing I'm worried about is performance. The original Yaroze game is done in hi-res 640x480. It will be interesting to see if NUON can handle it. What concerns me most is the C performance on NUON. The processor in the Playstation is pretty common and well known. It has the benefit of lots of people working on its compilers for a long time. The NUON processor is relatively new. Its compiler doesn't take advantage of the processor's VLIW design very well so much of the potential benefit is not used.

21 Jul 2002 - Follow along at home

Game Progress Here's a list of all the Yaroze library functions I need to implement. I anticipate many of them to be easy to get working. Some are Yaroze-specific so they would have no NUON equivalent.

  • CdPlay
  • ClearImage
  • DrawSync
  • GetPadBuf
  • GetTPage
  • GsClearOt
  • GsDefDispBuff
  • GsDrawOt
  • GsGetActiveBuff
  • GsGetTimInfo
  • GsInitGraph
  • GsSetWorkBase
  • GsSortBoxFill
  • GsSortClear
  • GsSortFastSprite
  • GsSortLine
  • GsSortSprite
  • GsSwapDispBuff
  • LoadImage
  • MoveImage
  • ResetGraph
  • SetVideoMode
  • SsSetMVol
  • SsSetSerialAttr
  • SsSetSerialVol
  • SsUtKeyOn
  • SsVabClose
  • SsVabTransfer
  • StoreImage
  • VSync

As I get them done I'll check them off the list.

24 Jul 2002 - Mole == Dorothy

Both my wife and I called it last night as Al was the next to go. Unless Bill pulls an upset we think Heather will win it all. It all depends on the final quiz. They could pull out some really wild questions and cause Heather to fumble it. It's kind of a let down since there was so much mystery and suspense last season.

Game Progress Rather than keep track of the full list of Yaroze functions, let's just go for the subset that are necessary to get the very first thing displayed on the screen.

  • GetPadBuf
  • VSync
  • GsGetTimInfo
  • LoadImage
  • GetTPage
  • SetVideoMode
  • GsInitGraph
  • GsDefDispBuff
  • MoveImage
  • GsGetActiveBuff
  • GsSetWorkBase
  • ClearImage

GetPadBuf - Returns a pointer to the location in memory where the controller info (buttons, analog stick values, etc) are placed. The actual values in the controller structures are updated during each vertical sync. This was a pretty easy one to write since all I had to do was declare an array to hold the controller info and return its pointer.

VSync - An essential part of any graphic system. Proper use of the vertical sync ensures that what you see doesn't get accidentally overwritten by the current frame being drawn. While the Yaroze VSync is very similar to the NUON VidSync there are subtle differences. The main one is that the Yaroze function can return a count of the number of horizontal syncs that have elapsed since the last vertical sync. Sort of a crude way to profile parts of your code to see how fast they execute. Get the count before and after and subtract. Anyway, since the NUON VidSync does not have the same capability I had to leave that out. No biggee for Decaying Orbit since it never uses it.

At some point I'll have to write about how I intend to go about porting the sprite environment. I've been thinking about it quite a bit, trying to figure out how to make it general enough so as to make it possible to port other sprite-based Yaroze games in the future. At the same time it needs to have optimizations so that it isn't dog slow. It's quite an interesting problem.

30 Jul 2002 - Yaroze-to-NUON ramblings

Work sucks so I haven't had much time to program. I have a handful of things left to add to the level editor before releasing version 1.4 of Chomp. Then it's full-bore on Decaying Orbit. (Never thought I'd say that again.)

First, a little bit about the porting process.

One of the challenges in porting the Yaroze environment to NUON is how video memory is managed. The Playstation has 2MB of vram, arranged as a 1024x256x16-bit buffer. It makes things easier if you visualize this graphically. Below is a representation of this buffer as shown by one of Sony's utilities called TimTool.

Click on the image to get a full-sized version. The large green section is the display buffer - the part that gets put on the screen (640x480 in my case). Any images you are currently using for sprites must fit in the areas around the display buffer. While the images (known as TIMs) are initially located in main memory they must be loaded into vram before they can be used as sprites (or textures in the case of polygons). Naturally you can swap images in and out of vram as needed by your program.

In the image above you can make out some of the graphics that go into Decaying Orbit. They are squashed horizontally because they are 4-bit sprites and use a color lookup table (CLUT) to display properly. While you can use full 16-bit images, it is more efficient to use 8-bit or, in my case, 4-bit palettized images. Not only does this reduce the size of the graphic in main memory, but it also takes up less room in vram.

One restriction placed on sprites is that they can only be so large. You'll notice the buffer is divided into 32 sections. Each of these sections is called a T-Page (I think this stands for "texture page"). Sprite images can be no larger than one tpage. If you want something larger you need to break it up into multiple sprites. Since each tpage is 64x256x16-bit, the maximum size for 16-bit sprites is 64x256. However, by using 4-bit images you can fit four times as many pixels horizontally - thus your sprite can be 256x256.

As you can see there's a pretty large incentive to use CLUT-based images. This causes a problem when trying to port it since the NUON sprite library wasn't built to handle palettized sprites. The program on NUON will need to convert the images from 4-bit to 16-bit. Doing this for every sprite every frame would take too long. I plan to do as much of the conversion as possible in advance. The program will convert the image from 4-bit to 16-bit the first time it is used. Then as long the sprite does not change it won't need to do so again.

The program will need to manage a list of these converted images to ensure coherency with the Yaroze vram. Every time a new image gets loaded into the Yaroze video buffer the program will scan the list and invalidate any images that it overlaps. Invalid images must be reconverted before their sprites can be rendered.

That's it for now. I'll dump some more of my thoughts soon.

31 Jul 2002 - Blah

Work sucks. Dororthy is the Mole. That is all.

7 Aug 2002 - Could you pass the crow?

Because I'm eating a full helping of it. Holy cow, Bill was the Mole?!? Like last season I was completely duped. Dorothy is one smart cookie to pull off so many suspicious things. Good for her - she deserves the money.

7 Aug 2002 - Endianness

Game Progress One more function is (mostly) done.

  • GetPadBuf
  • VSync
  • GsGetTimInfo
  • LoadImage
  • GetTPage
  • SetVideoMode
  • GsInitGraph
  • GsDefDispBuff
  • MoveImage
  • GsGetActiveBuff
  • GsSetWorkBase
  • ClearImage

GsGetTimInfo - The TIM (or Texture IMage) is the image file format used on the Yaroze. It is mostly just another image file format like TGA or BMP. It has entries for the pixel data and color lookup table, as well as some Playstation-specific data. TIMs contain data that tells the PS where to load the image into 1024x512x16 video ram.

The GsGetTimInfo function parses a TIM and puts the essential information in a GsIMAGE structure. This structure is what's used to create sprites.

One of the problems with the TIM is that (since it is created on the PC) it is encoded in little-endian format. Since NUON is big-endian the function must first convert the TIM. Luckily this conversion only needs to be done once per image so it will not hurt performace in the long term.

9 Aug 2002 - Yaroze progress

Game Progress I find that I can fit in some programming in the morning before I go to work. It's only about half an hour's worth, but better than nothing. I'm hoping to have the first image displayed this weekend.

  • GetPadBuf
  • VSync
  • GsGetTimInfo
  • LoadImage
  • GetTPage
  • SetVideoMode
  • GsInitGraph
  • GsDefDispBuff
  • MoveImage
  • GsGetActiveBuff
  • GsSetWorkBase
  • ClearImage

LoadImage - Moves an image from main memory into the Yaroze video memory. On NUON it's just a couple of DMAs. However, I kept getting a hang bug and finally figured it out this morning. I had to set the cluster bit during the bilinear DMA. I never really understood what this bit does or when you need it. I think if your buffer is larger than some number of pixels wide then you need to use it.

GetTPage - This one was easy. It simply returns which of the 32 T-Pages a particular X,Y coordinate falls. A few bit shifts is all that's required.

12 Aug 2002 - Sight for sore eyes

Game Progress I got the first splash screen to display Sunday night. It's the one that was required by the Official Playstation Magazine cover disc. It's a good first test and I finally got it to show up. Granted the colors are all messed up since I haven't done the RGB-to-YCrCb color space conversion yet, but it's still recognizeable. I need to get the screen shot routines working so I can snag some images.

  • GetPadBuf
  • VSync
  • GsGetTimInfo
  • LoadImage
  • GetTPage
  • SetVideoMode
  • GsInitGraph
  • GsDefDispBuff
  • MoveImage
  • GsGetActiveBuff
  • GsSetWorkBase
  • ClearImage

GsSetVideoMode - This chooses between NTSC and PAL. This does nothing on NUON since the BIOS handles it all.

GsInitGraph - Selects the screen resolution and color depth. There's only two color depths 16-bit and 24-bit. The resolution gets translated into the video channel structure in NUON.

GsDefDispBuff - Defines which part of the Yaroze video ram is the actual display buffer - the part that gets put on the screen. I need to keep track of this so I can regenerate the NUON frame buffer when it changes. For the most part this will be handled by the sprite library, but the Yaroze can do raw blits too.

MoveImage - Copies an image from one portion of the Yaroze vram to another. This is why the previous routine is important. When the program MoveImage's something into the visible part of the frame buffer I need to reflect that in the actual NUON display.

GsGetActiveBuff - Easy one. Returns which of the double buffer is being used at the moment.

GsSetWorkBase - In Yaroze this sets where to insert draw primitives for later rendering. In NUON it does nothing.

ClearImage - Blits a constant color over a rectangle in the Yaroze video ram. This one's pretty easy.

14 Aug 2002 - Ah, that's better

Game Progress It took longer than anticipated to get the image you see. The color conversion itself was pretty simple, but getting the screen capture working took a while.

When I take a screenshot (using a special button pattern on the controller) the program copies the bilinear frame buffer into a linear raw image in memory. It is supposed to print out the address of this new image so I can download it from NUON to my PC. However, for some reason printf() wasn't working. It's amazing how something so seemingly trivial as printf() can bring things to such an abrupt halt.

I finally traced it down this morning to a conflict with the Yaroze library. While the Yaroze does not have its own printf() (I had already checked for that), it has functions called write(), read(), and others. One of those must have had the same name as a function required by the NUON printf(). Once I fixed that it started working like a champ.

The nice thing about taking screen shots is that its code is handled by the VSync() routine. Since VSync() is used by every part of the program it should be possible to take screen shots anywhere. As a bit of backstory, my original screen grabbing routines for the Yaroze were such that you had to hard code them into every section of the game code that you might want to grab shots. The current way is so much better.

"Written in over one year" - What an understatement.

20 Aug 2002 - They must be invisible

Game Progress ...because I can't see any sprites yet. I'm very close to having something show up, but am getting some strange behavior. First, MPE0 crashes when I try to use the sprite engine on it. I changed to to only MPEs 1 & 2 and it seems to work better, but nothing is showing up. Rather there is garbage on the screen, which is strange since I wouldn't expect that. Even stranger is when I load the graphics into the simulated Yaroze video ram it looks like some of the data is ending up in the visible portion of the frame buffer. This shouldn't happen since the Yaorze vram is totally separate from the two display buffers. Must debug...

21 Aug 2002 - What's the point of 16bpp?

Game Progress By chance I happened to look at the NUON docs for the various pixel types. I saw that 16-bit pixels actually take up a full scalar. I was assuming that the system packed two 16bpp pixels into one 32-bit scalar. That explained why I was seeing stray pixels show up where I didn't expect. I had only allocated a buffer of size (1024 x 512 x 2) when I really needed (1024 x 512 x 4).

As much as it would be nice to create perfect code every time, it sure is incredibly satisfying to find and fix bugs. As stated in this thread on Yak's forum, coding can produce a rush at times. Damn I wish I could do this full time.

22 Aug 2002 - Sprites!

Game Progress I finally got the first sprites to display. It's just a moving starfield, but it's something. Only the truly curious should grab this zip (662kB). I would highly suggest using a CD R/W since it's hardly worth burning a CD-R.

If you run it you'll see the opening splash screen as shown in my previous update below. Press the A button to continue. The screen will turn green for a while then the stars will pop up.

I'm rather disappointed with the speed. They should be moving a lot faster than they are - at least twice as fast. I need to find a way to optimize the sprite handling. If the system can't draw a measly 100 2-by-2 pixel sprites without slowing down I don't know how it will cope with the rest of the game.

Well to be fair the way the stars are drawn is somewhat different from the other sprites in the game. Basically I reuse the same sprite structure for all 100 sprites. When you add a sprite to the display list on the Yaroze it copies all the necessary info to the list. Then you're free to alter the original structure if you like. Normally I don't - I keep a separate structure around for every sprite. However, to draw the stars I add the same sprite to the list 100 times, changing the X,Y coordinates between each call. Not very efficient I know, but it would be a shame if I had to start hacking away at my code just to get it running acceptably.

22 Aug 2002 - Now I don't know what to think

Well I convinced myself that the 16-bit pixels are indeed packed so that there are two per scalar. So I still need to find a reason for the corruption I was seeing. For now I got around it by allocating twice as much memory as I technically should need. It's really going to bug me until I figure it out.

23 Aug 2002 - Faster, but not quite there yet

Game Progress I've been trying to get the stars up to full speed with some limited success. I timed various sections of my code to find the trouble spots and what I found surprised me.

I started by tinkering around with the sprite library code to make it more friendly to my needs. The first thing I noticed is that when you add a new sprite to the display list it inserts the new sprite after all other sprites that have the same or higher priority. So in my case since I am drawing 100 sprites with the same priority it needs to traverse the entire list every time it inserts a new one (the new sprite gets placed at the end of the list). I changed it so that it stops traversing the list when it finds a sprite with the same priority. That helped a little. Of course this means that the sprites will now be drawn in the reverse order that you insert them. I'll eventually make this behavior optional so that the default case still acts like it used to.

Next, I added a new function to the sprite library called SPRReset(). This clears the display list and marks all sprites as unused. Making a dedicated function for this is more efficient than calling SPRRemove() and SPRDelete() for every single sprite. That helped a little too.

Finally I found the source of the majority of the slow down. I had left in a "fflush(stdout)" statement in one of the routines. Normally when you call printf(), the result goes into a buffer. The text only gets printed to the screen when the buffer is full and gets flushed. The fflush() function forces the buffer to flush immediately. This is less efficient, but sometimes necessary (for example, if you want to ensure your printf() shows up before your program crashes).

Fixing that helped tremendously. Before these changes a full frame was taking about 152ms, which translates to around 6fps. Now it takes about 55ms or 18fps. As a point of reference, I need to get this down to 16ms in order to achieve 60fps. I'm not done yet!

Probably the best thing I can do to improve speed is to double buffer the display list in the sprite library. This is the way the Yaroze works and would allow me to work on one list while the other is busy being drawn.

Next, my vertical sync routine takes about 25ms. This includes code to translate the data from the NUON controller into the PSX format. I'm sure there's room for optimization there.

26 Aug 2002 - Optimizing

Game Progress Lots of optimization done this weekend. I'm now sitting somewhere between 30 and 40 fps. This is exciting since it means that some frames actually take less than 16ms to draw. A bit more optimization and all of them will be that fast and I'll be at 60fps. Of course I did comment some stuff out so once I add that back it will slow down a bit. I hope it doesn't take much of a hit.

There were two main optimizations. The first was double buffering the display list in the sprite engine. When you call SPRDraw() it copies the sprites to a secondary list and passes that to the renderers. Your program is then free to change the original list without worrying about messing up the rendering. Before, you had to SPRWait() to ensure the renderers were done before modifying any sprite structure.

The second main optimization was to move the task of clearing the screen from the SPRDraw() C code to the renderers themselves (in assembly). Combined with the first optimization above, the delay to clear the screen becomes hidden. And since it was originally taking 16ms just to do the clear that's a huge savings.

With these out of the way, the thing that's taking the most time now is generating the sprites. One sprite by itself isn't so bad, but drawing 100 of them is a bit much.

And this is just one of the intro screens! I haven't even gotten to the main game play loop. Right now the C code is the bottleneck, but once I start throwing more hefty sprites at it I think the renderers will start chugging.

27 Aug 2002 - Returning the favor

My friend's not-so-nerdy (but mostly empty) website.

6 Sep 2002 - No progress

We went down to Disneyland over the long weekend. We haven't been there in quite a few years so it was nice to see all the new stuff. California Adventure is the new park they added. It has a couple really cool rides, but for the most part is rather ho-hum.

Game Progress Due to the trip, there's not much progress to report on the game. The main bottleneck now is the time it takes to create all 100 sprites and insert them into the display list. There's not much left to optimize - it's just the sheer number of sprites that's causing the slowness. I may just move on to the rest of the game in the hope that the problem is isolated to the intro screens.

10 Sep 2002 - Some success

I'm getting ready to put up a monster set of auctions on eBay. That has occupied most of my time the last few weeks. So sorry if the updates have been sparse - things will improve soon. I'm selling almost my entire comic book collection - something like 1500 comics. Rather than bunch them all together in one big auction I broke them down into their individual series. I should make more money that way (right Milon?), but it's a heck of a lot more work. I ended up writing a Perl script to parse my Excel spreadsheet and create the auction pages for me. I would go insane if I had to type all 90+ auctions in by hand, even with cut-and-paste.

Game Progress I'm sitting around 34-37 fps now. That's up from 30-32 so things are improving. (Incidentally, in Aries3 mode it jumps to about 45 fps.)

I had what I thought was a good idea recently. Rather than call both SPRCreateSprite() (which moves a sprite from the "free" queue to the "used" queue) and SPRAddSprite() (which moves it from the "used" queue to display list) I created a new function called SPRCreateAndAddSprite() that does both at once. This lets me bypass the "used" queue entirely and saves a couple calls to the queue insertion/removal routines. Similarly I added a SPRRemoveAndDeleteSprite() to combine those two functions as well.

This had absolutely zero effect for a while. Or rather it had a good speed boost one time and then every time after that it didn't seem to help. I finally tracked down the problem to me tinkering with the makefile. I don't know why I would have done such a thing, but I must have removed the "-O1" switch from my CFLAGS. This is the switch that does level-one optimization. My thinking probably was that I would get the game working well without optimization and then turn it on to get a nice final speed boost. Anyway, by removing that switch the compiler does absolutely no optimization, which causes it to generate some truly horrible assembly. Once I added the switch back the speed benefit I expected once again reappeared. So now my strategy is to use -O1 during development and switch to -O3 for release versions.

This all helped, but not as much as I was expecting. Either the bottleneck is elsewhere or the changes just didn't improve things as much as I thought it would. It might be the case that the renderers on the other MPEs are taking longer to draw the frame then the C code on MPE3. They run in parallel and I've been focusing on improving the C code, so if the renderers are chugging I will need to focus my efforts on them instead.

Before I dive into that, however, I want to release a new version of the sprite library that includes all the changes I've made. I need to test it out on other programs (Chomp, VMBalls, etc) to ensure I haven't broken anything. Also, I want to do some speed tests to find out how much faster the new library is. I'll do that by changing VMBalls to draw as many balls as it can in one frame. Then I can measure how many more sprites it displays with the new library.

12 Sep 2002 - Catching up

Game Progress Just catching up for those of you that don't read the NUON forums.

I took Riff's advice and removed the PACKED attribute from the sprite structures. This significantly reduced the code size and sped up most of the sprite routines. It seems the PACKED attribute was having the undesirable effect of telling the compiler not to assume any specific memory alignment for the structures. This means that is was doing ugly ANDs, ORs, and shifts every time it accessed one of the structure's members. By removing the attribute the compiler could see that the structures were 4-byte aligned and use normal loads and stores.

That got me to about 36fps. Next I noticed that the game was spending a lot of time just waiting for the renderers to finish. This means that the C code is fast enough and now the bottleneck is with the renderers themselves. I had only been using MPEs 1 & 2 to do rendering. Once I added MPE0 the frame rate increased to 42fps. However, the C code is still waiting a long time for the renderers to complete.

One of the problems is that I'm drawing 100 sprites that are essentially single pixels (I had to actually make them 2x2 since the sprite lib can't handle 1x1 sprites). If I were to write this game from scratch I wouldn't use sprites at all. But since I want to keep code changes to a minimum in the game itself I will keep them as sprites.

I have two ideas to gain more speed. One is to do a bit optimizing in the renderers themselves. I won't touch the inner loops, but there are a couple spots that I think I can improve.

Secondly, I want to try triple buffering the display, rather than double buffering. The frame rate is now between 30 fps and 60 fps, which means some frames are taking less than 1/60th of a second and some are taking more. So while the fast ones can complete in time, the slow ones cannot. Triple buffering lets you smooth things out by essentially borrowing the extra time from the fast frame and giving it to the slow frame.

19 Sep 2002 - Misc ramblings

I am in the process of starting the eBay auctions for my comic books. Since I have so many, I'm staggering their start times a bit. I'll have them all up by Saturday. It was a supreme pain getting them all organized and the descriptions written. Thankfully I found eBay's Turbo Lister. It lets you input all the auction data offline and upload them when you're ready. That way you can tweak things until everything is correct. It's also easy to make copies of auctions in case you have multiple similar items.

Game Progress With the comic stuff almost out of the way I did a spot of programming last night. I added a small optimization to the sprite code so that it doesn't bother computing reciprocals (which is very expensive cycle-wise) if the X- or Y-scale is 1.0. I think that got me a couple more fps.

I tried compiling Chomp with my version of the sprite lib and it died horribly. I must have broken something in the process. So before I release the lib I need to get it back to a working state with all known sprite apps.

I had a rather disturbing realization recently. At 54 MHz, the bandwidth of the main bus is 216 MB/sec. At 60 fps that gives 3.6 MB/frame. With a frame buffer of 640x480x32 that means I can read and/or write the entire frame buffer only two full times per frame. Taking into account the initial clear, that leaves only one full pass over the FB every frame. This does not give me much hope for getting Decaying Orbit working in its full glory.

I will definitely need to hack the DO source to have any hope of getting it running at 60fps (which is pretty necessary or else the game will be too slow). Also, I will probably need to reduce the resolution to 320x240. This means scaling all the sprites and will definitely not look as good.

24 Sep 2002 - Updated sprite library

Game Progress After some minor bug squashing I'm happy to make the updated sprite library available for download. Grab it through the link on the left. Copy "libsprite2.a" into your "C:\vmlabs\lib\" directory and "sprite2.h" into "C:\vmlabs\include\nuon\" (substitute your path as appropriate). You will also need to change your makefile to use "-lsprite2" rather than "-lsprite" and any references to "sprite.h" will change to "sprite2.h". See the readme file for details on the changes.

You will need to change your call to SPRInit() to include one extra parameter at the end. Simply pass in zero for now. This is the "flags" parameter and is used to enable some new features in the library.

Straight away you should see some speed-up without any changes to your code. The removal of the PACKED attribute allows more efficient C-to-assembly translation. The next easiest way to get a boost is to make the renderers handle the clearing of the screen rather than the C code. To enable this, pass in SPR_FLAG_CLEAR_FAST in the final parameter to SPRInit(). If you currently clear the screen yourself (rather than letting SPRDraw() do it) or don't clear it at all then this won't help you.

The next big boost will require some modification of your main loop. The way the original library worked you could not touch any of the sprite structures after calling SPRDraw() or else risk corrupting the sprites being drawn. By turning on SPR_FLAG_DOUBLE_BUFFER you force the library to make a copy of the sprites and pass those to the renderers. You are then free to muck with the originals. This means that your program can execute normally without you having to tip-toe around the sprite structures. If you previously called SPRWait() after SPRDraw() then you will see a big benefit from this option. It basically allows the renderers to run in parallel to your main program.

The last flag is SPR_FLAG_ADD_REVERSE. This is only really useful when you do lots of calls to SPRAddSprite() and SPRRemoveSprite(). This is the case for my Yaroze translation, but isn't the way a good program would be written from scratch.

As always, mail me with questions, problems, or suggestions.

24 Sep 2002 - Taking a page from Yak

Things I am #1 on Google for: 16 bit sprites

It's always fun to look at the extreme tracker stats. That's the icon at the very bottom-right of the page. I had no idea I was even listed on Google's web directory list for independent game developers. Pretty good description too.

25 Sep 2002 - Library update

Breakout Man Stephen Anderson found a problem with the new sprite library. I posted an updated version fixing it. Grab it from the same place as before.

It was a silly bug in the SPRBlitter routine. It's strange since I had run the new library through Chomp, which uses the blitter, and it worked fine.

This web page and all other pages on this site are © 1999-2007 Scott Cartier