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 > Simple loop, strange behaviour

#148296 - nipil - Fri Jan 04, 2008 1:56 pm

I'm back with something strange. Here's the actual code sample :
Code:
#include <nds.h>
#include <stdio.h>

int main(void) {
   u8 a,i;

   videoSetMode(0);
   videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
   vramSetBankC(VRAM_C_SUB_BG);
   SUB_BG0_CR = BG_MAP_BASE(31);
   BG_PALETTE_SUB[255] = RGB15(31,31,31);
   consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);

   u8 * tileMemory = (u8*)BG_TILE_RAM(1);
   for (i = 0; i < 64; i++) {
      tileMemory[i] = 6;
      printf("%i ",tileMemory[i]);
   }
   for (a = 0; a < 64; a++) {
      printf("%i ", tileMemory[a]);
   }

   return 0;
}
As you can see, the code is a *very* simple modification to the arm9 template: Basically, filling an 8x8 tile with "6" and double checking if it's correctly written.

Output from no$gba :
[Images not permitted - Click here to view it]

Output from other emulators :
[Images not permitted - Click here to view it]

Questions are :
- has this anything to do some "volatile" memory ?
- relating to the point above :
* is it a normal behaviour correctly implemented in no$gba (and as such something wrongly done on others)
* OR is it a bug in no$gba (which i should maybe report) ?
- If i'm doing it wrong, how should i do it ?

I'm asking this here, because i don't like having different results for something so simple (code-wise).

#148298 - Lick - Fri Jan 04, 2008 2:40 pm

Don't write to the VRAM in bytes (u8). Use shorts (u16) or longs (u32). Also, use BG_TILE_RAM_SUB for the subscreen.
_________________
http://licklick.wordpress.com

#148299 - nipil - Fri Jan 04, 2008 2:42 pm

Fiddling with this, i made the following discovery :

- if i write directly to the (u8*)BG_TILE_RAM(1), "6" is reset to "0"
- if i write the "6" to a temp buffer, and then copy it to memory using swiCopy, they is no reset

For info, I turned "main" display on & off (is turned on below), no change.
Now, with the swiCopy, i have a normal & consistant behaviour.
So... What's the big difference between the 2 methods ?

The actual code is now :
Code:
#include <nds.h>
#include <stdio.h>

int main(void) {
   u8 a,i;

   videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE);
   vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
   BG0_CR = BG_32x32 | BG_COLOR_256 | BG_MAP_BASE(0) | BG_TILE_BASE(1);
   
   videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
   vramSetBankC(VRAM_C_SUB_BG);
   SUB_BG0_CR = BG_MAP_BASE(31);
   BG_PALETTE_SUB[255] = RGB15(31,31,31);
   consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);

   u8 temp[64];
   u8 * tileMemory = (u8*)BG_TILE_RAM(1);
   for (i = 0; i < 64; i++) { temp[i] = 6; }
   for (a = 0; a < 64; a++) { iprintf("%i ", temp[a]); }
   swiCopy(temp, tileMemory, 32);
   for (a = 0; a < 64; a++) { iprintf("%i ", tileMemory[a]); }
   return 0;
}
I tend to think this might be a bug in no$gba... though i read it was quite reliable.

#148304 - nipil - Fri Jan 04, 2008 2:56 pm

Lick wrote:
Don't write to the VRAM in bytes (u8). Use shorts (u16) or longs (u32).

Argh, i wasn't aware of the 16/32 bits write. And now it works without swiCopy :
Code:
   u16 * tileMemory = (u16*)BG_TILE_RAM(1);
   for (i = 0; i < 32; i++) {
      tileMemory[i] = 0x0606;
      printf("%04x ",tileMemory[i]);
   }
   for (a = 0; a < 32; a++) {
      printf("%04x ", tileMemory[a]);
   }

So, this means i cannot write to the VRAM in 8-bit mode ? (so 16bit writes for sprites, tiles, maps, framebuffer and so on ?)

Lick wrote:
Also, use BG_TILE_RAM_SUB for the subscreen.

The tiles i'm writing in are to be displayed on the "main" screen (display "above" and "debug" on sub) that's why i chose BG_TILE_RAM. Should i change ?

#148305 - Peter - Fri Jan 04, 2008 3:01 pm

nipilSo wrote:
this means i cannot write to the VRAM in 8-bit mode ? (so 16bit writes for sprites, tiles, maps, framebuffer and so on ?)

From GBATek:
GBATek wrote:

All VRAM (and Palette, and OAM) can be written to only in 16bit and 32bit units (STRH, STR opcodes), 8bit writes are ignored (by STRB opcode). The only exception is "Plain <ARM7>-CPU Access" mode: The ARM7 CPU can use STRB to write to VRAM (the reason for this special feature is that, in GBA mode, two 128K VRAM blocks are used to emulate the GBA's 256K Work RAM).


See GBATek chapter DS Memory Control - VRAM for more information.
_________________
Kind Regards,
Peter

#148369 - Lick - Sat Jan 05, 2008 1:50 am

Nipil, in your first paste, you did not use the main screen. In your second paste, you do use it.

So disregard my suggestion, but remember that there's a BG_..._RAM() and a BG_..._RAM_SUB(). However, with bases there is only BG_..._BASE and no BG_..._BASE_SUB.
_________________
http://licklick.wordpress.com

#148450 - nipil - Sat Jan 05, 2008 10:14 pm

So in file video.h i read :

323 #define BG_TILE_BASE(base) ((base) << 2)
324 #define BG_MAP_BASE(base) ((base) << 8)
325 #define BG_BMP_BASE(base) ((base) << 8)

This means i use the same BG_*_BASE for both main and sub.

Got it, thanks !