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 > Trying to display a buffer from main memory

#170377 - DiscoStew - Sun Sep 20, 2009 8:54 am

This is what I have currently...

Code:
int main(void) {

   lcdMainOnTop();

   u16 *mmBuffer = new u16[ 256 * 192 ];
   for( int y = 0; y < 192; y++ )
   {
      for( int x = 0; x < 256; x++ )
      {
         if( y & 0x10 )
            mmBuffer[ x + ( y * 256 ) ] = ( 0x1F << 0 ) | ( 0x00 << 5 ) | ( 0x00 << 10 );
         else
            mmBuffer[ x + ( y * 256 ) ] = ( 0x1F << 0 ) | ( 0x1F << 5 ) | ( 0x00 << 10 );
      }
   }

   videoSetMode( MODE_FIFO );

   while( 1 ) {
      swiWaitForVBlank();

      DMA0_SRC = (u32)mmBuffer;
      DMA0_DEST = REG_DISP_MMEM_FIFO;
      DMA0_CR = DMA_DISP_FIFO | DMA_32_BIT | DMA_ENABLE | 4;
      
   }
}


What this should do is display red and yellow bars across the screen. But that's not the case I'm seeing. On emu, I get a white screen, and on hardware, I get a black screen. Anyone know what I'm doing wrong?

Setup info was taken from GBATek (after the Video Capture section)
_________________
DS - It's all about DiscoStew

#170378 - headspin - Sun Sep 20, 2009 9:27 am

If your in X1B5G5R5 mode bit 15 is a single alpha bit. So you need to OR in BIT(15) or (1 << 15).
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#170381 - DiscoStew - Sun Sep 20, 2009 5:18 pm

There is no alpha bit when using the Main Memory Display, at least that's what it says in GBATek. Nevertheless, I tried it. Nothing changed.
_________________
DS - It's all about DiscoStew

#170384 - headspin - Sun Sep 20, 2009 7:16 pm

Ah yes I see

Quote:
The FIFO can receive 4 words (8 pixels) at a time, each pixel is a 15bit RGB value (the upper bit, bit15, is unused)


I've never played with that video mode so I can't help sorry.
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#170386 - Miked0801 - Sun Sep 20, 2009 7:21 pm

I'll take a look on Monday if no one here has an answer. We've done some video mode capture stuff and I may be able to offer some insight then...

#170388 - DekuTree64 - Sun Sep 20, 2009 9:20 pm

Have you tried different DMA channels? On GBA, only DMA 1 and 2 are wired to be able to trigger by the sound FIFOs. Display FIFO might have a special channel too.

EDIT: Oh, and don't you need to set the dest mode to fixed address since the FIFO is only one register?
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#170391 - DiscoStew - Mon Sep 21, 2009 12:51 am

DekuTree64 wrote:
Have you tried different DMA channels? On GBA, only DMA 1 and 2 are wired to be able to trigger by the sound FIFOs. Display FIFO might have a special channel too.

EDIT: Oh, and don't you need to set the dest mode to fixed address since the FIFO is only one register?


I tried each of the 4 channels, but they all gave me the same result.

As far as the fixed destination address is concerned, I wasn't sure if that was needed, because I had thought that by setting the control to Main Memory Display, it would do that itself. But, it doesn't hurt to try. Unfortunately, it changed nothing.
_________________
DS - It's all about DiscoStew

#170428 - DiscoStew - Wed Sep 23, 2009 5:47 pm

Miked0801 wrote:
I'll take a look on Monday if no one here has an answer. We've done some video mode capture stuff and I may be able to offer some insight then...


Any progress? I've been trying out a couple of different things, including the method described by GBATek of having the Main Memory Display as Source B in capturing, and having the main display showing the contents of a particular VRAM bank (frame buffer mode). Excluding the line for the display capture, the frame buffer shows the content of the vram bank, but once I include that line, it's back to showing nothing. :(

I have a feeling that something is missing in the set up, but I have no idea what it is.
_________________
DS - It's all about DiscoStew

#170429 - sverx - Wed Sep 23, 2009 6:26 pm

DiscoStew wrote:
I have a feeling that something is missing in the set up, but I have no idea what it is.


DMA transfer length? (how many words should be moved...)
http://nocash.emubase.de/gbatek.htm#gbadmatransfers

#170430 - DiscoStew - Wed Sep 23, 2009 10:43 pm

sverx wrote:
DiscoStew wrote:
I have a feeling that something is missing in the set up, but I have no idea what it is.


DMA transfer length? (how many words should be moved...)
http://nocash.emubase.de/gbatek.htm#gbadmatransfers


It says to set it to 4, as that is how many words can fit into the FIFO (8 pixels per go). With that, and setting the mode to Main Memory Display, it is to start when it is requested, and continues to copy in 4 words each time until the screen is refreshed (at scanline 192 if I'm not mistaken).
_________________
DS - It's all about DiscoStew

#170431 - Miked0801 - Wed Sep 23, 2009 11:05 pm

Got nothing for you. The only times we do screen capture stuff, we're using API calls to handle it. Sorry.

#170432 - Cydrak - Wed Sep 23, 2009 11:28 pm

Yeah, this isn't well emulated. I found some old code kicking around that mentions the same whitescreens. Display capture (especially the "background" form of it, which is the apparent purpose of these modes) often gives emulators fits as well. Is that the use you had in mind?

As for the setup, I can't imagine any possible way this could be a single transfer. The FIFO wants 4 words at a time, so surely it must be hand-feeding it throughout the frame? In other words, it sounds a lot like HDMA: you'd want DMA_DST_FIX and DMA_REPEAT. (I suppose the GBA did special-case a few things, but the ARM9 channels look pretty generic to me.)

Okay, see if this works better:
Code:
    swiWaitForVBlank();
     
    DMA0_CR = 0;
    DMA0_SRC = (u32)mmBuffer;
    DMA0_DEST = (u32)&REG_DISP_MMEM_FIFO;
    DMA0_CR = DMA_ENABLE | DMA_DISP_FIFO | DMA_REPEAT | DMA_DST_FIX | DMA_32_BIT | 4;
The repeat will keep it enabled, if my memory serves. You might need to forcibly toggle DMA0_CR to reinitialize the address each frame. Also, check that address--REG_DISP_MMEM_FIFO looks to be an lvalue, not a pointer.

As I said--it's almost certainly hand-feeding the display. This has some implications, and (just possibly) a significant caveat. With 8 pixel transfers, and the 33MHz/6 pixel clock, it's going to kick in every 48 bus cycles. And assuming those lovely 10,2 timings, that would be 16 cycles--or 33% of the bus cycles outside of blanking periods. In theory, anyhow, I never timed it.

If that doesn't give you pause, here's the real gotcha. Consider that when I tried this, libnds was still using the old IPC struct. What do you suppose happens if the ARM7 goes anywhere near the RAM while this DMA is running? :-)

#170433 - DiscoStew - Thu Sep 24, 2009 12:13 am

Cydrak wrote:
Code:
DMA0_DEST = (u32)&REG_DISP_MMEM_FIFO;


That was it! This whole time, I thought the #define was a pointer, but after you mentioned it, I checked it again, and saw that you were right. I made that single change, and while it doesn't seems to work on No$GBA (probably because it isn't emulated), it is indeed working on hardware. Thank you very much. If I remember correctly, iDeas may have this emulated somewhat, so I might as well check with that as well.

An interesting thing I saw after getting it all working is the unusual side-effect if you don't use DMA_REPEAT. As my code above was laid out so that there are horizontal strips of yellow and red, if DMA_REPEAT isn't used, then what ends up showing are thinner "vertical" strips of yellow and red. Then, I tested with 4 different color strips to see what would happen, and it ended up doing the same thing, but only the 1st and 4th colors were showing up. It was fun to see nonetheless.
_________________
DS - It's all about DiscoStew

#170436 - headspin - Thu Sep 24, 2009 8:45 pm

Cearn's DMA article might be of interest to you

http://www.coranac.com/tonc/text/dma.htm
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#170465 - hacker013 - Mon Sep 28, 2009 8:16 pm

I tryed to use that code for a project of me but instead of a u16 pointer to de main memory I have a u8 pointer to the main memory but it shows only a black screen :( Does somebody know what i'm doing wrong? I already tried various things but they didn't work.
_________________
Website / Blog

Let the nds be with you.

#170470 - DiscoStew - Mon Sep 28, 2009 10:24 pm

Are you using the code I displayed, but mixed with the adjustments Cydrak pointed out? What about the alignment of the u8 pointer? Maybe it doesn't do anything if the source address isn't properly aligned.
_________________
DS - It's all about DiscoStew

#170489 - hacker013 - Tue Sep 29, 2009 3:25 pm

Alignment is correvy I think because if I set it to VRAM_A it just shows but if I want it to show your way it just give me a black screen. And I use Cydrak corrections ;)
_________________
Website / Blog

Let the nds be with you.