Page 3 of 6
Re: Beat Em Up Game Engine Ideas.
Posted: Sat Mar 28, 2015 10:41 pm
by Drew Sebastino
psycopathicteen wrote: I just want to use a huge load of 8x8s, like an NES on steroids.
I agree with you 1,000% The main thing I don't like is how a 16x16 object with only 8x16 of the object filled out will count 16 pixels instead of 8 to the sprite pixel per scan line limit. People always complain about how "slow" the SNES's CPU is (the people who do don't even know what a bit is. They just compare 7.6 with 3.58, and if both processors were exactly the same, the Genesis's CPU would blow the SNES's out of the water, but they aren't) but the sprite pixel per scan line limit is far greater to me. (I'd gladly get rid of BG 3 and transparency and mosaic and window layers and the useless 64x64 sprites and hi res mode and all that jazz for 2x the amount of overdraw any day of the week)
psycopathicteen wrote: I know the oam address gets left at the hioam byte of the last sprite rendered, but can you manually change the oam address to where you want it?
You mean kind of like say you try to store a number at $0010, but it instead stores it at $0020, so you store it at $0000, knowing it will turn into $0010? I've wondered the same thing.
(You know, maybe we could get our good buddy 93143 to "help" us.

)
Re: Beat Em Up Game Engine Ideas.
Posted: Tue Jul 19, 2016 5:57 pm
by 93143
Okay, so... I'm pretty sure it's possible to change sprite table locations mid-screen via OBSEL with zero artifacting regardless of how many sprites are onscreen or where they are. Just not the way I was doing it before...
The trick is apparently to do the write during active display, when the sprite system is busy with OAM, rather than during HBlank when VRAM fetch is going on.
First Try changes OBSEL with HDMA, which is probably why it's glitchy. In other words, my earlier attempt
was a softball, and only worked because I wasn't loading it down heavily. (Fortunately the actual application is a situation where I've already used up all the HDMA channels and need to use an IRQ anyway...)
I wrote a test program that loads up the whole screen with unique sprites, plus an additional 16x16 (actually a quad of 8x8s - long story) that can be moved around by the user and changes colour and shape halfway down due to the table location change. No glitches, whether the OBSEL write happens fairly early in the scanline or very late. I hacked it up to have 32 sprites per line in the area of the switch, and a Mode 7 layer mathed with the whole screen. Still no glitches (though you wouldn't know it, looking at the mess I made of the display).
There are two programs: "spritetest2" is the nice one, and "spritetest2s" is the hacked-up one. The hacked-up one has two 8x8 sprites deliberately missing from each of the two rows bracketing the switch, so as to allow the movable shape to be visible without clipping, and below those rows there are no sprites. I'd make the hacked-up one look nice too, but I've spent too long on this already...
EDIT: Just so it's clear, the name "spritetest2" never appeared in my internal workflow before now. The fact that the earlier test has the same name is an accident; I must have changed it for the forum, to distinguish it from the first version of "spritetest"...
Espozo wrote:(You know, maybe we could get our good buddy 93143 to "help" us.

)
Maybe someday. I only did this because it was easy, and I had a bit of breathing room...
Re: Beat Em Up Game Engine Ideas.
Posted: Fri Jul 22, 2016 9:22 am
by Stef
That is a really nice find

I already try to do that on Megadrive to bypass the 80 sprite limit per screen (in case we use many small sprites) and in fact it just doesn't work. Relocating the Sprite table during display is not enough to get the sprites correctly updated on screen. The problem is that the MD VDP has an internal cache which store a part of the sprite table and this cache is updated only on VRAM write operation (the VDP detect you are writing to the Sprite Table area and update the internal cache according). So if you just change the sprite table VRAM address without actually rewriting the Sprite Table itself the VDP internal cache is not updated, also that lead to weird behavior as some part of the sprite attribute are always fetched from VRAM while other are read from internal cache (Castlevania Bloodline uses that behavior in water level for sprite reflection effect).
Re: Beat Em Up Game Engine Ideas.
Posted: Fri Jul 22, 2016 3:36 pm
by psycopathicteen
I think he's talking about switching pattern banks midscreen, not doing sprite multiplexing.
Re: Beat Em Up Game Engine Ideas.
Posted: Fri Jul 22, 2016 3:44 pm
by 93143
Yeah, I think there may be a terminology issue here.
On MD, the "sprite table" is presumably the SAT, equivalent to OAM on the SNES. OAM is not in VRAM; it's separate memory, so you can't change where it is. Currently no one knows if it's possible to multiplex sprites during a frame on SNES, but if you can it's probably very difficult because of how the internal OAM addressing works.
What I meant by "sprite table" in the context of the SNES is the OBJ data, equivalent to... well, VRAM on the MD. One of the major issues with the SNES sprite system is the 16 KB sprite graphics data limit imposed by the fact that there are only two 8 KB OBJ tables available. What I have just shown is that it is possible to bust that limit under certain circumstances, by changing which two 8 KB areas of VRAM are considered sprite data partway through a frame. Unfortunately each scanline is still limited as before, which means this works best when the vertical position of the sprites is well controlled, such as when they are being used as a second BG in Mode 7, or maybe in a fighting game with very large characters (you can set it up so that either table can be relocated while leaving the other where it is).
So yeah - I haven't (yet?) figured out how to have more than 128 sprites on SNES without rendering them down on a coprocessor like the Yoshi's Island title screen does (or on the S-CPU like psycopathicteen's bullet hell tests do). I've just managed to allow the PPU to access more than 16 KB of graphics data for sprites in a single frame.
Re: Beat Em Up Game Engine Ideas.
Posted: Fri Jul 22, 2016 3:48 pm
by tepples
"Sprite VRAM bank switching" might have expressed this intent better.
Code: Select all
7654 3210 OBSEL ($2101): Sprite size and bank select
|||| |+++- Offset from first to second bank ($1000, $2000, ..., $8000)
|||+-+---- Address of first 8K sprite bank ($0000, $2000, $4000, or $6000)
+++------- Sprite sizes (useful values: 0 for 8/16 and 3 for 16/32)
Super NES VRAM can be thought of as divided into eight banks, each $1000 words (8 KiB) in size. Each bank can hold up to 256 16-color tiles. The S-PPU's sprite unit has two windows, which can be set to one of the eight banks. (The first window can use only even banks.) Bit 0 of byte 3 of each OAM entry determines whether the first or second is used:
Code: Select all
7654 3210 OAM[4x+3]: Sprite attributes
|||| |||+- Sprite tile window to use
|||| +++-- Palette to use ($80, $90, $A0, ..., $F0)
|||| Only $C0-$F0 are eligible for blending
||++------ Priority (3 in front)
|+-------- Horizontal flip
+--------- Vertical flip
A game can use the first window for sprites used throughout the screen and the second for things limited to the top or the bottom of the screen. This may require careful layout of the screen, not unlike the division into horizontal strips that Atari 2600 games rely on.
For comparison, the Genesis VDP drops one priority bit and one palette bit to gain two more tile number bits, allowing use of all eight banks:
Code: Select all
7654 3210 SAT[8x+4]: Sprite attributes
|||| |+++- Sprite tile bank
|||| +---- Horizontal flip
|||+------ Vertical flip
|++------- Palette to use
+--------- Priority (1 in front)
Re: Beat Em Up Game Engine Ideas.
Posted: Fri Jul 22, 2016 4:02 pm
by Sik
93143 wrote:On MD, the "sprite table" is presumably the SAT, equivalent to OAM on the SNES.
Yeah, SAT = Sprite Attribute Table. But people always drop the "Attribute" part.
Re: Beat Em Up Game Engine Ideas.
Posted: Fri Jul 22, 2016 4:06 pm
by psycopathicteen
It still looks like it would be crazy complicated to juggle sprites between pages.
Re: Beat Em Up Game Engine Ideas.
Posted: Fri Jul 22, 2016 4:27 pm
by 93143
psycopathicteen wrote:It still looks like it would be crazy complicated to juggle sprites between pages.
Depends what you're doing, I guess. I'm using this technique for my shmup port, because a rendered layer over a Mode 7 backdrop eats a lot of OBJ memory. Sprite paging is relatively simple to handle in this case, since the rendered layer never moves, and the actual game sprites are mostly small and easy to hardcode.
It seems to me that a fighting game could be a plausible application too, as long as non-player sprites like projectiles are either
locked to the player's vertical position or small enough to duplicate between tables without killing the space available for BG data.
I can see how this Idea might be complicated to make use of in a Beat Em Up Game Engine, though, or a platformer or a run 'n' gun or something like that...
Re: Beat Em Up Game Engine Ideas.
Posted: Sat Jul 23, 2016 3:12 am
by Stef
Oh yeah sorry i misunderstood, only the sprite tiles bank is switched here... i guess that sentence "it's possible to change sprite table locations mid-screen via OBSEL with zero artifacting" got me wrong because i'm too used about how Megadrive works. Indeed on SNES OAM is outside VRAM and cannot be relocated. Still i think that surpassing that 8/16 KB limit is interesting depending the game situation... but bypassing the OAM limit would be even better i believe

What i tried to do on MD is to have 2 SAT (Sprite Attribut Table or OAM for SNES), one for all sprites with Y position between [-31...128] and a second SAT for sprites with Y pos between [96...223] (need 32 pixels overlapping so sprites between [96...127] are duplicated). That way i could get more than 80 sprites (the more you split the SAT, the more you can get) but unfortunately my method couldn't work :-/ I guess updating the OAM during active display on SNES is even tricker than doing it on MD (from what i read OAM could not be write at all during active display or you get corrupted result).
On MD I found a simple trick to display 128 sprites (work both in H32 and H40 mode). You just need to arrange the sprite in SAT so they are linked somehow by Y coordinate (of course still respecting inter sprite priority correctly) so you just need to modify the sprite #0 link field during active display to bypass already rendered sprites. You can modify it once or twice per frame if you really want to exploit the maximum of 128 sprites. This work as internally the link field is 7 bits so the SAT size is 128 entries even if VDP cannot parse more than 80 (linked) entries per scanline.
Re: Beat Em Up Game Engine Ideas.
Posted: Sat Jul 23, 2016 3:54 am
by tepples
Imagine a separate SAT for every 16 scanlines.
"Holey DMA, Batman! That sounds like an Atari 7800!"
Re: Beat Em Up Game Engine Ideas.
Posted: Sat Jul 23, 2016 4:11 am
by Sik
tepples wrote:Imagine a separate SAT for every 16 scanlines.
I once considered porting
Illumination Laser and legitimately thought about this >.> The idea would have been to reserve 16 entries to use for bullets, then every 16 scanlines this part of the SAT would be rewritten (since I'd only change the Y coordinate as all bullets would be 16×16 and link would remain the same as well, multiplexing would take up only like 3 scanlines, overhead included). Then at least there'd be less risk of running out of sprites when the game goes bullet happy. I'm not sure how feasible the extra complexity is in practice though =/
Re: Beat Em Up Game Engine Ideas.
Posted: Sat Jul 23, 2016 4:12 pm
by psycopathicteen
I just read an article about Cho Ren Sha for the Sharp x68000, and according to the developer, he used both sprite multiplexing, and dynamic animation, to have up to 512 sprites onscreen, and have unlimited animation frames. I'm not exactly sure what type of dynamic animation he used, but it sounded like he checked every individual 16x16 sprite if it was in VRAM or not, and looked for new slots when an existing slot was not found. I don't know if there were any memory bandwidth limitations for the x68000. It appears that sprites on the x68000 use a separate memory chip, so it might use an alternating bus system between the CPU and sprite chip.
Re: Beat Em Up Game Engine Ideas.
Posted: Sat Jul 23, 2016 4:30 pm
by Drew Sebastino
psycopathicteen wrote:I'm not exactly sure what type of dynamic animation he used, but it sounded like he checked every individual 16x16 sprite if it was in VRAM or not, and looked for new slots when an existing slot was not found.

Re: Beat Em Up Game Engine Ideas.
Posted: Sat Jul 23, 2016 5:21 pm
by Sik
psycopathicteen wrote:I just read an article about Cho Ren Sha for the Sharp x68000, and according to the developer, he used both sprite multiplexing, and dynamic animation, to have up to 512 sprites onscreen, and have unlimited animation frames.
Yeah, 128 sprites per quarter screen, and in fact Illumination Laser is using the same code (a large part of the reason it slows down is because it's an amalgamation of tons of 3rd party libraries glued together lol, lots of syscalls going on)
psycopathicteen wrote:I don't know if there were any memory bandwidth limitations for the x68000.
I couldn't find any sort of information on DMA to transfer data into sprite memory. Now, I may have missed something (I don't really know how to program the X68000 =P), but if that's indeed the case then it'd mean the CPU has to stream the graphics on its own, which is probably a cap in itself (although later X68k models use faster CPUs that don't waste as many cycles when doing bus accesses, and as I said this game is quite prone to slow down)
psycopathicteen wrote:It appears that sprites on the x68000 use a separate memory chip
There are 32KB reserved just for sprite graphics, yeah.
Espozo wrote:psycopathicteen wrote:I'm not exactly sure what type of dynamic animation he used, but it sounded like he checked every individual 16x16 sprite if it was in VRAM or not, and looked for new slots when an existing slot was not found.

16×16 is literally the only sprite size on the X68000, so that probably makes things simpler =P