Internal Link
(opens in same window)
External Link
(opens in new window)
Broken Link
(likely 404 error)
|
July-September 2002 (oldest-to-newest)
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
Work sucks. Dororthy is the Mole. That is all.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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...
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|