Register - Login
Views: 95749959
Main - Memberlist - Active users - Calendar - Wiki - IRC Chat - Online users
Ranks - Rules/FAQ - Stats - Latest Posts - Color Chart - Smilies
11-13-18 08:19:32 PM

Jul - Projects and Creations - Superfeather SNES Game Engine New poll - New thread - New reply
Next newer thread | Next older thread
HihiDanni

Level: 6


Posts: 4/11
EXP: 614
For next: 293

Since: 02-02-18


Since last post: 281 days
Last activity: 227 days

Posted on 02-03-18 12:17:51 PM (last edited by HihiDanni at 02-05-18 08:14:51 PM) Link | Quote
Over the past couple years I had decided to pursue SNES homebrew. The idea came to me after playing Sparkster SNES, a game that clearly showed that the SNES hardware has a ton of potential, but could have performed better. Originally I was going to make a full game featuring Lyn, the dragon you see in my avatar (though the original sprite was somewhat smaller). I ran out of steam pretty early, but later I revisited my work and decided to turn it into a general engine for myself and others to use.

Superfeather is a homebrew game engine for the SNES. It is written in 65816 assembly. The core tenets are Performance, Flexibility, and Convenience. In other words, I'm looking to get a lot out of the relatively humble CPU, but also make it easy to do so, while remaining generalized enough that it can be adapted to a variety of games. It's a work in progress, but right now I have the following:

- Gameloop - VBlank handling, and a scene system which lets you cleanly switch between different screens in a game (e.g. levels, title screens, whatever you want).
- Game Objects - You can create and destroy objects dynamically and give them behaviors to run every frame. You can move them around with 16.8 fixed point precision. Default maximum of 128 objects.
- Sprites - You can draw single sprites as well as metasprites. You can define animations with callbacks to choreograph all kinds of behavior sequences.
- Other Stuff - Third party audio driver (SNESGSS), crash handler, Lua-based buildsystem, basic DMA scheduling.
- User Manual! I explain how all the stuff in the engine works.

There's still a lot of stuff I need to do but so far I'm pretty happy with the core essentials. Some things I hope to implement soon:

- VRAM engine and metasprite editor for easy importing of complex graphics and streaming of those graphics to VRAM
- Scrolling levels and a level editor
- Data structures for optimizing collision checks (for shmups)

I do have some binary releases, but given the current progress on 0.6, I'd rather have folks wait until that's released as it fixes a lot of issues with 0.5.

Github project page is here!

Here are a few examples I've made so far (click on pictures to download):


bounceballs - Spawns 128 bouncing balls. I kind of wish I could have gotten the CPU a bit lower but it's still enjoyable to watch.


metaspritebounds - I made a recent optimization that completely avoids drawing metasprites if they are completely outside view. The metasprites are made out of four 16x16 sprites each which is why CPU is high and it hits the sprite limit pretty quickly. It's meant to test an extreme worst case scenario regarding metasprite usage, and seems to handle it okay!


objectpools - Illustrates the object pool system, where you can dedicate different object slots to different kinds of objects.


walker-dynamic - Shows how to make a controllable character with callbacks for footstep sounds and animation via VRAM sprite streaming.




Some interesting metrics:

- An empty scene takes about 8% CPU. 3% of that is from iterating through an empty object list with 128 slots. 3% of that is from finalizing the in-RAM copy of OAM. 2% is from the VBlank handler which uploads the in-RAM OAM to the PPU and does some other stuff.
- Each ball in the bounceballs demo uses about 0.47% CPU. The majority of that time is spent drawing the sprites themselves. Since 128 sprites is the worst case scenario, this should mean that in practice you have quite a bit of headroom to do all the stuff you want in your game and remain at 60 FPS.

Right now I'm trying to come up with a good algorithm for allocating sprite slots in VRAM for sprite streaming. Ideally there will be different sizes of slots (thinking 32x32, 64x32, and 128x32) - the varying sizes means I will need to come up with a strategy to defragment the space if I don't want to settle with having totally separate regions for each slot size.
maple
Member
Level: 19


Posts: 130/153
EXP: 32686
For next: 3091

Since: 01-19-18

From: a linode vps

Since last post: 270 days
Last activity: 128 days

Posted on 02-03-18 05:37:28 PM Link | Quote
this is extremely relevant to my interests
BatElite
Member
Level: 23


Posts: 90/188
EXP: 61458
For next: 6265

Since: 04-24-17

Pronouns: they/them, maybe also she/her

Since last post: 7 days
Last activity: 3 hours

Posted on 02-05-18 03:09:25 PM Link | Quote
I need to get a SNES emulator on here again.

Love the little green dragon.
maple
Member
Level: 19


Posts: 134/153
EXP: 32686
For next: 3091

Since: 01-19-18

From: a linode vps

Since last post: 270 days
Last activity: 128 days

Posted on 02-05-18 04:13:39 PM (last edited by maple at 02-05-18 04:16:34 PM) Link | Quote
oh gods what happened to this page's layout

edit: pls remove
height: 100%;
from
.hihidanni-base
that doesn't scale to content
HihiDanni

Level: 6


Posts: 10/11
EXP: 614
For next: 293

Since: 02-02-18


Since last post: 281 days
Last activity: 227 days

Posted on 02-05-18 06:10:08 PM (last edited by HihiDanni at 02-05-18 08:14:43 PM) Link | Quote
Originally posted by maple
oh gods what happened to this page's layout

Sorry about that. Should be fixed now.

So last night I came up with three possible strategies for allocating slots in VRAM for streaming sprites:

- All slots are the same size (eg. 32x32). The object requesting the slots needs to remember all of the slots, and do separate sprite calls to render the whole metasprite. It's easy to implement from the VRAM manager perspective but it really complicates things for users and bloats the memory used by game objects, neither of which I want.

- Slots can be different sizes, but each size of slot has its own exclusive region (e.g. 32x32 slots have one region in VRAM, while 64x64 slots have another). Easy to implement, but you waste a lot of space.

- Slots can be different sizes, and regions can be given to any size slot. Flexible, but requires defragmentation. Objects may spawn a few frames late as a result.

I'm currently looking to implement the third option. A couple things I will need to work out first:

- How to perform the defragmentation. I'm considering having it so that if any object is animating (i.e. it will need to stream to VRAM anyway), try to move it to any VRAM slot that is to the left.

- How to determine, with constant time complexity, which slots are remaining. I already have a system for this for creating and destroying game objects, but the different VRAM slot sizes makes this trickier, because you need contiguous space to allocate the larger spanning slots.

I'm going to prototype this before I implement it in the actual assembly code. Suggestions are welcome too.
Next newer thread | Next older thread
Jul - Projects and Creations - Superfeather SNES Game Engine New poll - New thread - New reply




Rusted Logic

Acmlmboard - commit 220d144 [2018-11-04]
©2000-2018 Acmlm, Xkeeper, Inuyasha, et al.

28 database queries, 2 query cache hits.
Query execution time: 0.183567 seconds
Script execution time: 0.014181 seconds
Total render time: 0.197748 seconds