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