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