1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     FsSecureSaveSample.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: 46547 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_SAMPLE_DEMOS_FS_SAMPLE_SECURE_SAVE_H_
17 #define NN_SAMPLE_DEMOS_FS_SAMPLE_SECURE_SAVE_H_
18 
19 namespace sample { namespace fs { namespace streaming {
20 
21 const char SAVE_DATA_ARCHIVE[] = "data:";
22 const char DATA_FILE_NAME[]    = "data:/Data";
23 
24 const int MAX_PATH_LENGTH = 255;
25 
26 const char EXT_ARCHIVE[] = "ext:";
27 const wchar_t MEMO_FILE_NAME[]  = L"ext:/Memo";
28 const bit64 EXT_SAVEDATA_ID = 0xFFFFF;
29 const int MEMO_FILE_NUM_MAX = 64;
30 
31 // Size of the region where recording can be done.
32 //
33 // Because the archive that saves streaming in this sample is expanded save data, the guaranteed overhead is 2000 ms when saving, and the write speed is 0.5 mb/s.
34 //
35 // The size of the region that can be saved each frame must be calculated from these values.
36 //
37 // Here, the byte size that must be recorded each second is x[MB/s], the single side buffer size is  y[MB], and the time to switch buffers is t[s].
38 //
39 // Given that:
40 // 2 + x * t / 0.5 < t
41 // x * t = y
42 // conditions need to be satisfied.
43 // Transforming this simultaneous inequality gives:
44 // 2 + y / 0.5 < y / x
45 // Analyzing the above with a buffer size y of 4[MB] gives x < 0.4[MB/s].
46 //
47 //
48 // From the fact that 1 byte is 8 pixels because 60 frames per second and binary, black/white, are used
49 // The number of pixels per frame is:
50 // 0.4[MB/s] / 60[frame/s] * 8[pixel/B] = 53333[pixel/frame].
51 //
52 // From the above, the size of the render region is 264 pixels wide by 200 pixels high.
53 const int MEMO_WIDTH  = 264;
54 const int MEMO_HEIGHT = 200;
55 const int MEMO_BLANK_WIDTH  = NN_GX_DISPLAY1_HEIGHT - MEMO_WIDTH;
56 const int MEMO_BLANK_HEIGHT = NN_GX_DISPLAY1_WIDTH - MEMO_HEIGHT;
57 const int MEMO_X = MEMO_BLANK_WIDTH  / 2;
58 const int MEMO_Y = MEMO_BLANK_HEIGHT / 2;
59 
60 
61 // This constant is used when rendering textures.
62 const int TEXTURE_BLOCK_SIZE = 8;
63 const int MEMO_TEXTURE_WIDTH = 512;
64 const int MEMO_TEXTURE_HEIGHT = 256;
65 
66 // With this sample, because textures are rendered directly, both the height and width must be a integer multiple of TEXTURE_BLOCK_SIZE.
67 //
68 NN_STATIC_ASSERT(MEMO_WIDTH % TEXTURE_BLOCK_SIZE == 0);
69 NN_STATIC_ASSERT(MEMO_HEIGHT % TEXTURE_BLOCK_SIZE == 0);
70 
71 // The number of bytes for the buffer required for each frame.
72 const int MEMO_BUFFER_SIZE = MEMO_WIDTH * MEMO_HEIGHT / 8;
73 
74 // Number of frames stored with the single side buffer.
75 const int BUFFERING_FRAME_NUM = 600;
76 
77 // Number of bytes for the buffer for each side.
78 // Each of the front buffer and back buffers are prepared with this size.
79 const int BUFFER_SIZE = MEMO_BUFFER_SIZE * BUFFERING_FRAME_NUM; // Corresponds to y in the equation.
80 
81 // Number of longest frames that can be recorded continuously. 3 minutes is specified.
82 // This is used only for determining the size when creating a file for the first time and does not define the length of the temporary buffer for streaming.
83 //
84 const int RECORDABLE_FRAME_NUM_MAX = 3 * 60 * 60;
85 
86 // Size of the file where each movie is recorded.
87 const s64 MAX_MEMO_FILE_SIZE = MEMO_BUFFER_SIZE * RECORDABLE_FRAME_NUM_MAX;
88 
89 #define RETURN_IF_FAILED_BASE(result, s1) \
90     do \
91     { \
92         ::nn::Result macro_return_if_failure_result = (result); \
93         if (macro_return_if_failure_result.IsFailure()) \
94         { \
95             s1;\
96             return macro_return_if_failure_result; \
97         } \
98     } while(0)
99 
100 #define RETURN_IF_FAILED(result) RETURN_IF_FAILED_BASE(result,)
101 #define RETURN_IF_FAILED_1(result, c1) RETURN_IF_FAILED_BASE(result,c1)
102 
103 struct Header
104 {
105     s64 size;
106 };
107 
108 struct SaveData
109 {
110     s32 data[1024];
111 };
112 
113 struct PacketData
114 {
115 private:
116     bit8 *data;
117     s32 size;
118     nn::os::BlockingQueue &returnQueue;
119 
120 public:
PacketDataPacketData121     PacketData(bit8 *_data, s32 _size, nn::os::BlockingQueue &_returnQueue) :
122         data(_data), size(_size), returnQueue(_returnQueue)
123     {}
124 
GetDataPacketData125     bit8 *GetData() { return data; }
GetSizePacketData126     s32 GetSize() { return size; }
127 
FreePacketData128     void Free()
129     {
130         returnQueue.Enqueue(reinterpret_cast<uptr>(this));
131     }
132 };
133 
134 enum ENUM_RECORDING_RESULT
135 {
136     RECORDING_RESULT_SUCCESS,
137     RECORDING_RESULT_BUFFER_FULL,
138     RECORDING_RESULT_FILE_FULL
139 };
140 
141 bool LoadMemo(PacketData **pOut);
142 ENUM_RECORDING_RESULT SaveMemo(const bit8 *srcBuffer);
143 nn::Result StartRecording(const wchar_t *fileName);
144 nn::Result StopRecording();
145 nn::Result StartPlaying(const wchar_t *fileName);
146 nn::Result StopPlaying();
147 nn::Result FinishPlaying();
148 nn::Result BgSave(const s32 data);
149 nn::Result BgLoad(s32 &data);
150 
151 }}}
152 
153 #endif
154