1 /*---------------------------------------------------------------------------*
2 Project: single field frame buffer demo
3 File: moving.progressive.c
4
5 Copyright 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.progressive.c,v $
14 Revision 1.3 08/10/2006 13:40:14 urata
15 Revised the rendermode of pal progressive.
16
17 Revision 1.2 06/01/2006 12:31:25 urata
18 Added EURGB60 mode.
19
20 Revision 1.1 05/18/2006 09:44:38 urata
21 Initial checkin.
22
23 $NoKeywords: $
24 *---------------------------------------------------------------------------*/
25
26 #include <revolution.h>
27
28 #define NTSC // if you change here, you can see PAL or M/PAL
29
30 #define FLOOR(x, a) ( (x < a)? a : x )
31 #define CEIL(x, b) ( (x > b)? b : x )
32 #define CLAMP(x, a, b) (CEIL(FLOOR(x, a), b))
33
34 #if defined(NTSC)
35
36 GXRenderModeObj* rmode = &GXNtsc480Prog;
37
38 #elif defined(PAL)
39
40 GXRenderModeObj* rmode = &GXEurgb60Hz480Prog;
41
42 #elif defined(EURGB60)
43
44 GXRenderModeObj* rmode = &GXEurgb60Hz480Prog;
45
46 #else
47
48 GXRenderModeObj* rmode = &GXMpal480Prog;
49
50 #endif
51
52 // for X frame buffer
53 static u8* xfbA;
54 static u8* xfbB;
55
56 typedef struct
57 {
58 u32 Y;
59 u32 Cb;
60 u32 Cr;
61
62 } Color_s;
63
64 Color_s color[] = {
65 { 180, 128, 128 },
66 { 162, 44, 142 },
67 { 131, 156, 44 },
68 { 112, 72, 58 },
69 { 84, 184, 198 },
70 { 65, 100, 212 },
71 { 35, 212, 114 },
72 { 16, 128, 128 },
73 };
74
75 void allocateFB(u32 fbSize);
76 void draw(u32 field, u32 code, u32 fbSize, u8* xfb);
77
78 /*---------------------------------------------------------------------------*
79 Name: allocateFB
80
81 Description: Allocates memory for two frame buffers
82
83 Arguments: fbSize each frame buffer size
84
85 Returns: none
86 *---------------------------------------------------------------------------*/
allocateFB(u32 fbSize)87 void allocateFB(u32 fbSize)
88 {
89 void* arenaLo;
90
91 arenaLo = OSGetArenaLo();
92
93 // allocate memory for frame buffer here.
94 xfbA = (u8*)OSRoundUp32B(arenaLo);
95 xfbB = (u8*)OSRoundUp32B(xfbA + fbSize);
96
97 arenaLo = (void*)(xfbA + 2 * fbSize);
98 OSSetArenaLo(arenaLo);
99 }
100
101 /*---------------------------------------------------------------------------*
102 Name: draw
103
104 Description: draw screen
105
106 Arguments: field above field(0) or below(1)
107 count frame count
108 fbSize size of the frame buffer
109 xfb frame buffer address
110
111 Returns: none
112 *---------------------------------------------------------------------------*/
draw(u32 field,u32 count,u32 fbSize,u8 * xfb)113 void draw(u32 field, u32 count, u32 fbSize, u8* xfb)
114 {
115 u32 i, j;
116 u32 colorVal;
117 u32 cb, cr;
118 u32 y;
119 u8* ptr;
120
121 ptr = xfb;
122
123 // if field == above(0), we draw 1, 2, 3, ... n lines.
124 // if field == below(1), we draw 1, 2, 3, ... n lines.
125 // "field" is the same "frame" when the scan-mode is progressive.
126 for (j = field; j < rmode->viHeight; j++)
127 {
128 for (i = 0; i < rmode->fbWidth; i += 2)
129 {
130 // clamping is needed because Cb and Cr should be
131 // in range [16, 240].
132 y = 128;
133 cb = CLAMP( (i + count*2) % 256, 16, 240);
134 cr = CLAMP( (j + count) % 256, 16, 240);
135
136 colorVal = (y << 24)
137 + (cb << 16)
138 + (y << 8)
139 + cr;
140
141 *(u32*)ptr = colorVal;
142
143 // We handle two pixels at a time.
144 ptr += VI_DISPLAY_PIX_SZ * 2;
145 }
146 }
147 DCStoreRange((void*)xfb, fbSize);
148 }
149
150
main(void)151 void main(void)
152 {
153 u32 frame;
154 u32 fbSize;
155 u8* xfb;
156 u32 first;
157
158
159 OSInit();
160 VIInit();
161
162 // Calculate frame buffer size.
163 // Note that each line width should be a multiple of 16.
164 fbSize = (u32)(VIPadFrameBufferWidth(rmode->fbWidth)
165 * rmode->xfbHeight * VI_DISPLAY_PIX_SZ);
166
167 allocateFB(fbSize);
168
169 VIConfigure(rmode);
170
171 // Need to "flush" so that the VI changes so far takes effect
172 // from the following field
173 VIFlush();
174 VIWaitForRetrace();
175
176 // Since the tv mode is interlace after VIInit,
177 // we need to wait for one more frame to make sure
178 // that the mode is switched from interlace to non-interlace.
179 // Progressive-scan is non-interlace.
180 VIWaitForRetrace();
181
182
183 first = 1;
184 frame = 0;
185
186 while(1)
187 {
188 xfb = (frame & 0x1)? xfbB : xfbA;
189
190 draw(VIGetNextField(), frame, fbSize, xfb);
191 VISetNextFrameBuffer( (void*)xfb );
192
193 if (first == 1)
194 {
195 VISetBlack(FALSE);
196 first = 0;
197 }
198
199 VIFlush();
200 VIWaitForRetrace();
201
202 frame++;
203 }
204 }
205