1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     gx_CaptureUtil.cpp
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  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   $Rev: 46365 $
14  *---------------------------------------------------------------------------*/
15 
16 
17 #include <nn.h>
18 
19 /*
20     Decompose the perspective projection matrix. Assume input from the matrix generated by CTR-SDK MATH.
21  */
GetProjectionParameters(nn::math::Matrix44 * proj,f32 * left,f32 * right,f32 * bottom,f32 * top,f32 * near,f32 * far)22 void GetProjectionParameters( nn::math::Matrix44* proj, f32* left, f32* right,
23                               f32* bottom, f32* top, f32* near, f32* far)
24 {
25     // Reverse calculate, assuming that the perspective projection matrix that was input takes CTR clip coordinates into account.
26     *near   = proj->m[2][3] / proj->m[2][2];
27     *far    = proj->m[2][3] / (proj->m[2][2] - 1.0f);
28 
29     f32 tmp = proj->m[2][3] / (proj->m[0][0] * proj->m[2][2]);
30     *left   = tmp * (proj->m[0][2] - 1.0f);
31     *right  = tmp * (proj->m[0][2] + 1.0f);
32 
33     tmp     = proj->m[2][3] / (proj->m[1][1] * proj->m[2][2]);
34     *top    = tmp * (proj->m[1][2] + 1.0f);
35     *bottom = tmp * (proj->m[1][2] - 1.0f);
36 }
37 
38 /* Please see man pages for details
39 
40 
41 
42 
43 */
GetProjectionForPartialCapture(nn::math::Matrix44 * pOut,nn::math::Matrix44 * proj,s32 div,s32 indexV,s32 indexH,const f32 dist,nn::math::PivotDirection pivot)44 void GetProjectionForPartialCapture(nn::math::Matrix44* pOut, nn::math::Matrix44* proj,
45                                     s32 div, s32 indexV, s32 indexH, const f32 dist, nn::math::PivotDirection pivot)
46 {
47     (void)dist;
48     NN_NULL_ASSERT(pOut);
49     NN_NULL_ASSERT(proj);
50     NN_ASSERT( 0 <= indexV || 0 <= indexH || indexV < div || indexH < div);
51     NN_ASSERT( nn::math::PIVOT_NONE <= pivot || pivot <= nn::math::PIVOT_NUM );
52 
53     const f32 divH = static_cast<f32>(div);
54     const f32 divV = static_cast<f32>(div);
55 
56     // Reverse-calculate the arguments from the perspective projection matrix that was input. Calculate and return the projection matrix used to display the specified magnification and index position on the full screen.
57     //
58     f32 near, far, top, bottom, left, right;
59 
60     GetProjectionParameters( proj, &left, &right, &bottom, &top, &near, &far);
61 
62     // Find the arguments for the specified division
63     f32 partLeft, partRight, partTop, partBottom;
64 
65     partLeft   = (static_cast<f32>(indexH)/divH * right + (divH - static_cast<f32>(indexH))/divH * left);
66     partRight  = (static_cast<f32>(indexH + 1)/divH * right + (divH - static_cast<f32>(indexH + 1))/divH * left);
67     partTop    = (static_cast<f32>(indexV)/divV * bottom + (divV - static_cast<f32>(indexV))/divV * top);
68     partBottom = (static_cast<f32>(indexV + 1)/divV * bottom + (divV - static_cast<f32>(indexV + 1))/divV * top);
69 
70 //    NN_SLOG_("calc: left:%lf, right:%lf, bottom:%lf, top:%lf, near:%lf, far:%lf\n", partLeft, partRight, partBottom, partTop, near, far);
71 
72     nn::math::MTX44FrustumPivot(pOut, partLeft, partRight, partBottom, partTop, near, far, pivot);
73 }
74 
75 /* Please see man pages for details
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
98 
99 
100 
101 
102 */
SaveDisplayBufferSD(const wchar_t * dirname,const wchar_t * filename,u32 index,GLuint addr,const u32 width,const u32 height,u8 * work=NULL)103 int SaveDisplayBufferSD(const wchar_t *dirname, const wchar_t *filename, u32 index,
104                         GLuint addr, const u32 width, const u32 height, u8 *work = NULL)
105 {
106     static wchar_t *sdname = L"sdmc:/";
107     static wchar_t *exname = L".bmp";
108 
109     // BMP Header
110     static u8 bh[54]={
111         0x42,0x4D,0x04,0x03,0x02,0x00,0x00,0x00,
112         0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
113         0x00,0x00,0x80,0x02,0x00,0x00,0xE0,0x01,
114         0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,
115         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
116         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
117         0x00,0x00,0x00,0x00,0x00,0x00
118     };
119 
120     NN_NULL_ASSERT( dirname );
121     NN_NULL_ASSERT( filename );
122     NN_ASSERT( 0 < width || width <= nn::gx::DISPLAY0_WIDTH );
123     NN_ASSERT( 0 < height || height <= nn::gx::DISPLAY0_HEIGHT);
124 
125     u8 linebuf[nn::gx::DISPLAY0_HEIGHT * 3];
126     u8 *data;
127     int i, j;
128     nn::Result result;
129 
130     // Check whether SD Card is being used
131     for (i = 0; i < 6; ++i)
132     {
133         if (dirname[i] != sdname[i])
134             return(-1);
135     }
136 
137     // Checks whether a directory was specified. If so, try to create directory.
138     if (dirname[i])
139     {
140         result = nn::fs::TryCreateDirectory(dirname);
141     }
142 
143     // Create a file path
144     wchar_t *path;
145 
146     path = reinterpret_cast<wchar_t*>(linebuf);
147     for (i = 0; i < 245; ++i)
148     {
149         if (dirname[i] == 0)
150             break;
151         path[i] = dirname[i];
152     }
153     if (path[i-1] != '/')
154     {
155         path[i++] = '/';
156     }
157     for (j = 0; i < 246; i++, j++)
158     {
159         if (filename[j] == 0 )
160             break;
161         path[i] = filename[j];
162     }
163 
164     path[i  ] = (index/10000) + 48; index %= 10000;
165     path[i+1] = (index/1000 ) + 48; index %= 1000;
166     path[i+2] = (index/100  ) + 48; index %= 100;
167     path[i+3] = (index/10   ) + 48;
168     path[i+4] = (index%10   ) + 48;
169     i += 5;
170 
171     for (j = 0; j < 5; i++, j++)
172     {
173         path[i] = exname[j];
174     }
175 
176     nn::fs::FileOutputStream fos;
177 
178     result = fos.TryInitialize(path, true);
179     if (result.IsFailure())
180     {
181         return(-2);
182     }
183 
184     // Create a BMP header
185     {
186         u32 xpad;
187 
188         xpad = ( 4 - ((width * 3) & 3) ) & 3;
189         i = 54 + width * height * 3 + xpad * height;
190 
191         // File size.
192         bh[ 2] = static_cast<u8>(i);
193         bh[ 3] = static_cast<u8>(i >> 8);
194         bh[ 4] = static_cast<u8>(i >> 16) & 255;
195         // Image size (width and height are reversed to accommodate LCD arrangement)
196         bh[18] = static_cast<u8>(height);
197         bh[19] = static_cast<u8>(height >> 8);
198         bh[22] = static_cast<u8>(width);
199         bh[23] = static_cast<u8>(width >> 8);
200     }
201 
202     // Write to display buffer
203     {
204         int x, y;
205         s32 size;
206 
207         data = reinterpret_cast<u8*>(addr);
208 
209         if(work == NULL)
210         {
211             result = fos.TryWrite(&size, bh, 54, true);
212             if (result.IsFailure())
213             {
214                 return(-3);
215             }
216 
217             for (x = 0; x < width; ++x)
218             {
219                 i = x * 3;
220                 for (y = j = 0; y < height; ++y)
221                 {
222                     linebuf[j  ] = data[i  ];
223                     linebuf[j+1] = data[i+1];
224                     linebuf[j+2] = data[i+2];
225                     j += 3;
226                     i += 3 * width;
227                 }
228                 result = fos.TryWrite(&size, linebuf, height * 3, true);
229                 if (result.IsFailure())
230                 {
231                     return(-4);
232                 }
233             }
234         }
235         else
236         {
237             u8* dst = work + 54;
238             // Copy to 'work' to write data along with the BMP header
239             std::memcpy(work, bh, 54);
240 
241             for (x = j = 0; x < width; ++x)
242             {
243                 i = x * 3;
244                 for (y = 0; y < height; ++y)
245                 {
246                     dst[j  ] = data[i  ];
247                     dst[j+1] = data[i+1];
248                     dst[j+2] = data[i+2];
249                     j += 3;
250                     i += 3 * width;
251                 }
252             }
253             result = fos.TryWrite(&size, work, width * height * 3 + 54, true);
254             if (result.IsFailure())
255             {
256                 return(-4);
257             }
258         }
259     }
260 
261     fos.Finalize();
262 
263     return 0;
264 }
265 
266 
267