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.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:25  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 = &GXNtsc240Int;
42 
43 #elif defined(PAL)
44 
45 GXRenderModeObj* rmode = &GXPal264Int;
46 
47 #else
48 
49 GXRenderModeObj* rmode = &GXMpal240Int;
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 field, u32 code, u32 fbSize, u8* xfb);
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:          field       above field(0) or below(1)
108                         count       frame count
109                         fbSize      size of the frame buffer
110                         xfb         frame buffer address
111 
112     Returns:            none
113  *---------------------------------------------------------------------------*/
draw(u32 field,u32 count,u32 fbSize,u8 * xfb)114 void draw(u32 field, u32 count, u32 fbSize, u8* xfb)
115 {
116     u32         i, j;
117     u32         colorVal;
118     u32         cb, cr;
119     u32         y;
120     u8*         ptr;
121 
122     ptr = xfb;
123 
124     // if field == above(0), we draw 0, 2, 4, ... 2n lines.
125     // if field == below(1), we draw 1, 3, 5, ... (2n-1) lines.
126     for (j = field; j < rmode->viHeight; j += 2)
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*)ptr = colorVal;
142 
143             // We handle two pixels at a time.
144             ptr += VI_DISPLAY_PIX_SZ * 2;
145         }
146     }
147 
148     DCStoreRange((void*)xfb, fbSize);
149 }
150 
main(void)151 void main(void)
152 {
153     u32         frame;
154     u32         fbSize;
155     u8*         xfb;
156     u32         first;
157 
158     OSInit();
159     VIInit();
160 
161     // Calculate frame buffer size.
162     // Note that each line width should be a multiple of 16.
163     fbSize = (u32)(VIPadFrameBufferWidth(rmode->fbWidth)
164         * rmode->xfbHeight * VI_DISPLAY_PIX_SZ);
165 
166     allocateFB(fbSize);
167 
168     VIConfigure(rmode);
169 
170     // Need to "flush" so that the VI changes so far takes effect
171     // from the following field
172     VIFlush();
173     VIWaitForRetrace();
174 
175     // Since the tv mode is interlace after VIInit,
176     // we need to wait for one more frame to make sure
177     // that the mode is switched from interlace to non-interlace
178 #ifdef NON_INTERLACE
179     VIWaitForRetrace();
180 #endif
181 
182     first = 1;
183     frame = 0;
184 
185     while(1)
186     {
187         xfb = (frame & 0x1)? xfbB : xfbA;
188 
189         draw(VIGetNextField(), frame, fbSize, xfb);
190         VISetNextFrameBuffer( (void*)xfb );
191 
192         if (first == 1)
193         {
194             VISetBlack(FALSE);
195             first = 0;
196         }
197 
198         VIFlush();
199         VIWaitForRetrace();
200 
201         frame++;
202     }
203 }
204