1 /*---------------------------------------------------------------------------*
2   Project:  TV mode demo
3   File:     moving.regions.c
4 
5   Copyright 2000-2006 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: moving.regions.c,v $
14   Revision 1.3  2006/09/25 15:57:20  urata
15   Fixed the sequence for setting to Progressive.
16 
17   Revision 1.2  2006/09/25 04:22:49  urata
18   Removed the sequence that Progressive flag is set to OFF.
19 
20   Revision 1.1  2006/09/22 08:38:26  urata
21   Initial checkin.
22 
23   $NoKeywords: $
24  *---------------------------------------------------------------------------*/
25 
26 #include <revolution.h>
27 #include <revolution/sc.h>
28 
29 #define FLOOR(x, a)         ( (x < a)? a : x )
30 #define CEIL(x, b)          ( (x > b)? b : x )
31 #define CLAMP(x, a, b)      (CEIL(FLOOR(x, a), b))
32 
33 GXRenderModeObj* rmode;
34 
35 // for X frame buffer
36 static u8*  xfbA;
37 static u8*  xfbB;
38 
39 typedef struct
40 {
41     u32         Y;
42     u32         Cb;
43     u32         Cr;
44 
45 } Color_s;
46 
47 Color_s color[] = {
48     { 180, 128, 128 },
49     { 162,  44, 142 },
50     { 131, 156,  44 },
51     { 112,  72,  58 },
52     {  84, 184, 198 },
53     {  65, 100, 212 },
54     {  35, 212, 114 },
55     {  16, 128, 128 },
56 };
57 
58 void allocateFB(u32 fbSize);
59 void draw(u32 field, u32 code, u32 fbSize, u8* xfb);
60 
61 
62 /*---------------------------------------------------------------------------*
63     Name:               SetProgressiveMode
64 
65     Description:        Set the video mode to Progressive.
66 
67     Arguments:          none
68 
69     Returns:            none
70  *---------------------------------------------------------------------------*/
SetProgressiveMode(u32 tv)71 static void SetProgressiveMode( u32 tv )
72 {
73     switch(tv)
74     {
75         case VI_PAL:
76         case VI_EURGB60:
77             rmode = &GXEurgb60Hz480Prog;
78             break;
79         default:
80             rmode = &GXNtsc480Prog;
81             break;
82     }
83 
84     VIConfigure(rmode);
85     VIFlush();
86     VIWaitForRetrace();
87     VIWaitForRetrace();
88 }
89 
90 /*---------------------------------------------------------------------------*
91     Name:               SetInterlaceMode
92 
93     Description:        Set the video mode to Interlace.
94 
95     Arguments:          none
96 
97     Returns:            none
98  *---------------------------------------------------------------------------*/
SetInterlaceMode(u32 tv)99 static void SetInterlaceMode( u32 tv )
100 {
101     switch(tv)
102     {
103         case VI_PAL:
104             if( SCGetEuRgb60Mode() == SC_EURGB60_MODE_ON)
105             {
106                 rmode = &GXEurgb60Hz480Int;
107             }
108             else
109             {
110                 rmode = &GXPal528Int;
111             }
112             break;
113         case VI_EURGB60:
114             rmode = &GXEurgb60Hz480Int;
115             break;
116         default:
117             rmode = &GXNtsc480Int;
118             break;
119     }
120 
121     VIConfigure(rmode);
122     VIFlush();
123     VIWaitForRetrace();
124     VIWaitForRetrace();
125 }
126 
127 /*---------------------------------------------------------------------------*
128     Name:               allocateFB
129 
130     Description:        Allocates memory for two frame buffers
131 
132     Arguments:          fbSize      each frame buffer size
133 
134     Returns:            none
135  *---------------------------------------------------------------------------*/
allocateFB(u32 fbSize)136 void allocateFB(u32 fbSize)
137 {
138     void*       arenaLo;
139 
140     arenaLo = OSGetArenaLo();
141 
142     // allocate memory for frame buffer here.
143     xfbA = (u8*)OSRoundUp32B(arenaLo);
144     xfbB = (u8*)OSRoundUp32B(xfbA + fbSize);
145 
146     arenaLo = (void*)(xfbA + 2 * fbSize);
147     OSSetArenaLo(arenaLo);
148 }
149 
150 /*---------------------------------------------------------------------------*
151     Name:               draw
152 
153     Description:        draw screen
154 
155     Arguments:          field       above field(0) or below(1)
156                         count       frame count
157                         fbSize      size of the frame buffer
158                         xfb         frame buffer address
159 
160     Returns:            none
161  *---------------------------------------------------------------------------*/
draw(u32 field,u32 count,u32 fbSize,u8 * xfb)162 void draw(u32 field, u32 count, u32 fbSize, u8* xfb)
163 {
164     u32         i, j;
165     u32         colorVal;
166     u32         cb, cr;
167     u32         y;
168     u8*         ptr;
169 
170     ptr = xfb;
171 
172     // if field == above(0), we draw 1, 2, 3, ... n lines.
173     // if field == below(1), we draw 1, 2, 3, ... n lines.
174     // "field" is the same "frame" when the scan-mode is progressive.
175     for (j = field; j < rmode->viHeight; j++)
176     {
177         for (i = 0; i < rmode->fbWidth; i += 2)
178         {
179             // clamping is needed because Cb and Cr should be
180             // in range [16, 240].
181             y = 128;
182             cb = CLAMP( (i + count*2) % 256, 16, 240);
183             cr = CLAMP( (j + count) % 256, 16, 240);
184 
185             colorVal = (y << 24)
186                 + (cb << 16)
187                 + (y << 8)
188                 + cr;
189 
190             *(u32*)ptr = colorVal;
191 
192             // We handle two pixels at a time.
193             ptr += VI_DISPLAY_PIX_SZ * 2;
194         }
195     }
196     DCStoreRange((void*)xfb, fbSize);
197 }
198 
199 
200 /*---------------------------------------------------------------------------*
201     Name:               main
202 
203     Description:        Main funciton
204 
205     Arguments:          none
206 
207     Returns:            none
208  *---------------------------------------------------------------------------*/
main(void)209 void main(void)
210 {
211     u32         frame;
212     u32         fbSize;
213     u8*         xfb;
214     u32         first;
215     PADStatus   pstat[PAD_MAX_CONTROLLERS];
216     u32         plast=0;
217     u32         tv;
218 
219     OSInit(); // including SCInit
220 
221 
222     // VIGetTvFormat() always reports "NTSC" before VIInit.
223     tv = VIGetTvFormat();
224     OSReport("TV format before VIInit is %s\n", tv == VI_NTSC    ? "NTSC":
225                                                 tv == VI_PAL     ? "PAL" :
226                                                 tv == VI_MPAL    ? "MPAL":
227                                                 tv == VI_EURGB60 ? "EURGB60" : "UNKWON");
228     VIInit();
229     PADInit();
230 
231     // VIGetTvFormat() reports current TV type if VIInit had been executed.
232     tv = VIGetTvFormat();
233     OSReport("TV format after VIInit is %s\n", tv == VI_NTSC    ? "NTSC":
234                                                tv == VI_PAL     ? "PAL" :
235                                                tv == VI_MPAL    ? "MPAL":
236                                                tv == VI_EURGB60 ? "EURGB60" : "UNKWON");
237 
238 
239     // It is the sequence to set a TV type automatically.
240     if((SCGetProgressiveMode() == SC_PROGRESSIVE_MODE_ON) && (1 == VIGetDTVStatus()))
241     {
242         // If Progressive flag is ON and Component cable is connected then..
243         // Set the mode to Progressive.
244         SetProgressiveMode( tv );
245     }
246     else
247     {
248         // Set the mode to Interlace.
249         SetInterlaceMode( tv );
250     }
251 
252     // Calculate frame buffer size.
253     // Note that each line width should be a multiple of 16.
254     fbSize = (u32)(VIPadFrameBufferWidth(rmode->fbWidth)
255         * rmode->xfbHeight * VI_DISPLAY_PIX_SZ);
256 
257     allocateFB(fbSize);
258 
259     first = 1;
260     frame = 0;
261 
262     while(1)
263     {
264         PADRead(pstat);
265         if ((pstat[0].button & PAD_BUTTON_A) && !(plast & PAD_BUTTON_A))
266         {
267             VISetBlack(TRUE);
268             VIFlush();
269             VIWaitForRetrace();
270 
271             // Restart
272             OSRestart(0);
273         }
274 
275 
276         xfb = (frame & 0x1)? xfbB : xfbA;
277         draw(VIGetNextField(), frame, fbSize, xfb);
278         VISetNextFrameBuffer( (void*)xfb );
279 
280         if (first == 1)
281         {
282             VISetBlack(FALSE);
283             first = 0;
284         }
285 
286         VIFlush();
287         VIWaitForRetrace();
288 
289         plast = pstat[0].button;
290         frame++;
291     }
292 }
293