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