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 > Windowing constants not in libnds?

#162725 - gauauu - Thu Sep 11, 2008 4:01 am

Am I missing something, or is there a reason that the bit values for the various items for windows aren't in libnds?

The registers for windows are (WIN_IN, WIN_OUT, etc), but no constants are defined for writing to those registers.

For example, for blending, BLEND_SRC_BG0, BLEND_SRC_BG1, etc, are defined. But, unless I'm missing them, there's no constants to make writing to the windowing registers easier.

Not a big deal, as it's pretty easy to write the correct bits based on the specs, but it seems like this was omitted where other similar constants were defined.

Thoughts?

#162745 - dovoto - Thu Sep 11, 2008 9:47 pm

I will take a look at this for the next release. It will probably be wrapped in an accessor but I will add register definitions for those that prefer to set registers directly.

If you have allready created some and they make sense feel free to post them here and I will look at getting them into the next release.
_________________
www.drunkencoders.com

#162747 - gauauu - Thu Sep 11, 2008 10:13 pm

dovoto wrote:
If you have allready created some and they make sense feel free to post them here and I will look at getting them into the next release.


I've been using accessors also:

Code:

#define WIN_BG0    (1<<0)
#define WIN_BG1    (1<<1)
#define WIN_BG2    (1<<2)
#define WIN_BG3    (1<<3)
#define WIN_OBJ    (1<<4)
#define WIN_BLEND  (1<<5)

void setWinObjItems(uint8 items)
{
   WIN_OUT = (WIN_OUT & 0x003F) | (items << 8);
}

void setWinOutItems(uint8 items)
{
   WIN_OUT = (WIN_OUT & 0x3F00) | (items);
}

void setWin0Items(uint8 items)
{
   WIN_IN = (WIN_IN & 0x3F00) | (items);
}

void setWin1Items(uint8 items)
{
   WIN_IN = (WIN_IN & 0x003F) | (items << 8);
}


(Although I'm not sure that my term "items" is the best term for it)

You could go farther and define pre-bitshifted versions of everything, but it seems a bit too cluttered and verbose to me:
Code:

#define WIN0_BG0    WIN_BG0
#define WIN0_BG1    WIN_BG1
#define WIN0_BG2    WIN_BG2
#define WIN0_BG3    WIN_BG3
#define WIN0_OBJ    WIN_OBJ
#define WIN0_BLEND  WIN_BLEND

#define WIN1_BG0    (WIN_BG0 << 8)
#define WIN1_BG1    (WIN_BG1 << 8)
#define WIN1_BG2    (WIN_BG2 << 8)
#define WIN1_BG3    (WIN_BG3 << 8)
#define WIN1_OBJ    (WIN_OBJ << 8)
#define WIN1_BLEND  (WIN_BLEND << 8)

//...etc

#162753 - tepples - Fri Sep 12, 2008 12:02 pm

dovoto wrote:
I will take a look at this for the next release. It will probably be wrapped in an accessor but I will add register definitions for those that prefer to set registers directly.

You're right. Accessors are nice, but exclusively using accessors doesn't work too well for defining the shape or content of a window with HDMA.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#162759 - Cearn - Fri Sep 12, 2008 2:59 pm

You don't really need pre-shifted bits if the windowing registers are mapped to bytes instead of halfwords.

Code:
//! \name Windowing registers in bytes
//\{
#define REG_WIN0R           *(vu8*)(0x04000040)     //!< Win 0 right
#define REG_WIN0L           *(vu8*)(0x04000041)     //!< Win 0 left
#define REG_WIN1R           *(vu8*)(0x04000042)     //!< Win 1 right
#define REG_WIN1L           *(vu8*)(0x04000043)     //!< Win 1 left

#define REG_WIN0B           *(vu8*)(0x04000044)     //!< Win 0 bottom
#define REG_WIN0T           *(vu8*)(0x04000045)     //!< Win 0 top
#define REG_WIN1B           *(vu8*)(0x04000046)     //!< Win 1 bottom
#define REG_WIN1T           *(vu8*)(0x04000047)     //!< Win 1 top

#define REG_WIN0CNT         *(vu8*)(0x04000048)     //!< Window 0 control
#define REG_WIN1CNT         *(vu8*)(0x04000049)     //!< Window 1 control
#define REG_WINOUTCNT       *(vu8*)(0x0400004A)     //!< Out window control
#define REG_WINOBJCNT       *(vu8*)(0x0400004B)     //!< Obj window control
//\}

//! \name Window control bits
//\{
#define WIN_ALL            (31<< 0)     //<! All layers in window
#define WIN_BG0            ( 1<< 0)     //<! Windowed bg 0
#define WIN_BG1            ( 1<< 1)     //<! Windowed bg 1
#define WIN_BG2            ( 1<< 2)     //<! Windowed bg 2
#define WIN_BG3            ( 1<< 3)     //<! Windowed bg 3
#define WIN_OBJ            ( 1<< 4)     //<! Windowed objects
#define WIN_BLEND          ( 1<< 5)     //<! Windowed blending
//\}


//! Set Window 0 mode.
static inline void win0SetMode(u32 mode)
{
    REG_WIN0CNT= mode;
}

etc


You can also map the control registers to a byte array and use control everything through a single function.

Code:
#define REG_WINCNT      ((vu8*)(0x04000048))    //!< Window control registers

enum WinType {  WINID_0= 0, WINID_1, WINID_OUT, WINID_OBJ   };

static inline void winSetMode(u32 id, u32 mode)
{
    REG_WINCNT[id]= mode;
}

#162760 - gauauu - Fri Sep 12, 2008 3:19 pm

Cearn wrote:
You don't really need pre-shifted bits if the windowing registers are mapped to bytes instead of halfwords.


True. Right now, in libnds, the window position registers are mapped to bytes, but the window control registers are mapped to halfwords. (Not that this couldn't change, but that's why my brain was going from that direction)

#162769 - a128 - Fri Sep 12, 2008 5:10 pm

great..but I was never able to get those window stuff working..any examples?

#162771 - gauauu - Fri Sep 12, 2008 5:31 pm

a128 wrote:
great..but I was never able to get those window stuff working..any examples?


Check out Tonc's information about it. Libnds uses different names for the registers, but other than that, the GBA handling of windows is almost identical to the DS.

There is this glitch, though, mentioned in gbatek:
Quote:

DS Window Glitches
The DS counts scanlines in range 0..262 (0..106h), of which only the lower 8bit are compared with the WIN0V/WIN1V register settings. Respectively, Y1 coordinates 00h..06h will be triggered in scanlines 100h-106h by mistake. That means, the window gets activated within VBlank period, and will be active in scanline 0 and up (that is no problem with Y1=0, but Y1=1..6 will appear as if if Y1 would be 0). Workaround would be to disable the Window during VBlank, or to change Y1 during VBlank (to a value that does not occur during VBlank period, ie. 7..191).
Also, there's a problem to fit the 256 pixel horizontal screen resolution into 8bit values: X1=00h is treated as 0 (left-most), X2=00h is treated as 100h (right-most). However, the window is not displayed if X1=X2=00h; the window width can be max 255 pixels.


For more examples, Cearn posted some code of how to use hblank dma to make a cool circular window effect in this thread. Again, GBA code, but should help.

Also, I've got some simple windowing code from the DS port of Anguna I'm working on that I could share with you if you are interested (a black screen other than a small window specified by absolute coordinates, and another small window from a sprite mask). Not going to waste the space posting it here, but if you're still stuck, send me a message, and I can send you relevant code.