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.3  08/10/2006 13:40:14  urata
15   Revised the rendermode of pal progressive.
16 
17   Revision 1.2  06/01/2006 12:31:25  urata
18   Added EURGB60 mode.
19 
20   Revision 1.1  05/18/2006 09:44:38  urata
21   Initial checkin.
22 
23   $NoKeywords: $
24  *---------------------------------------------------------------------------*/
25 
26 #include <revolution.h>
27 
28 #define NTSC      // if you change here, you can see PAL or M/PAL
29 
30 #define FLOOR(x, a)         ( (x < a)? a : x )
31 #define CEIL(x, b)          ( (x > b)? b : x )
32 #define CLAMP(x, a, b)      (CEIL(FLOOR(x, a), b))
33 
34 #if defined(NTSC)
35 
36 GXRenderModeObj* rmode = &GXNtsc480Prog;
37 
38 #elif defined(PAL)
39 
40 GXRenderModeObj* rmode = &GXEurgb60Hz480Prog;
41 
42 #elif defined(EURGB60)
43 
44 GXRenderModeObj* rmode = &GXEurgb60Hz480Prog;
45 
46 #else
47 
48 GXRenderModeObj* rmode = &GXMpal480Prog;
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 1, 2, 3, ... n lines.
124     // if field == below(1), we draw 1, 2, 3, ... n lines.
125     // "field" is the same "frame" when the scan-mode is progressive.
126     for (j = field; 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*)ptr = colorVal;
142 
143             // We handle two pixels at a time.
144             ptr += VI_DISPLAY_PIX_SZ * 2;
145         }
146     }
147     DCStoreRange((void*)xfb, fbSize);
148 }
149 
150 
main(void)151 void main(void)
152 {
153     u32         frame;
154     u32         fbSize;
155     u8*         xfb;
156     u32         first;
157 
158 
159     OSInit();
160     VIInit();
161 
162     // Calculate frame buffer size.
163     // Note that each line width should be a multiple of 16.
164     fbSize = (u32)(VIPadFrameBufferWidth(rmode->fbWidth)
165         * rmode->xfbHeight * VI_DISPLAY_PIX_SZ);
166 
167     allocateFB(fbSize);
168 
169     VIConfigure(rmode);
170 
171     // Need to "flush" so that the VI changes so far takes effect
172     // from the following field
173     VIFlush();
174     VIWaitForRetrace();
175 
176     // Since the tv mode is interlace after VIInit,
177     // we need to wait for one more frame to make sure
178     // that the mode is switched from interlace to non-interlace.
179     // Progressive-scan is non-interlace.
180     VIWaitForRetrace();
181 
182 
183     first = 1;
184     frame = 0;
185 
186     while(1)
187     {
188         xfb = (frame & 0x1)? xfbB : xfbA;
189 
190         draw(VIGetNextField(), frame, fbSize, xfb);
191         VISetNextFrameBuffer( (void*)xfb );
192 
193         if (first == 1)
194         {
195             VISetBlack(FALSE);
196             first = 0;
197         }
198 
199         VIFlush();
200         VIWaitForRetrace();
201 
202         frame++;
203     }
204 }
205