gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > MODE 7 for a Beginner...

#17756 - ZombieMauler - Sun Mar 14, 2004 6:34 am

Hi,

I have 2 questions:

1/ Where can I find an easy-to-understand mode-7 tutorial?

2/ For those of you who know how to use mode-7, would it be possible to have something where: the pitch of the camera angle is something similar to mario kart, but there is a sprite as an rpg character, and there is a lot of scaling sprites that are, for instance, trees around it?

Thanks

#17757 - Gopher - Sun Mar 14, 2004 7:44 am

I don't know which would be easiest to understand, but I'm pretty sure there are several tutorials in the Tutorials section on the subject; if they leave you confused, search the forums for "Mode 7" as I'm sure it's been covered more than once in here helping other new GBA programmers learn to use it.

[edit]
I realised shortly after posting this that in this next section that I was talking about something else. You wouldn't need to update the matrices for the objects every hblank unless you wanted them to be projected like the ground is. This is not what you wanted to do, so you would only need to change the matrices once per vblank. I'm leaving the next rit in, just noting that it's not directly related to this question.
[/edit]

As for using scaling/rotation sprites, you can certainly do this, and I'm pretty sure Mario Kart does. There are two limitations. First, there are only 32 rot-data structures to be shared by all 128 sprites. Since every sprite would need it's own unique matrix based on it's position in the world, you could only have 32 such objects visible at a time.

The other limitation is that all the matrices must be updated durring the HBlank. I don't have the numbers off the top of my head, so I'm not certain if the HBlank is long enough to easily copy all 33 matrics (BG + 32 sprite), but it doesn't seem unreasonable. It would be simpler if they were linearly arranged, but they are interleaved with the sprite data in OAM.

I'm still fairly new to GBA myself so I don't have things like the length of the HBlank memorized yet. Maybe someone else will do the math, or maybe I'll look it up later.

#17758 - poslundc - Sun Mar 14, 2004 7:59 am

Gopher wrote:
The other limitation is that all the matrices must be updated durring the HBlank. I don't have the numbers off the top of my head, so I'm not certain if the HBlank is long enough to easily copy all 33 matrics (BG + 32 sprite), but it doesn't seem unreasonable. It would be simpler if they were linearly arranged, but they are interleaved with the sprite data in OAM.


There is little reason to apply HBlank transformations to the sprites. Sprites are considered to be projected onto the camera's frustrum in just about every Mode 7 game, so all they require is scaling and translating to the correct position.

The greatest limitation is the sprite rendering cycles available per line. Depending on whether you want to be able to affect OAM entries during HBlank, this is either 1210 or 954 cycles. Normal sprites take only 1 cycle/pixel, but scale/rot sprites consume 26 cycles every 8 pixels, and if you have to double-size them then naturally they will consume twice that. For something like an RPG this can be damn well near disastrous if you aren't careful. (I've had to seriously abridge the graphics specs for my Mode 7 RPG on account of this limitation.)

Dan.

#17759 - Gopher - Sun Mar 14, 2004 8:03 am

poslundc wrote:

There is little reason to apply HBlank transformations to the sprites. Sprites are considered to be projected onto the camera's frustrum in just about every Mode 7 game, so all they require is scaling and translating to the correct position.


heh, you must've been posting this while I was editing my original post. I realised I was being a bonehead shortly after posting it.
_________________
"Only two things are infinite: the universe, and human stupidity. The first is debatable." -Albert Einstein

#17815 - ZombieMauler - Mon Mar 15, 2004 5:52 am

Damn :(

I was thinking of a large number of sprites, (I was inspired by how Outrun used so many sprites to create depth and a weird immersion to the game)

Looks like I'll have to think of something else...

#17816 - tepples - Mon Mar 15, 2004 6:09 am

Remember that you can still have about 300 pixels worth of rot/scale sprites on one scanline, which is more than the screen width and more than you could have on the Super NES even without rot/scale. To get around the limitation of 32 different scaling matrices, use pre-scaled sprites at power-of-two intervals and switch among them, using the 32 scaling matrices to interpolate between adjacent powers of two.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#17824 - poslundc - Mon Mar 15, 2004 2:52 pm

tepples wrote:
To get around the limitation of 32 different scaling matrices, use pre-scaled sprites at power-of-two intervals and switch among them, using the 32 scaling matrices to interpolate between adjacent powers of two.


Hey, that's a clever idea. But keep in mind that for many Mode 7 games you can also often reuse the scaling matrices. Eg. if I am using an entry to scale a character, that same entry can also scale his weapon and any visual effects being applied to him. So 32 matrices doesn't necessarily mean you're limited to 32 sprites, just 32 distinctly locatable "objects" in the world (which you can use tepples' technique to overcome if you want to exceed it).

Me, I've got up to ten distinct objects (characters) in the battlefield at once, and they could conceivably all bunch together in the same area (with some overlap). Originally I was using 32x32 sprites for them, but they can scale upwards to 64x64, potentially causing scanlines to require 2080 cycles to render! Any suggestion on how I could deal with that without reducing my sprites to 16x32?

Dan.

#17829 - tepples - Mon Mar 15, 2004 4:50 pm

For those objects that may bunch together, use even more pre-drawn sizes like on the Super NES. This may not work for an EWRAM-based program where footprint is everything.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#17834 - poslundc - Mon Mar 15, 2004 5:39 pm

I don't know how practical that would be... since there's going to be a pretty huge tileset for all of the battle sprites, the amount of tile data required could get pretty overwhelming. I would require 32 times the image data to cover the growth stages from 32x32 to 64x64.

Plus, at this point I'm only swapping VRAM data when a sprite animates or changes direction, but doing that would mean swapping every sprite's data whenever the camera moves. Even if I just DMA raw data in, it could potentially take half my VBlank period, which I don't know that I can afford.

Even if, for example, I only had 300 battle sprites (25 poses for 12 different creatures/characters), 32 scale-levels of a 64x64 sprite would consume 18.75MB! Sure, I could compress it to maybe half that, but then I'd be in hell trying to decompress it during VBlank (EWRAM would be too slow, and I'm already using most of it for other stuff).

Dan.

#17852 - poslundc - Mon Mar 15, 2004 11:54 pm

Okay, my new idea is to use the rot-scale feature for HALF of my sprites, and for the other half (if they are larger than 32x32) using plain 64x64 sprites. During VDraw, I'll attempt to run a fast, nearest-neighbour scaling algorithm into an EWRAM buffer (5 sprites will consume 20K, which I can afford). Then I'll DMA it into VRAM during VBlank, which should take about 17 scanlines (not cheap... but may be necessary).

The only better system I could think of would be to double-buffer in Sprite VRAM, but I don't think I have enough of it...

Dan.

#18091 - poslundc - Sat Mar 20, 2004 6:04 am

I don't know if anyone cares about what I've been doing here... but anyway, it looks like I almost have my code working. Give me another couple days and I'll let y'all know what kind of resource consumption it is taking.

Right now I am special-casing all 128 possible scale-levels between 32x32 to 64x64, with specific ARM code to scale up a single scanline of a 32x32 image for each of these. Because the scaling is uniform (ie. every single scanline follows the same pattern of scaling) it becomes a fairly long code sequence for one scanline, which then gets called 32 times for each scanline of the sprite.

When the algorithm first runs it DMAs the appropriate code out of the ROM and into an IWRAM buffer, then branches to that code to process each scanline.

I'm optimizing the crap out of this thing... logistically speaking it should be impossible for me to get very good performance anyway. Even if I can, say, get 64x64 pixels at a cost of only 5 cycles per pixel, that's still 16 scanlines worth for a single sprite, or half my VDraw just for the 5 sprites I'm aiming to do. But if I can get it running fast enough it may be just what the doctor ordered for me to get all of my scaled sprites on the screen without running out of cycles.

Dan.

#18155 - poslundc - Sun Mar 21, 2004 10:43 pm

Results are in...

It seems that scaling a 32x32 up to a 64x64 sprite using my technique on an EWRAM cache takes between 6 and 10 scanlines on hardware (depending on the complexity of the scaling factor). DMA from EWRAM to VRAM during VBlank then takes about 3 scanlines.

So altogether I'm looking at up to 50 VDraw scanlines to scale my 5 sprites, and 15 VBlank scanlines to transfer them into VRAM. Not too bad, considering in return I'm getting sprites that consumes only 64 cycles/scanline to draw instead of 208 cycles!

Also, depending on how the weight of processor consumption in my program is distributed I can always scale some of the sprites directly to VRAM, or to an IWRAM cache. (It's that waitstate for EWRAM that makes everything so much more brutal.)

Anyway, there's still a lot more work to be done on it, but it's now moved past the theoretical workaround stage and into the viable solution phase.

Dan.