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