How does page flipping work?

Page 1/3
| 2 | 3

By Driehoogvoor

Resident (52)

Driehoogvoor's picture

15-08-2014, 16:37

It's going to be a rainy weekend, so more than enough time to do some more assembly. I'd like to build a small proof of concept for page flipping, but I'm not really sure about what's the best way to do it.

Basically, you use two pages, and show one page while you draw the next frame on the other page, right? As far as I see it, there are two possibilities to do this:

1. Always show page 0 and always use page 1 for drawing the next frame. When it's done, you copy the contents of page 1 to page 0 (during the vertical retrace, I guess), and then you start drawing on page 1 again;
2. You show page 0 while you draw page 1. When that's done, you switch the display to page 1 and start drawing on page 0, etc.

Which of these would be the best option? Or is there a better way to do it? I'll figure out the code by myself, I just need some pointers in the right direction. Thanks! Smile

Login or register to post comments

By Grauw

Ascended (10565)

Grauw's picture

15-08-2014, 16:44

Method 2.

The first method is really slow, no way you can do it during vertical retrace. In screen 5, copying the entire screen takes about 5 whole interrupts to complete. In the pattern modes, it’s faster but the CPU has to do all the copying work, and it’s not exactly speedy either. Whereas page switching is instant.

By Driehoogvoor

Resident (52)

Driehoogvoor's picture

15-08-2014, 16:50

Thanks, Grauw. Method 2 it is. This'll be a fun little experiment, so much to figure out. I'll post the code when I'm done. Smile

By Grauw

Ascended (10565)

Grauw's picture

15-08-2014, 17:17

Have fun Smile.

By Driehoogvoor

Resident (52)

Driehoogvoor's picture

15-08-2014, 20:14

Whew, took me a while to figure how to draw a bitmap to the screen, but I did it. I want to make the bitmap smooth scroll vertically, so I'll be writing an offset into R#23. I'm seeing some garbage scroll into view, which is probably some uninitialized VRAM. No biggie, I can clean that up.

R#23 takes a byte as value, so it can vertically offset to 256 positions. I'm using screen 5, so that would be 128 bytes width x 256 lines. That equals to #8000. I don't have any sprites right now, but those are in the #7400..#7FFF range. Won't the R#23 scrolling interfere with any sprite data?

By Grauw

Ascended (10565)

Grauw's picture

15-08-2014, 21:00

Yeah for the purpose of R#23, a screen page is 256 lines high. It’s nice, really, cause that allows you to render the content that scrolls in off-screen in the area under line 212 / above line 0. Also, you can have a game which just scrolls up and down a little bit with little cost (Space Manbow 2 is a good example of this). Or you can scroll in some menu or conversation box (think RPG), etc.

By the way, are you sure you need to use double buffering? If you want to make a vertically scrolling game like a shmup, most likely it is not needed and it’d just be a bother. Also, if you build your screen from the top to the bottom and “stay ahead of the beam”, you won’t get any visible screen tearing either. Of course that only works if your game runs at 60fps and the screen updates are small enough to actually do so.

Double buffering mostly makes sense if so many things change on screen that you can’t do it at 60 frames per second. An RPG is a good example; there double buffering can actually be beneficial if you have e.g. tiles that alternate (3 4 3 4), then you don’t need to update as many tiles each frame because these alternating tiles can stay put.

Driehoogvoor wrote:

R#23 takes a byte as value, so it can vertically offset to 256 positions. I'm using screen 5, so that would be 128 bytes width x 256 lines. That equals to #8000. I don't have any sprites right now, but those are in the #7400..#7FFF range. Won't the R#23 scrolling interfere with any sprite data?

You have to move them outside that area to e.g. 8400H-8FFFH. The base addresses can be changed.

By Driehoogvoor

Resident (52)

Driehoogvoor's picture

15-08-2014, 21:19

Thanks! I've almost got it now. Smile

The page flipping is probably not needed at all, but I wanted to know how something like that worked. I'm having heaps of fun exploring my MSX (well, the VDP, mostly) and I think I'll give it a shot and actually try making a game for it. I'm working on a small game in JavaScript (using HTML5 canvas) and that's an ode to Tetris on the Game Boy. I've been trying to make it look and feel like it would actually be able to run on a Game Boy, and I'm starting to think it would be possible to port it to MSX. You can find the work in progress here (it needs decent level generation and some other work, but the physics can be tested): http://i-am-error.driehoogvoor.nl.

The MAP is really helping me out, by the way. I'm coding on a modified F700D, which has a 7MHz switch and an MSX2+ switch (and thus a V9958 instead of a V9938). Your comment in one of your articles about how the VDP should be the bottle neck and flipping the 7MHz switch shouldn't do anything noticeable when the game is running has really become my mantra.

Grauw wrote:

Or you can scroll in some menu or conversation box (think RPG), etc.

How would something like this work with R#23? You can only offset the entire display and it even carries over when switching to another page, right? Can you target a specific part of the screen?

By Grauw

Ascended (10565)

Grauw's picture

15-08-2014, 21:42

Driehoogvoor wrote:

I'm starting to think it would be possible to port it to MSX. You can find the work in progress here (it needs decent level generation and some other work, but the physics can be tested): http://i-am-error.driehoogvoor.nl.

That looks awesome, it’d be real nice to see that on MSX :). It seems possible for sure. I also like the colour scheme.

Driehoogvoor wrote:

Your comment in one of your articles about how the VDP should be the bottle neck and flipping the 7MHz switch shouldn't do anything noticeable when the game is running has really become my mantra.

Like! :)

(Don’t go overboard though and lose yourself in optimisation. That’s the good advise I perhaps forgot to give ;p. But whenever I see a bitmap mode-based game that runs crappily on MSX2 run like a smooth tiger on an MSX turboR in turbo mode, I cringe thinking “if only they’d optimised it a little…”)

Driehoogvoor wrote:

How would something like this work with R#23? You can only offset the entire display and it even carries over when switching to another page, right? Can you target a specific part of the screen?

You can scroll up the entire screen I meant. If there’s no borders around the play area it can look kinda nice.

It is possible by the way to scroll only part of the screen by a well-timed change of the scroll register in the middle of the screen (called a “screensplit”), you can see this in the game Quarth for example. But maybe leave that technique for your next game :).

By Driehoogvoor

Resident (52)

Driehoogvoor's picture

15-08-2014, 23:38

Grauw wrote:

That looks awesome, it’d be real nice to see that on MSX Smile. It seems possible for sure. I also like the colour scheme.

Thanks! Smile I've been playing around with assembly a lot the last couple of days, and I'm starting to feel confident that I could actually pull this off if I give it a few months. Of course, I want to finish the JavaScript game first, haha. The color scheme was picked to emulate the Game Boy screen. I've got quite a few more graphics (the title screen, some more environment stuff for during the game, and even the top half of a Game Boy to wrap around all of it). The total color count is below 12, so that'll work perfectly too. Man, I'm starting to feel all excited for this project, haha. Big smile

Grauw wrote:

(Don’t go overboard though and lose yourself in optimisation. That’s the good advise I perhaps forgot to give ;p. But whenever I see a bitmap mode-based game that runs crappily on MSX2 run like a smooth tiger on an MSX turboR in turbo mode, I cringe thinking “if only they’d optimised it a little…”)

This will be my first full game in assembly, so they code will probably be far from optimized. The rendering probably won't be too hard to code, but the collision detection will take me quite some time to run smoothly, I think. So I guess I'll just try to optimize that bit and see how it goes when I play with the 7MHz switch a bit.

Grauw wrote:

You can scroll up the entire screen I meant. If there’s no borders around the play area it can look kinda nice.

Yeah, I know what you mean now. I've always liked that effect, you see it for inventory menus too sometimes.

Grauw wrote:

It is possible by the way to scroll only part of the screen by a well-timed change of the scroll register in the middle of the screen (called a “screensplit”), you can see this in the game Quarth for example. But maybe leave that technique for your next game Smile.

That's one more thing I'll have to figure out. In the JavaScript game, the playable area is only 160x144 pixels (the Game Boy's screen resolution), and that area will be wrapped by a Game Boy case. I'll need to figure out how to deal with that. Using a screensplit sounds like overkill, but that might be the fastest solution. Ah well, I'll deal with that later. Smile

Thanks for all the advice!

By hit9918

Prophet (2921)

hit9918's picture

16-08-2014, 10:25

Quote:

Your comment in one of your articles about how the VDP should be the
bottle neck and flipping the 7MHz switch shouldn't do anything noticeable
when the game is running has really become my mantra.

You still may need to slow down some VDP codes then.
Anyways a vertical scroll game with sprites can go very fast on MSX2.

Another thing is fill in the graphics of the scroller.
Need to make a software nametable (graphics puzzeling like a charset mode).
Using 16bit tile numbers you can make very big gfx.

I would fill in the gfx with cpu from RAM/ROM, is easy to code and fast.
some sketching fun, inner code to draw one line

	;vram pointer gotta be set up for that line
	;de = Y 0..7 offset in tile
	
	ld ix,0
	add ix,sp	;save sp in ix
	di

	;todo setup sp = pointing to 16bit nametable


	ld b,4*32	;32 tiles a 4 bytes, every outi does decrement B
	ld c,0x98	;VDP port
lineloop:
	pop hl		;fetch next 16bit tile address
	add hl,de	;Y offsetting
	outi
	outi
	outi
	outi		;4x outi, 8 pixels done
	jp nz,lineloop

	ld sp,ix
	ei
	ret

just 3 extra instructions per tile instead setup the blitter. cpu borderdraw is the burner.
a 16bit nametable is so fast. no address calculation from tilenumber. plus z80 POP instruction is so strong.
it even makes sense when the tools have only 256 tiles, 8bit numbers, just convert to 16bit in initialization.

By hit9918

Prophet (2921)

hit9918's picture

16-08-2014, 10:36

Quote:

The rendering probably won't be too hard to code, but the collision detection will take me quite some time to run smoothly

Bounding box checks with fixed 16x16 pixel size can go really fast.
At fast rate weed out things that need no further check.

Getting some things right in the begining one can win so much that all the rest can be comfort code.
Same thing with the pointerarray that I always recommend. It means register objects in lists.

here is the code
https://sites.google.com/site/tueftlerlabs/home/downloads/
demo20130928spriteheight.zip
labels "arradd:" and "arrremove:".

First candidate always is to have a sprite list.
Add sprites to the list and remove when they die.
Dont register object base address but the address of the Y of hardware sprite.
Then copy to SAT doesnt need to make itching address calculations.

You need some object rack where you can allocate and free objects.
I would start with 32 bytes size slots.
And the addresses of these shall be dividable by 32, then can faster create a members address.

Next candidate is the list "enemies". Everyone who can kill the player is in there.
For the collision check loop to walk this list without any sort of IF THEN about the object IDs.
Because all in the list are known to be "can kill the player" without any IF THEN.

Done these parts right, all the other object acess can go with the slow but comfortable (IX+offset) addressing.

Page 1/3
| 2 | 3