Optimal/standard full screen tiled-mode proposal

Hello, I’ve been trying to think about ways to use pokitto’s full res with 16 colors while being smart about the ram limit, came up with a proposal because unfortunately it involves messing around with asm lcd code, and I have no clue, so this will need a blessing, some healthy chats and then someone with that skills to go ahead and do this for us all, if we agree it’s the way to go.

Here goes the rumble:
Untitled-1
First off, the idea is that we have tiles, 8x8, stored in a map.h file, I’ll simply call this the map.

BackgroundMap: this is a region of the map defined by 4 ints, X, Y, Width, Height.
It acts like a clear-screen, it’s drawn at every refresh, without a buffer, directly uploading pixels to the lcd. The tiles in the bufferCanvasRegion are marked with -1 to know they will be skipped at this stage.

BufferCanvas: the smaller, the more ram you have left for your game, this area is set at compile time and allows for maps to be drawn, scrolled, and sprites to be placed arbitrarily within this region.

MarginOffset: we have 4 pixels that can’t be tiled, they would be set to a palette color, and with an offset value it could be decided if they are all to the right, to the left or split.

DynamicTiles: having the backgroundMap just as a fixed background would make it a useless decoration, we could have a dynamic array of ints to indicate which tile of the backgroundMap will be swapped with another tile from the map at the next refresh.
The lcd upload routine would look up this array before placing a tile of the backgroundMap on screen.
This would allow to use the background map for scores, dynamic text and what not.
The more tiles you want to swap, the more ram you’ll use, I think the array will need a 16bit int to be split between background tile id to swap and new map tile id to use, but at least you get to be smart about it and decide when to use this or not.

SpriteList: sprites are drawn on the bufferCanvas by specifying tiles from the map and x-y offsets, the lcd routine won’t even know about them.

What do you guys think? yay or nay?

1 Like

Here’s a real life example of how this could work for the game I’m trying to make.
Notice how the buffer needed in this case is just a mere 144x144 area, and the dynamic tiles used would amount to just about 26.
Untitled-2

Ok, you are talking about mixed screen mode, where the inner part of the screen is non-full screen buffer with 16 colors, and the border area is drawn directly, using tiles.
To me it looks like a good way to use less memory for the screen buffer and more memory for the game. As a bonus you could also use “full” 16-bit colors for the border tiles :grin:

I did not get the meaning of MarginOffset?

I think (but I might be wrong) the mode I described will required a whole new screen update routine to make it go fast enough. I can take a shot at it in c++, see if the idea is valid at all before we even think about asm. Just wanted to first check here if it sounds like a good idea or not.

Pokitto’s resolution can’t be covered by 8x8 tiles without leaving 4 columns of blank pixels.
So, since the real resolution we’ll cover is 216x176, there should be a rule on what to do with those 4 pixels on each row.
Some people might want to center their tiled screen, some other might want to leave those pixels at the right or left side of the screen.

2 Likes

Before we start thinking of messing with asm, we need to make a simple reference implementation in C++. Once that’s done I’d gladly lend a hand with the optimizations.
Diving head-first into assembly is a good way to waste a whole lot of time if there’s a conceptual issue. Besides, we’ll need the non-asm version for the simulator anyway.

2 Likes

absolutely wise, on a first glance at mode15 code I had the impression we could only talk to the lcd via low level routines, but it’s not the case, so I’m happy to test this idea in c++ first, go back to my game and use that as a test ground before anybody wastes time on this : )

If anyone has concerns about this technique or obvious things I’m missing that will not make this work, let me know.

Just go for it. Implemented like this it should avoid flickering. In the performance point of view if the size of the inner buffer is divisible by 8 we should be fine. Also I suppose the border area tiles should be refreshed only if there are changes, not on every frame. IIRC, the LCD is not forcefully cleared after each frame so there can be persistent gfx.

drawing stuff on screen like a boss :sunglasses:

As soon as I figure out how to correctly get from the femto generated images to a palette index, I’ll be pretty much done with this.

I started putting this stuff in the pokitto lib as a new render mode, but it was making other stuff redundant, so I ended up with my own simplified lib.
Don’t take it as an arrogant thing, but if this thing works it will cover my needs, from making a tiles-only game to a full screen buffered game.

3 Likes

It works! at a mere 30-40fps, but it works!
The bottleneck is in the buffer update routine, it seems that no matter what I do, I hit a 40fps cap just to send 144x144 pixels to the lcd, and I’m pretty much doing the same as the non-asm mode-15 stuff, will an asm routine make a difference here?

So far I like the animated tiled background a lot, it fills the whole screen without any mandatory ram cost.
The animated background tiles are stored in a dynamic array, so the user only allocates what’s needed, that’s how I’m displaying the fps counter right now.

I only need to add the possibility to draw tiles with a transparent color, then I can start making a game with this thing : )
The apis are soo tiny!!!

2 Likes

Don’t worry Andrea. I thought I had pretty good code before the man from Ipanema* came to town.

15fps turned into 100fps. Not kidding.

(* he who codes in the shadows)
(* the Beast from Brazil)

1 Like

40 fps does not sound bad. Note that if you set fps limit to 60 it will limit it to a much smaller value. Setting the fps limit to 200 should be good to allow at least 100 fps.

Legends say he can write emulators of whatever he gets in contact with, even your toaster. Don’t get too close he who codes in the shadows! or you’ll get emulated too.

I fear with game code I might drop some more, but it’s ok, I think I can manage and have some fun : )

1 Like

We won’t know for sure until you’ve actually published the code for people to comb through. :P

2 Likes

Did you try with SetFrameRateLimit(200)? I suspect SetFrameRateLimit(60) will not get you more than 40 fps.

2 Likes

Youp, I’ll put it up on git later today.

I even tried skipping the frame counter code completely, still 40fps.

2 Likes

edit: that video sucks unless watched full screen. And, ghosting is made in code, not a bug : D
I might have a problem of pokitto programming addiction.
I wanted to take a step back from the other game I was doing, too complex too soon, so I’m making a game&watch clone that is easy enough to be made while I also create the underlying tiled engine along the way.

If someone wants to have a peek and start an early bash on my c++ skills, here’s the whole project (femto):

I’ll create a git repo later.

4 Likes

oh that is just brilliant!

2 Likes

Do you actually want suggestions or was that “please don’t suggest anything”?

If it was the former, do you want:

  • Just the most important stuff?
  • The important stuff and the ‘good practice’ stuff?
  • The important stuff, the ‘good practice’ stuff and some potentially subjective style-related stuff?

At an absolute minimum I have to suggest that you get rid of new.
Dynamic memory allocation probably isn’t a good idea,
you could just statically allocate the memory and get rid of the init function altogether.
(I’m assuming Pokitto::Core::begin() calls all the other stuff,
so it should probably be left to the user to do that anyway.)

1 Like

Looks good!

The biggest reason, why I started programming for Pokitto was that I wanted programming to be easy and fun again. I was using Unity for a couple of projects before. I did not want to fight with huge frameworks and zillion of features any more in my free time. Just plain and simple 2d games for a simple HW. Well, I accidentally was messing with 3d calculations in Pokitto GP :wink:

Pokitto has just optimal level of complexity and features so that this does not start to feel like work to me :slight_smile:

Edit: And as a bonus, making ZX Spectrum like gfx in lores-mode is just simple enough for my pixel graphics skills.

5 Likes

Sure! any advice is super welcome, for example, divisions:
I just started optimizing where I use divisions, replacing them with incremental integers, is it gonna make any difference? my code becomes unreadable, worth it?

Nested loops, I’m guessing the fewer the better, so I’m removing those again at the expense of code readability, worth it?

As for the “new” statement, it’s used for one small array to replace certain background tiles on the fly, I thought having the option to free up ram when needed was the better choice, but maybe the cost of accessing this array on every frame is not worth it? I know allocation is slow, but that would not happen on every frame.

Code reuse/encapsulation, trying to avoid it, I usually write lots of compact funcions and maximize reuse while minimazing the need for comments, but function calls have a cost here, right? Worth making my code harder to maintain?

I’ve never needed to care about performance that much on a PC, so these are all the little doubts I have as I’m writing this engine : )