1 /*---------------------------------------------------------------------------*
2 Project: single field frame buffer demo
3 File: moving.c
4
5 Copyright 2000 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.30Hz.c,v $
14 Revision 1.2 02/20/2006 04:13:13 mitu
15 changed include path from dolphin/ to revolution/.
16
17 Revision 1.1 12/16/2005 08:34:26 urata
18 Initial check-in.
19
20
21 2 3/01/00 5:41p Hashida
22 Moved NTSC definition from makefile to .c's
23
24 1 2/18/00 10:39a Hashida
25 initial check-in
26
27 $NoKeywords: $
28 *---------------------------------------------------------------------------*/
29
30 #include <revolution.h>
31
32 #define NTSC // if you change here, you can see PAL or M/PAL
33 /* #define NON_INTERLACE */ // if you define this, you can see non-interlace
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 #if defined(NTSC)
40
41 GXRenderModeObj* rmode = &GXNtsc480Int;
42
43 #elif defined(PAL)
44
45 GXRenderModeObj* rmode = &GXPal528Int;
46
47 #else
48
49 GXRenderModeObj* rmode = &GXMpal480Int;
50
51 #endif
52
53 // for X frame buffer
54 static u8* xfbA;
55 static u8* xfbB;
56
57 typedef struct
58 {
59 u32 Y;
60 u32 Cb;
61 u32 Cr;
62
63 } Color_s;
64
65 Color_s color[] = {
66 { 180, 128, 128 },
67 { 162, 44, 142 },
68 { 131, 156, 44 },
69 { 112, 72, 58 },
70 { 84, 184, 198 },
71 { 65, 100, 212 },
72 { 35, 212, 114 },
73 { 16, 128, 128 },
74 };
75
76 void allocateFB(u32 fbSize);
77 void draw(u32 code, u32 fbSize, u8* xfb);
78 void waitFrame(u32 count);
79
80 /*---------------------------------------------------------------------------*
81 Name: allocateFB
82
83 Description: Allocates memory for two frame buffers
84
85 Arguments: fbSize each frame buffer size
86
87 Returns: none
88 *---------------------------------------------------------------------------*/
allocateFB(u32 fbSize)89 void allocateFB(u32 fbSize)
90 {
91 void* arenaLo;
92
93 arenaLo = OSGetArenaLo();
94
95 // allocate memory for frame buffer here.
96 xfbA = (u8*)OSRoundUp32B(arenaLo);
97 xfbB = (u8*)OSRoundUp32B(xfbA + fbSize);
98
99 arenaLo = (void*)(xfbA + 2 * fbSize);
100 OSSetArenaLo(arenaLo);
101 }
102
103 /*---------------------------------------------------------------------------*
104 Name: draw
105
106 Description: draw screen
107
108 Arguments: count frame count
109 fbSize size of the frame buffer
110 xfb frame buffer address
111
112 Returns: none
113 *---------------------------------------------------------------------------*/
draw(u32 count,u32 fbSize,u8 * xfb)114 void draw(u32 count, u32 fbSize, u8* xfb)
115 {
116 u32 i, j;
117 u32 colorVal;
118 u32 cb, cr;
119 u32 y;
120 u8* fbStart;
121
122 count *= 2;
123
124 fbStart = xfb;
125 // draw full image
126 for (j = 0; 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*)xfb = colorVal;
142
143 // We handle two pixels at a time.
144 xfb += VI_DISPLAY_PIX_SZ * 2;
145 }
146 }
147
148 DCStoreRange((void*)fbStart, fbSize);
149 }
150
151 /*---------------------------------------------------------------------------*
152 Name: waitFrame
153
154 Description: wait until the specified retrace count comes.
155 if it's already in or after the frame, just pass.
156
157 Arguments: count frame count
158
159 Returns: none
160 *---------------------------------------------------------------------------*/
waitFrame(u32 count)161 void waitFrame(u32 count)
162 {
163 BOOL enabled;
164
165 enabled = OSDisableInterrupts();
166 while (VIGetRetraceCount() < count)
167 VIWaitForRetrace();
168 OSRestoreInterrupts(enabled);
169 }
170
main(void)171 void main(void)
172 {
173 u32 frame;
174 u32 fbSize;
175 u8* xfb;
176 u32 first;
177 u32 count;
178
179 OSInit();
180 VIInit();
181
182 // Calculate frame buffer size.
183 // Note that each line width should be a multiple of 16.
184 fbSize = (u32)(VIPadFrameBufferWidth(rmode->fbWidth)
185 * rmode->xfbHeight * VI_DISPLAY_PIX_SZ);
186
187 allocateFB(fbSize);
188
189 VIConfigure(rmode);
190
191 // Need to "flush" so that the VI changes so far takes effect
192 // from the following field
193 VIFlush();
194 VIWaitForRetrace();
195
196 // Since the tv mode is interlace after VIInit,
197 // we need to wait for one more frame to make sure
198 // that the mode is switched from interlace to non-interlace
199 #ifdef NON_INTERLACE
200 VIWaitForRetrace();
201 #endif
202
203 count = VIGetRetraceCount();
204 first = 1;
205 frame = 0;
206
207 while(1)
208 {
209 xfb = (frame & 0x1)? xfbB : xfbA;
210
211 draw(frame, fbSize, xfb);
212 VISetNextFrameBuffer((void*)xfb);
213
214 if (first == 1)
215 {
216 VISetBlack(FALSE);
217 first = 0;
218 }
219
220 // wait for some frames in case the rendering finishes too early
221 waitFrame(count + 1);
222
223 VIFlush();
224 VIWaitForRetrace();
225
226 count = VIGetRetraceCount();
227 frame++;
228 }
229 }
230