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