1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ut_BinaryFileFormat.cpp
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  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   $Revision:$
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/types.h>
19 #include <nw/assert.h>
20 #include <nw/ut/ut_BinaryFileFormat.h>
21 #include <nw/ut/ut_Inlines.h>
22 
23 
24 namespace nw {
25 namespace ut {
26 
27 
28 bool
IsValidBinaryFile(const BinaryFileHeader * pHeader,u32 signature,u32 version,u16 minBlocks)29 IsValidBinaryFile(
30     const BinaryFileHeader* pHeader,
31     u32                     signature,
32     u32                     version,
33     u16                     minBlocks  /* = 1 */
34 )
35 {
36     NW_POINTER_ASSERT( pHeader );
37 
38     if ( pHeader->signature != signature )
39     {
40         NW_WARNING(false, "Signature check failed ('%c%c%c%c' must be '%c%c%c%c').",
41             static_cast<char>(BitExtract(pHeader->signature, 24, 8)),
42             static_cast<char>(BitExtract(pHeader->signature, 16, 8)),
43             static_cast<char>(BitExtract(pHeader->signature,  8, 8)),
44             static_cast<char>(BitExtract(pHeader->signature,  0, 8)),
45             static_cast<char>(BitExtract(signature, 24, 8)),
46             static_cast<char>(BitExtract(signature, 16, 8)),
47             static_cast<char>(BitExtract(signature,  8, 8)),
48             static_cast<char>(BitExtract(signature,  0, 8))
49         );
50         return false;
51     }
52 
53     if ( pHeader->byteOrder != BYTE_ORDER_MARK )
54     {
55         NW_WARNING(false, "Unsupported byte order.");
56         return false;
57     }
58 
59     if ( NW_UT_VERSION_MAJOR(version) != NW_UT_VERSION_MAJOR(pHeader->version) ||
60          NW_UT_VERSION_MINOR(version) < NW_UT_VERSION_MINOR(pHeader->version)  ||
61          NW_UT_VERSION_BINARYBUGFIX(version) > NW_UT_VERSION_BINARYBUGFIX(pHeader->version) )
62     {
63         NW_WARNING(false, "Version check faild (bin:'%d.%d.%d.%d', lib:'%d.%d.%d.%d').",
64             NW_UT_VERSION_MAJOR(pHeader->version),
65             NW_UT_VERSION_MINOR(pHeader->version),
66             NW_UT_VERSION_MICRO(pHeader->version),
67             NW_UT_VERSION_BINARYBUGFIX(pHeader->version),
68             NW_UT_VERSION_MAJOR(version),
69             NW_UT_VERSION_MINOR(version),
70             NW_UT_VERSION_MICRO(version),
71             NW_UT_VERSION_BINARYBUGFIX(version)
72         );
73         return false;
74     }
75 
76     if( pHeader->fileSize < sizeof(BinaryFileHeader) + sizeof(BinaryBlockHeader) * minBlocks )
77     {
78         NW_WARNING(false, "Too small file size(=%d).", pHeader->fileSize);
79         return false;
80     }
81 
82     if( pHeader->dataBlocks < minBlocks )
83     {
84         NW_WARNING(false, "Too small number of data blocks(=%d).", pHeader->dataBlocks);
85         return false;
86     }
87 
88     return true;
89 }
90 
91 
92 /*!--------------------------------------------------------------------------*
93   Name:         IsReverseEndianBinaryFile
94 
95   @brief        NintendoWare 標準バイナリファイルのエンディアンが逆かどうかを
96                 チェックします。
97 
98   @param[in]    pFileHeader     対象のファイルヘッダへのポインタ
99 
100   @return       エンディアンが逆なら true,さもなければ false を返します。
101  *---------------------------------------------------------------------------*/
102 bool
IsReverseEndianBinaryFile(const BinaryFileHeader * pFileHeader)103 IsReverseEndianBinaryFile( const BinaryFileHeader* pFileHeader )
104 {
105     NW_POINTER_ASSERT( pFileHeader );
106     return ( pFileHeader->byteOrder != BYTE_ORDER_MARK );
107 }
108 
109 
110 /*!--------------------------------------------------------------------------*
111   Name:         GetNextBinaryBlockHeader
112 
113   @brief        NintendoWare 標準バイナリファイル内の次のブロックヘッダを
114                 取得します。
115 
116   @param[in]    pFileHeader     対象のファイルヘッダへのポインタ
117   @param[in]    pBlockHeader    現在のブロックヘッダへのポインタ
118 
119   @return       pBlockHeaderの次のブロックヘッダを返します。
120                 次のブロックがない場合は、NULLを返します。
121                 pBlockHeaderがNULLの場合は、一番始めのブロックヘッダを返します。
122  *---------------------------------------------------------------------------*/
123 BinaryBlockHeader*
GetNextBinaryBlockHeader(BinaryFileHeader * pFileHeader,BinaryBlockHeader * pBlockHeader)124 GetNextBinaryBlockHeader(
125     BinaryFileHeader*       pFileHeader,
126     BinaryBlockHeader*      pBlockHeader
127 )
128 {
129     NW_POINTER_ASSERT( pFileHeader );
130 
131     void* ptr;
132     if ( ! IsReverseEndianBinaryFile( pFileHeader ) )
133     {
134         if ( pBlockHeader == NULL )
135         {
136             if ( pFileHeader->dataBlocks == 0 ) return NULL;
137             ptr = AddOffsetToPtr( pFileHeader, pFileHeader->headerSize );
138         }
139         else
140         {
141             ptr = AddOffsetToPtr( pBlockHeader, pBlockHeader->size );
142         }
143 
144         if ( ptr >= AddOffsetToPtr( pFileHeader, pFileHeader->fileSize ) )
145         {
146             return NULL;
147         }
148     }
149     else
150     {
151         if ( pBlockHeader == NULL )
152         {
153             if ( pFileHeader->dataBlocks == 0 ) return NULL;
154             ptr = AddOffsetToPtr( pFileHeader, ReverseEndian( pFileHeader->headerSize ) );
155         }
156         else
157         {
158             ptr = AddOffsetToPtr( pBlockHeader, ReverseEndian( pBlockHeader->size ) );
159         }
160 
161         if ( ptr >= AddOffsetToPtr( pFileHeader, ReverseEndian( pFileHeader->fileSize ) ) )
162         {
163             return NULL;
164         }
165     }
166 
167     return reinterpret_cast<BinaryBlockHeader*>( ptr );
168 }
169 
170 } /* namespace ut */
171 } /* namespace nw */
172