gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

ASM > Double Buffer in Mode 3

#9930 - Omega81 - Fri Aug 22, 2003 2:29 am

Anyone know how I can implement a double buffer in mode3. so as to draw graphics off screen and copy it to the screen later or is page filpping the only option on the GBA?

thanks
_________________
Keep it real, keep it Free, Keep it GNU

#9932 - tepples - Fri Aug 22, 2003 3:07 am

In mode 3 or 4, you can stretch the screen horizontally (BGAFFINE[2].pa = 0x80), draw in the left or right half, and then scroll (BGAFFINE[2].x = pageno ? (120<<8) : 0) to the part of the screen you want displayed. This gives you double-buffering in mode 3 and double-buffering with ample spare VRAM in mode 4.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#9946 - Omega81 - Fri Aug 22, 2003 6:37 pm

The problem is I am trying to create fire and I need a buffer to shift the flame up, blur the screen and then blit it fast to the actual screen. the problem is my current function copies the content of a buffer and stores it in the screen buffer. But the pixel location were it is plotted is wrong even through I am calculating the pixel location in the buffer like I would on the screen (y*240+x). For some reason when I copy the buffer halfword at a time, the pixel I plotted in the buffer is ploted 3 times. The buffer copy code is shown below.

Code:

.global CopyBuffer
.arm
.align 4
CopyBuffer:   
    ldrh r3,[r0],#2   
    strh r3,[r1],#2
    subs r2,r2,#1
   bne CopyBuffer
end:
bx lr


I believe this function is fine so I don't know why a buffer of the same size as the screen buffer doesn't copy correctly.My buffer is a u16 (unsigned short) array and the screen buffer is a u16 pointer. any ideas?
_________________
Keep it real, keep it Free, Keep it GNU

#9948 - hzx - Fri Aug 22, 2003 7:22 pm

That code will run at insufficient speed for a double buffering display. Why dont you use DMA?
_________________
.hzx

#10234 - regularkid - Sat Aug 30, 2003 10:04 pm

Mode 3: No double buffer, 240x160x16
Mode 4: Double buffered, 240x160x8
Mode 5: Double buffered, 128x120x16 (not sure on the resolution, but it's smaller)

So, no, there is no double buffering in mode 3 (unless you do it yourself in some other place in memory...but that wouldn't be very fast). Mode 4 is your best bet if you are trying to real time drawing where you have direct access to the video buffer. Hope that helps.
_________________
- RegularKid

#10238 - sajiimori - Sun Aug 31, 2003 5:58 am

regularkid,

You're confusing double buffering and page flipping.

Double buffering is where an off-screen buffer is copied to the screen every frame.

Modes 4 and 5 provide page flipping, which means there are two video pages and a flag that controls which page is to be displayed. No copying is necessary, so this is totally different from double buffering.

Also, you don't know if Omega81 considers 16 bit color more important than the difference in speed, so saying that mode 4 is the "best bet" is a little presumptuous.

#10242 - FluBBa - Sun Aug 31, 2003 11:09 am

@sajiimori:
I don't know where you've got the idea that double buffering is about copying stuff.
Double buffering is exactly what it sounds like, nothing more, nothing less.
You have 2 buffers which you alter your writes between.
That's it.
Even on the old Amiga 500 we did "double buffering" and was using 2 chipmem buffers and changing the bitplane pointers to either of the 2 buffers, that is what you would call page flipping, which is completly true also. In the control panel for nvidia gfx card you see that they call the copying of buffers something like bitblocktransfer or so, can't remember.
_________________
I probably suck, my not is a programmer.

#10254 - regularkid - Sun Aug 31, 2003 7:19 pm

sajiimori,

Just trying to help. Page flipping and double buffering are the same thing...like FluBBa said, no copying is necessary. You simply have two buffers, one that is currently being shown and another "hidden" one that you are drawing everything to. Then, at the appropriate time, you "flip" which one is currently being shown and which one you are drawing to. Also, since Omega81 asked about double buffering and want's to do something (drawing a fire) in real-time, then using mode 4 would give you the speed you need, the double buffering, and still give you a full screen (240x160). Of couse this is my opinion and not everyone may think this way.
_________________
- RegularKid

#10262 - tepples - Sun Aug 31, 2003 11:42 pm

The difference is that in the documentation for the Allegro game programming library for PC, "double buffering" and "page flipping" refer to different things. "Double buffering" refers to double-buffering where the back buffer is in WRAM and the page-flipping consists of a blit() to a single page of VRAM. (Rough equivalent on the GBA this would be full-res mode 3.) "Page flipping" is double-buffering where either (a) the back buffer is as big as two screens, and page-flipping consists of a hardware scroll (as in scaled mode 3), or (b) there are two surfaces, and page-flipping consists of a hardware switch between the surfaces (as in mode 4 or mode 5).
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#10273 - sajiimori - Mon Sep 01, 2003 8:01 am

Hmm, it seems there are some semantic differences between different computing cultures. I apologize for speaking prematurely.

In fact, here is a snippet of SDL documentation which agrees with the definition of page flipping as a subcategory of double buffering:

SDL_DOUBLEBUF - Enable double buffering; only valid with SDL_HWSURFACE. Calling SDL_Flip will flip the buffers and update the screen. If double buffering could not be enabled then SDL_Flip will just perform a SDL_UpdateRect on the entire screen.

#14661 - Snake - Sat Jan 10, 2004 10:42 am

I don't know if I'm too late to post on this question but I'll do it anyway..

In my conversion of Barbarian for the GBA I have used Mode 3 exclusively and of course needed to double buffer the screen. I set up a double buffer in external RAM, which is of course of exactly the same size as video RAM I.E. 480x160 pixels = 76800 (Each pixel is 2 bytes).
Access to any given pixel is given by:-

Base address of buffer + (X*2) + (Y*480)

Where X = 0 TO 239
and Y = 0 TO 159

When you have drawn a complete frame DMA copy it to the video buffer
like this:-

Set DMA3SAD to Base address of buffer
Set DMA3DAD to Base address of video buffer
Set DMA3CNT_L to 76800/4 = 19200
Wait for VCOUNT > 160
Set DMA3CNT_H to 32 - bit copy and enable it

Source code example:-

ldr r1,=back_buffer

ldr r0,=DMA3SAD
str r1,[r0]+4!
mov r1,video_buffer
str r1,[r0]+4!
mov r1,19200
strh r1,[r0]+2!
mov r2,0x8400
ldr r3,=VCOUNT

waitfb

ldrh r1,[r3]
and r1,r1,0x00ff
cmp r1,160
ble waitfb

strh r2,[r0]
mov pc,lr

Frame rate is very good assuming entire game is written in assembler. In Barbarian I actually have quite a large delay in the main loop to keep the game speed down.

snake

#14674 - Miked0801 - Sat Jan 10, 2004 6:41 pm

You're doing the transfer during VBLank right - to prevent tearing? The advantage of the stretching of the bitmap and copying off-screen is that the update can happen anytime and only the scroll register update need occur during vblank. Of course, you lose half your resolution... :)

Mike

#14749 - Snake - Mon Jan 12, 2004 9:23 am

Yes, update occurs during vblank when VCOUNT > 160. This is currently updated scanline. The value of this ranges from 0 - 227, 160 to 227 are hidden scanlines.


snake

#14897 - sasq - Wed Jan 14, 2004 3:18 pm

If you can modify your renderer to only render on every other line each frame, you can take advantage of the fact that the GBA screen is interlaced and get "double-buffering" (odd lines is one buffer, even is another) in mode 3 without copying anything.
I haven't tried this myself on GBA but it's been used on other platforms.

#14907 - Miked0801 - Wed Jan 14, 2004 6:31 pm

Interlaced huh? I haven't seen that with my tests. It's an LCD so how can it be? I believe if you render every other line, you'll just get a darker picture and a bit of blurring when it updaets. Someone else care to jump in and shoot one of us down?

#14916 - tepples - Wed Jan 14, 2004 8:00 pm

Like the GBC screen, the GBA screen is pseudo-interlaced to improve its response time. It draws all scanlines in all frames, but in each frame, it draws half the scanlines slightly darker, alternating between darkening odd and even scanlines. Because of this characteristic, fillrate-bound applications will look slightly better if they render at 60fps interlaced than at 30fps progressive. Compare TOD M1, which uses 30fps progressive, to TOD M3, which uses 60fps interlaced, to see what I mean.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#15034 - Maddox - Fri Jan 16, 2004 10:38 am

Okay. Then how does one determine which field should be drawn (even or odd) or if does matter? I.e. is this frame odd-darkening or even darkening?

M!
_________________
You probably suck. I hope you're is not a game programmer.