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