[Wiki]5.Pokitto Screen Modes

has anyone used these modes?

MODE_NOBUFFER 
MODE_ARDUBOY_16COLOR
MODE_HI_MONOCHROME 
MODE_HI_GRAYSCALE
MODE_GAMEBOY //outside of gameboy port
MODE_UZEBOX
MODE_LAMENES
MODE_256_COLOR
MIXMODE
MODE14
MODE_TILED_1BIT
MODE_TILED_8BIT

Is anyone else having issues with hi-res modes not working?

Image3|nullxnull

In hardware also?

mode 15 seems to work OK on hardware, but mode 1 appears low-res on both.

Have you got some demo code?

I tried using TASMODE for a normal game as I wanted 220x176, 256 colour. The transparency did not seem to work but did when I reverted to Mode13.

Does TASMODE support transparency or am I just doing it wrong (my first assumption)?

Transparency only work with colour index 0, this is done for speed I believe.

Oh OK … thanks, I had my transparency set as 255. Will have to change my palette up a bit as zero is black and I think I will need that!

1 Like

So … after a lot of trying, I cannot figure TASMODE out when using it as a simple 256colour 220x176. Things do not render correctly (things on the left hand side of the screen simply do not render at all!).

Is there a ‘standard’ 256 colour 220x176 mode?

220 * 176 = 38,720 and the Pokitto has 36KB of RAM (i.e. 36,864 bytes),
so there wouldn’t be enough bytes for a full frame buffer.

Yep … you are absolutely correct. I saw TAS mode and thought it was possible without doing the math.

TAS mode works because it’s splitting the screen up into tiles, hence it doesn’t use a full screen buffer despite using 256 colours and filling a full screen.

To use it as if it were a ‘standard’ mode you’d have to have enough repetition in your image that you could represent your image using tiles.

Depending on what you’re trying to do there might be another approach you could try. Though ultimately you’re probably either going to have to sacrifice some precision or do some direct drawing (which I suspect will have to be reasonably fast to avoid tearing).

I found that frustrating as well, so I started implementing what I call a strip-buffer 8bit mode, where the whole screen is split into X pieces (I’m currently using 11).

  • Split the screen in X pieces (either vertically or horizontally)
  • For each piece:
    • Render your scene into an appropriate buffer, with the right clipping and appropriate offset (11 vertical slices -> x will be offset by 0, 20, 40, 60, …).
    • Upload the buffer to the screen.

It’s kind of an intermediary between TAS and a full-screen buffer and it combines both sides perks and issues:

  • Your buffer is 38kB / X and it’ll be allocated on the stack.
    • In my case I’m using 11 strips, so I need 3520 bytes available on the stack, in addition to the regular stack reserve.
  • You have to redraw things X times, with an offset each time.
    • That means you cannot draw things in your update loop, but instead outside of it.
    • That also means you should be careful not to have complicated calculation there, as it’ll be called X times on each update!
  • In average, every drawing primitive (tile, sprites, lines, …) is faster than in TAS (especially the vertical-inclined ones).
    • Of course, they’re also slower than full-screen buffer!
  • Because it’s like printing on X screens, things are going to get clipped X times.
    • Non-H/V lines (and probably polygons when I get to that point) need special consideration - otherwise they won’t join properly. We don’t get to see that in a fullscreen buffer.
  • Whole screen effects (like a blurring one) will look weird on each edges if you’re not careful.
  • While it requires some stack, it doesn’t need a drawing list to maintain.
    • My own system is simply asking each visible entity to redraw itself X times.

In any case, it’s more complex than both Screen Buffer and TAS. I’m using it because it’s definitely worth it in my case (3D iso stuff having a lot of vertical/slanted things, …), but there is a high mental cost whenever I need to render stuff. Grouping things together for example is welcomed (e.g. your character needs 5 sprites, you’re asking yourself “is at least part of the character visible on this specific part of the screen?”)

Funnily enough, I can easily make a split-screen game with this but I haven’t found yet an application to that :stuck_out_tongue:

4 Likes

Surely it ought to be possible to statically allocate it by declaring it as a global rather than a local?

Just to note: this can be sped up by using some kind of space partitioning in the game world, or by simply sorting objects by their y coordinate, and then either by their x coordinate or their ‘z’ coordinate if there’s zome kind of depth to take into account, like the UI being drawn on top of the monsters.

That way you could do something like this:

std::size_t objectIndex = 0;

// Go through all the strips
for(std::uint8_t y = 0; y < 176; y += stripSize)
{
	std::uint8_t yEnd = (y + stripSize);
	
	std::size_t nextObjectIndex = ~0;
	
	// Draw all objects within the current strip
	while(objects[objectIndex].y < yEnd)
	{
		auto & object = objects[objectIndex];
	
		draw(object);
		
		// This is needed for when objects overlap two strips,
		// otherwise you only draw half an object
		if(((object.y + object.height) >= yEnd) && (nextObjectIndex > objectIndex))
			nextObjectIndex = objectIndex;
	
		++objectIndex;
	}
	
	if(nextObjectIndex < objectIndex)
		objectIndex = nextObjectIndex;
}

This assumes an ‘object’ will overlap two strips at most. If your objects overlap three strips, you’ll probably need to maintain a ‘redraw list’ of objects you need to redraw in the next strip. Either that or you need to dynamically move the objects in the obejct list around as you draw, which could get awkward.

1 Like

It is, but flushing to the LCD generally happens when the stack is empty, so it’s better than allocating statically and having all that memory be permanently unavailable.

1 Like

@FManga explained it all. I did initially consider allocating a global and use a union or std::variant so I could reuse that memory for other, temporary calculation. Then I remembered that it was exactly what the Stack was meant to :stuck_out_tongue: and in a much, much easier way than with a union/variant.

That’s also what is doing TAS by the way - the 220+ bytes linebuffer exists only when TAS is doing its stuff. I didn’t take out this buffer-on-the-stack out of nowhere :stuck_out_tongue: @FManga did

Also, I agree there are numerous opportunities for optimizations. But as you can see, compared to the ScreenBuffer it’s far from being straightforward…
I’m definitely going to use a lot of these opportunities in any case; only as they’re optimizations they’ll be relevant only when I got the more important stuff done first and when I can easily and properly measure how good they might be

2 Likes