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