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.

DS development > Display capture: am I doing it wrong?

#90343 - kvance - Thu Jun 29, 2006 8:10 pm

I'm having trouble using the hardware display capture. I'm trying to render 3D objects into VRAM to use as sprites. My code works, but I have to run it in a loop 3 times and I don't understand why. There are some printfs sprinkled in to watch the DCAP_ENABLE bit. It appears to finish after two iterations, but if I stop there then nothing gets copied to VRAM_A.

I'd appreciate any ideas or suggestions.

Code:
vramSetBankA(VRAM_A_LCD);

for(int i = 0; i < 3; i++) {

        DISP_CAPTURE = DCAP_ENABLE |
                DCAP_MODE(0) |          /* Capture source A */
                DCAP_DST(0) |           /* VRAM write offset 0 */
                DCAP_SRC(1) |           /* 3D screen */
                DCAP_SIZE(3) |          /* 256x192 */
                DCAP_OFFSET(0) |        /* VRAM read offset 0 */
                DCAP_BANK(0) |          /* Write to VRAM A */
                DCAP_A(16) |            /* Blend amount */
                DCAP_B(0);              /* Ignore source B */

        printf("%d0: cap=%d\n", i, (DISP_CAPTURE & DCAP_ENABLE) == DCAP_ENABLE);

        glReset();
        glOrtho(0, 2.56f, 1.92f, 0, -1, 1);

   ... draw draw draw ...

        printf("%d1: cap=%d\n", i, (DISP_CAPTURE & DCAP_ENABLE) == DCAP_ENABLE);

        glFlush();
        printf("%d2: cap=%d\n", i, (DISP_CAPTURE & DCAP_ENABLE) == DCAP_ENABLE);
        swiWaitForVBlank();
        printf("%d3: cap=%d\n", i, (DISP_CAPTURE & DCAP_ENABLE) == DCAP_ENABLE);
}


The console output is:

Code:
00: cap=1
01: cap=1
02: cap=1
03: cap=1
10: cap=1
11: cap=1
12: cap=1
13: cap=0
20: cap=1
21: cap=1
22: cap=1
23: cap=0

_________________
Corner Office: dev LJ
HexxagonDS, dsmzx, more...

#90360 - DekuTree64 - Thu Jun 29, 2006 10:21 pm

Try drawing all your 3D stuff first (including sending the page flip command), then set up the capture and wait for 2 VBlanks. One VBlank because the capture won't start running until the next frame starts drawing, and one to wait for that frame to draw.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#91815 - kvance - Sun Jul 09, 2006 10:53 pm

DekuTree64 wrote:
Try drawing all your 3D stuff first (including sending the page flip command), then set up the capture and wait for 2 VBlanks. One VBlank because the capture won't start running until the next frame starts drawing, and one to wait for that frame to draw.


(Sorry for my long response time. I haven't had much time for my DS project lately.)

I followed your advice, but still no joy. I've boiled it down to the simplest possible function, just capturing a 32x32 white triangle.

Code:
void create_sprites()
{
        /* Render 3D onto VRAM A. */
        videoSetMode(MODE_5_3D);
        vramSetBankA(VRAM_A_LCD);

        glViewPort(0, 0, 255, 191);
        glClearDepth(0x7FFF);
        glReset();

        glOrtho(0, 2.56f, 1.92f, 0, -1, 1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE);
        glColor3f(1.0f, 1.0f, 1.0f);
        glBegin(GL_TRIANGLE);
                glVertex3f( 0.0f,  0.0f, 0.0f);
                glVertex3f( 0.0f, 0.32f, 0.0f);
                glVertex3f(0.32f, 0.32f, 0.0f);
        glEnd();
        glFlush();

        DISP_CAPTURE = DCAP_ENABLE |
                DCAP_MODE(0) |          /* Capture source A */
                DCAP_DST(0) |           /* VRAM write offset 0 */
                DCAP_SRC(1) |           /* 3D screen */
                DCAP_SIZE(3) |          /* 256x192 */
                DCAP_OFFSET(0) |        /* VRAM read offset 0 */
                DCAP_BANK(0) |          /* Write to VRAM A */
                DCAP_A(16) |            /* Blend amount */
                DCAP_B(0);              /* Ignore source B */

        swiWaitForVBlank();
        swiWaitForVBlank();
}


An interesting thing I noticed about my method from the first post is that it only works for a specific number of triangles. 60 tris was fine, but the same routine with 120 tris did nothing. Seems like it was only some race condition that was allowing the capture to take place, and there's something about timing this that I still don't understand.
_________________
Corner Office: dev LJ
HexxagonDS, dsmzx, more...