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.c,v $
14   Revision 1.3  2008/06/26 02:51:26  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:25  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 = &GXNtsc240Int;
45 
46 #elif defined(PAL)
47 
48 GXRenderModeObj* rmode = &GXPal264Int;
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 field, u32 code, u32 fbSize, u8* xfb);
77 
78 /*---------------------------------------------------------------------------*
79     Name:               allocateFB
80 
81     Description:        Allocates memory for two frame buffers
82 
83     Arguments:          fbSize      each frame buffer size
84 
85     Returns:            None.
86  *---------------------------------------------------------------------------*/
allocateFB(u32 fbSize)87 void allocateFB(u32 fbSize)
88 {
89     void*       arenaLo;
90 
91     arenaLo = OSGetArenaLo();
92 
93     // allocate memory for frame buffer here.
94     xfbA = (u8*)OSRoundUp32B(arenaLo);
95     xfbB = (u8*)OSRoundUp32B(xfbA + fbSize);
96 
97     arenaLo = (void*)(xfbA + 2 * fbSize);
98     OSSetArenaLo(arenaLo);
99 }
100 
101 /*---------------------------------------------------------------------------*
102     Name:               Draw
103 
104     Description:        draw screen
105 
106     Arguments:          field       above field(0) or below(1)
107                         count       frame count
108                         fbSize      size of the frame buffer
109                         xfb         frame buffer address
110 
111     Returns:            None.
112  *---------------------------------------------------------------------------*/
draw(u32 field,u32 count,u32 fbSize,u8 * xfb)113 void draw(u32 field, u32 count, u32 fbSize, u8* xfb)
114 {
115     u32         i, j;
116     u32         colorVal;
117     u32         cb, cr;
118     u32         y;
119     u8*         ptr;
120 
121     ptr = xfb;
122 
123     // if field == above(0), we draw 0, 2, 4, ... 2n lines.
124     // if field == below(1), we draw 1, 3, 5, ... (2n-1) lines.
125     for (j = field; j < rmode->viHeight; j += 2)
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 
147     DCStoreRange((void*)xfb, fbSize);
148 }
149 
main(void)150 void main(void)
151 {
152     u32         frame;
153     u32         fbSize;
154     u8*         xfb;
155     u32         first;
156 
157     OSInit();
158     VIInit();
159 
160     // Calculate frame buffer size.
161     // Note that each line width should be a multiple of 16.
162     fbSize = (u32)(VIPadFrameBufferWidth(rmode->fbWidth)
163         * rmode->xfbHeight * VI_DISPLAY_PIX_SZ);
164 
165     allocateFB(fbSize);
166 
167     VIConfigure(rmode);
168 
169     // Need to "flush" so that the VI changes so far takes effect
170     // from the following field
171     VIFlush();
172     VIWaitForRetrace();
173 
174     // Since the TV mode is interlace after VIInit,
175     // we need to wait for one more frame to make sure
176     // that the mode is switched from interlace to non-interlace
177 #ifdef NON_INTERLACE
178     VIWaitForRetrace();
179 #endif
180 
181     first = 1;
182     frame = 0;
183 
184     while(1)
185     {
186         xfb = (frame & 0x1)? xfbB : xfbA;
187 
188         draw(VIGetNextField(), frame, fbSize, xfb);
189         VISetNextFrameBuffer( (void*)xfb );
190 
191         if (first == 1)
192         {
193             VISetBlack(FALSE);
194             first = 0;
195         }
196 
197         VIFlush();
198         VIWaitForRetrace();
199 
200         frame++;
201     }
202 }
203