1 /*---------------------------------------------------------------------------*
2   Project:  single field frame buffer demo
3   File:     moving.progressive.c
4 
5   Copyright 2006 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.progressive.c,v $
14   Revision 1.4  2008/06/26 02:50:52  urata
15   Removed MPAL defines
16 
17   Revision 1.3  2006/08/10 13:40:14  urata
18   Revised the rendermode of pal progressive.
19 
20   Revision 1.2  2006/06/01 12:31:25  urata
21   Added EURGB60 mode.
22 
23   Revision 1.1  2006/05/18 09:44:38  urata
24   Initial check-in.
25 
26   $NoKeywords: $
27  *---------------------------------------------------------------------------*/
28 
29 #include <revolution.h>
30 
31 #define NTSC      // if you change here, you can see PAL
32 
33 #define FLOOR(x, a)         ( (x < a)? a : x )
34 #define CEIL(x, b)          ( (x > b)? b : x )
35 #define CLAMP(x, a, b)      (CEIL(FLOOR(x, a), b))
36 
37 #if defined(NTSC)
38 
39 GXRenderModeObj* rmode = &GXNtsc480Prog;
40 
41 #elif defined(PAL)
42 
43 GXRenderModeObj* rmode = &GXEurgb60Hz480Prog;
44 
45 #elif defined(EURGB60)
46 
47 GXRenderModeObj* rmode = &GXEurgb60Hz480Prog;
48 
49 #endif
50 
51 // for X frame buffer
52 static u8*  xfbA;
53 static u8*  xfbB;
54 
55 typedef struct
56 {
57     u32         Y;
58     u32         Cb;
59     u32         Cr;
60 
61 } Color_s;
62 
63 Color_s color[] = {
64     { 180, 128, 128 },
65     { 162,  44, 142 },
66     { 131, 156,  44 },
67     { 112,  72,  58 },
68     {  84, 184, 198 },
69     {  65, 100, 212 },
70     {  35, 212, 114 },
71     {  16, 128, 128 },
72 };
73 
74 void allocateFB(u32 fbSize);
75 void draw(u32 field, u32 code, u32 fbSize, u8* xfb);
76 
77 /*---------------------------------------------------------------------------*
78     Name:               allocateFB
79 
80     Description:        Allocates memory for two frame buffers
81 
82     Arguments:          fbSize      each frame buffer size
83 
84     Returns:            None.
85  *---------------------------------------------------------------------------*/
allocateFB(u32 fbSize)86 void allocateFB(u32 fbSize)
87 {
88     void*       arenaLo;
89 
90     arenaLo = OSGetArenaLo();
91 
92     // allocate memory for frame buffer here.
93     xfbA = (u8*)OSRoundUp32B(arenaLo);
94     xfbB = (u8*)OSRoundUp32B(xfbA + fbSize);
95 
96     arenaLo = (void*)(xfbA + 2 * fbSize);
97     OSSetArenaLo(arenaLo);
98 }
99 
100 /*---------------------------------------------------------------------------*
101     Name:               Draw
102 
103     Description:        draw screen
104 
105     Arguments:          field       above field(0) or below(1)
106                         count       frame count
107                         fbSize      size of the frame buffer
108                         xfb         frame buffer address
109 
110     Returns:            None.
111  *---------------------------------------------------------------------------*/
draw(u32 field,u32 count,u32 fbSize,u8 * xfb)112 void draw(u32 field, u32 count, u32 fbSize, u8* xfb)
113 {
114     u32         i, j;
115     u32         colorVal;
116     u32         cb, cr;
117     u32         y;
118     u8*         ptr;
119 
120     ptr = xfb;
121 
122     // if field == above(0), we draw 1, 2, 3, ... n lines.
123     // if field == below(1), we draw 1, 2, 3, ... n lines.
124     // "field" is the same "frame" when the scan-mode is progressive.
125     for (j = field; 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*)ptr = colorVal;
141 
142             // We handle two pixels at a time.
143             ptr += VI_DISPLAY_PIX_SZ * 2;
144         }
145     }
146     DCStoreRange((void*)xfb, fbSize);
147 }
148 
149 
main(void)150 void main(void)
151 {
152     u32         frame;
153     u32         fbSize;
154     u8*         xfb;
155     u32         first;
156 
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     // Progressive-scan is non-interlace.
179     VIWaitForRetrace();
180 
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