/*---------------------------------------------------------------------------* Project: single field frame buffer demo File: moving.progressive.c Copyright 2006 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: moving.progressive.c,v $ Revision 1.4 2008/06/26 02:50:52 urata Removed MPAL defines Revision 1.3 2006/08/10 13:40:14 urata Revised the rendermode of pal progressive. Revision 1.2 2006/06/01 12:31:25 urata Added EURGB60 mode. Revision 1.1 2006/05/18 09:44:38 urata Initial check-in. $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #define NTSC // if you change here, you can see PAL #define FLOOR(x, a) ( (x < a)? a : x ) #define CEIL(x, b) ( (x > b)? b : x ) #define CLAMP(x, a, b) (CEIL(FLOOR(x, a), b)) #if defined(NTSC) GXRenderModeObj* rmode = &GXNtsc480Prog; #elif defined(PAL) GXRenderModeObj* rmode = &GXEurgb60Hz480Prog; #elif defined(EURGB60) GXRenderModeObj* rmode = &GXEurgb60Hz480Prog; #endif // for X frame buffer static u8* xfbA; static u8* xfbB; typedef struct { u32 Y; u32 Cb; u32 Cr; } Color_s; Color_s color[] = { { 180, 128, 128 }, { 162, 44, 142 }, { 131, 156, 44 }, { 112, 72, 58 }, { 84, 184, 198 }, { 65, 100, 212 }, { 35, 212, 114 }, { 16, 128, 128 }, }; void allocateFB(u32 fbSize); void draw(u32 field, u32 code, u32 fbSize, u8* xfb); /*---------------------------------------------------------------------------* Name: allocateFB Description: Allocates memory for two frame buffers Arguments: fbSize each frame buffer size Returns: None. *---------------------------------------------------------------------------*/ void allocateFB(u32 fbSize) { void* arenaLo; arenaLo = OSGetArenaLo(); // allocate memory for frame buffer here. xfbA = (u8*)OSRoundUp32B(arenaLo); xfbB = (u8*)OSRoundUp32B(xfbA + fbSize); arenaLo = (void*)(xfbA + 2 * fbSize); OSSetArenaLo(arenaLo); } /*---------------------------------------------------------------------------* Name: Draw Description: draw screen Arguments: field above field(0) or below(1) count frame count fbSize size of the frame buffer xfb frame buffer address Returns: None. *---------------------------------------------------------------------------*/ void draw(u32 field, u32 count, u32 fbSize, u8* xfb) { u32 i, j; u32 colorVal; u32 cb, cr; u32 y; u8* ptr; ptr = xfb; // if field == above(0), we draw 1, 2, 3, ... n lines. // if field == below(1), we draw 1, 2, 3, ... n lines. // "field" is the same "frame" when the scan-mode is progressive. for (j = field; j < rmode->viHeight; j++) { for (i = 0; i < rmode->fbWidth; i += 2) { // clamping is needed because Cb and Cr should be // in range [16, 240]. y = 128; cb = CLAMP( (i + count*2) % 256, 16, 240); cr = CLAMP( (j + count) % 256, 16, 240); colorVal = (y << 24) + (cb << 16) + (y << 8) + cr; *(u32*)ptr = colorVal; // We handle two pixels at a time. ptr += VI_DISPLAY_PIX_SZ * 2; } } DCStoreRange((void*)xfb, fbSize); } void main(void) { u32 frame; u32 fbSize; u8* xfb; u32 first; OSInit(); VIInit(); // Calculate frame buffer size. // Note that each line width should be a multiple of 16. fbSize = (u32)(VIPadFrameBufferWidth(rmode->fbWidth) * rmode->xfbHeight * VI_DISPLAY_PIX_SZ); allocateFB(fbSize); VIConfigure(rmode); // Need to "flush" so that the VI changes so far takes effect // from the following field VIFlush(); VIWaitForRetrace(); // Since the TV mode is interlace after VIInit, // we need to wait for one more frame to make sure // that the mode is switched from interlace to non-interlace. // Progressive-scan is non-interlace. VIWaitForRetrace(); first = 1; frame = 0; while(1) { xfb = (frame & 0x1)? xfbB : xfbA; draw(VIGetNextField(), frame, fbSize, xfb); VISetNextFrameBuffer( (void*)xfb ); if (first == 1) { VISetBlack(FALSE); first = 0; } VIFlush(); VIWaitForRetrace(); frame++; } }