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