/*---------------------------------------------------------------------------* Project: TV mode demo File: moving.regions.c Copyright 2000-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.regions.c,v $ Revision 1.5 2008/06/26 02:50:15 urata Removed MPAL defines Revision 1.4 2008/06/10 12:23:58 urata Modified Progressive sequence with VIGetScanMode(). Revision 1.3 2006/09/25 15:57:20 urata Fixed the sequence for setting to Progressive. Revision 1.2 2006/09/25 04:22:49 urata Removed the sequence that Progressive flag is set to OFF. Revision 1.1 2006/09/22 08:38:26 urata Initial check-in. $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #include #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)) GXRenderModeObj* rmode; // 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: SetProgressiveMode Description: Set the video mode to Progressive. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ static void SetProgressiveMode( u32 tv ) { switch(tv) { case VI_PAL: case VI_EURGB60: rmode = &GXEurgb60Hz480Prog; break; default: rmode = &GXNtsc480Prog; break; } VIConfigure(rmode); VIFlush(); VIWaitForRetrace(); VIWaitForRetrace(); } /*---------------------------------------------------------------------------* Name: SetInterlaceMode Description: Set the video mode to Interlace. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ static void SetInterlaceMode( u32 tv ) { switch(tv) { case VI_PAL: if( SCGetEuRgb60Mode() == SC_EURGB60_MODE_ON) { rmode = &GXEurgb60Hz480Int; } else { rmode = &GXPal528Int; } break; case VI_EURGB60: rmode = &GXEurgb60Hz480Int; break; default: rmode = &GXNtsc480Int; break; } VIConfigure(rmode); VIFlush(); VIWaitForRetrace(); VIWaitForRetrace(); } /*---------------------------------------------------------------------------* 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); } /*---------------------------------------------------------------------------* Name: Main Description: Main function Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void main(void) { u32 frame; u32 fbSize; u8* xfb; u32 first; PADStatus pstat[PAD_MAX_CONTROLLERS]; u32 plast=0; u32 tv; OSInit(); // including SCInit // VIGetTvFormat() always reports "NTSC" before VIInit. tv = VIGetTvFormat(); OSReport("TV format before VIInit is %s\n", tv == VI_NTSC ? "NTSC": tv == VI_PAL ? "PAL" : tv == VI_EURGB60 ? "EURGB60" : "UNKWON"); VIInit(); PADInit(); // VIGetTvFormat() reports current TV type if VIInit had been executed. tv = VIGetTvFormat(); OSReport("TV format after VIInit is %s\n", tv == VI_NTSC ? "NTSC": tv == VI_PAL ? "PAL" : tv == VI_EURGB60 ? "EURGB60" : "UNKWON"); // It is the sequence to set a TV type automatically. if(VIGetScanMode() == VI_PROGRESSIVE) { // Set the mode to Progressive. SetProgressiveMode( tv ); } else { // Set the mode to Interlace. SetInterlaceMode( tv ); } // 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); first = 1; frame = 0; while(1) { PADRead(pstat); if ((pstat[0].button & PAD_BUTTON_A) && !(plast & PAD_BUTTON_A)) { VISetBlack(TRUE); VIFlush(); VIWaitForRetrace(); // Restart OSRestart(0); } xfb = (frame & 0x1)? xfbB : xfbA; draw(VIGetNextField(), frame, fbSize, xfb); VISetNextFrameBuffer( (void*)xfb ); if (first == 1) { VISetBlack(FALSE); first = 0; } VIFlush(); VIWaitForRetrace(); plast = pstat[0].button; frame++; } }