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