1 /*---------------------------------------------------------------------------*
2 Project: NitroSDK - WFS - libraries
3 File: wfs_format.c
4
5 Copyright 2007-2008 Nintendo. 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 *---------------------------------------------------------------------------*/
14
15
16 #include <nitro/wfs/format.h>
17
18
19 /*---------------------------------------------------------------------------*/
20 /* Functions */
21
22 /*---------------------------------------------------------------------------*
23 Name: WFS_LoadTable
24
25 Description: Reads the NTR binary FAT from the device.
26
27 Arguments: archive: The WFSTableFormat structure to initialize
28 allocator: The allocator used to internally allocate memory
29 device: The device storing the target FAT.
30 origin_a: The device-internal offset for the ROM loading the source FAT.
31 origin_b: The device-internal offset for the ROM that merges the overlay.
32
33 Returns: TRUE if the FAT is loaded correctly.
34 *---------------------------------------------------------------------------*/
WFS_LoadTable(WFSTableFormat * archive,MIAllocator * allocator,MIDevice * device,u32 origin_a,u32 origin_b)35 BOOL WFS_LoadTable(WFSTableFormat *archive, MIAllocator *allocator,
36 MIDevice *device, u32 origin_a, u32 origin_b)
37 {
38 const u32 diff = origin_b - origin_a;
39 const BOOL mixed = (diff != 0);
40 u32 mixed_overlay_count = 0;
41 u32 origin_b_fat = 0;
42 CARDRomRegion mem_region[WFS_TABLE_REGION_MAX];
43 int i;
44
45 /* Initializes the structure */
46 archive->origin = origin_a;
47 archive->buffer = NULL;
48 archive->length = 0;
49
50 /* Load the A header and record it in fat/fnt */
51 {
52 u8 buf[0x60];
53 const CARDRomHeader *header = (const CARDRomHeader *)buf;
54 (void)MI_ReadDevice(device, buf, archive->origin, sizeof(buf));
55 archive->region[WFS_TABLE_REGION_FAT].offset = MI_LoadLE32(&header->fat.offset);
56 archive->region[WFS_TABLE_REGION_FAT].length = MI_LoadLE32(&header->fat.length);
57 archive->region[WFS_TABLE_REGION_FNT].offset = MI_LoadLE32(&header->fnt.offset);
58 archive->region[WFS_TABLE_REGION_FNT].length = MI_LoadLE32(&header->fnt.length);
59 }
60 /* Load the B header and record it in ov9/ov7 */
61 {
62 u8 buf[0x60];
63 const CARDRomHeader *header = (const CARDRomHeader *)buf;
64 (void)MI_ReadDevice(device, buf, origin_b, sizeof(buf));
65 archive->region[WFS_TABLE_REGION_OV9].offset = MI_LoadLE32(&header->main_ovt.offset) + diff;
66 archive->region[WFS_TABLE_REGION_OV9].length = MI_LoadLE32(&header->main_ovt.length);
67 archive->region[WFS_TABLE_REGION_OV7].offset = MI_LoadLE32(&header->sub_ovt.offset) + diff;
68 archive->region[WFS_TABLE_REGION_OV7].length = MI_LoadLE32(&header->sub_ovt.length);
69 origin_b_fat = header->fat.offset + diff;
70 }
71 /* If 'mixed', [fat += (ov9 + ov7)] */
72 if (mixed)
73 {
74 mixed_overlay_count = (archive->region[WFS_TABLE_REGION_OV9].length +
75 archive->region[WFS_TABLE_REGION_OV7].length)
76 / sizeof(WFSOVLFormat);
77 }
78 /* Calculate length */
79 {
80 u32 offset = 0;
81 offset += sizeof(u32);
82 for (i = 0; i < WFS_TABLE_REGION_MAX; ++i)
83 {
84 mem_region[i].offset = offset;
85 mem_region[i].length = archive->region[i].length;
86 if (i == WFS_TABLE_REGION_FAT)
87 {
88 mem_region[i].length += mixed_overlay_count * sizeof(WFSFATFormat);
89 }
90 mem_region[i].length = MATH_ROUNDUP(mem_region[i].length, 32);
91 offset += sizeof(u32) + mem_region[i].length;
92 }
93 archive->length = offset;
94 }
95 /* Allocate the buffer */
96 if (allocator)
97 {
98 archive->buffer = MI_CallAlloc(allocator, archive->length, sizeof(u32));
99 if (archive->buffer)
100 {
101 /* Load either A or B's fat/fnt/ov9/ov7. NOTE: origin has been adjusted. */
102 {
103 u8 *dst = archive->buffer;
104 MI_StoreLE32(dst, archive->origin);
105 dst += sizeof(u32);
106 for (i = 0; i < WFS_TABLE_REGION_MAX; ++i)
107 {
108 const u32 length = archive->region[i].length;
109 const u32 padding = mem_region[i].length - length;
110 MI_StoreLE32(dst, length);
111 dst += sizeof(u32);
112 (void)MI_ReadDevice(device, dst, archive->origin + archive->region[i].offset, length);
113 dst += length;
114 MI_CpuFill8(dst, 0x00, padding);
115 dst += padding;
116 }
117 }
118 /* If 'mixed', [fat += (ov9 + ov7)] */
119 if (mixed)
120 {
121 u32 count = archive->region[WFS_TABLE_REGION_FAT].length / sizeof(WFSFATFormat);
122 u32 total = count + mixed_overlay_count;
123 u8 *dst = &archive->buffer[mem_region[WFS_TABLE_REGION_FAT].offset];
124 WFSFATFormat *fat = (WFSFATFormat*)(dst + sizeof(u32));
125 MI_StoreLE32(dst, total * sizeof(WFSFATFormat));
126 for (i = WFS_TABLE_REGION_OV9; i < WFS_TABLE_REGION_MAX; ++i)
127 {
128 WFSOVLFormat *ovl = (WFSOVLFormat *)&archive->buffer[mem_region[i].offset + sizeof(u32)];
129 u32 num = archive->region[i].length / sizeof(WFSOVLFormat);
130 u32 j;
131 for (j = 0; j < num; ++j)
132 {
133 if (count >= total)
134 {
135 OS_TWarning("exceeded FAT iterator! (internal logic error)");
136 }
137 else
138 {
139 WFSFATFormat entry;
140 (void)MI_ReadDevice(device, &entry,
141 archive->origin + origin_b_fat + ovl[j].file_id * sizeof(WFSFATFormat),
142 sizeof(entry));
143 MI_StoreLE32(&fat[count].top, MI_LEToH32(entry.top) + diff);
144 MI_StoreLE32(&fat[count].bottom, MI_LEToH32(entry.bottom) + diff);
145 MI_StoreLE32(&ovl[j].file_id, count);
146 ++count;
147 }
148 }
149
150 }
151 }
152 }
153 }
154 return (archive->buffer != NULL);
155 }
156
157 /*---------------------------------------------------------------------------*
158 Name: WFS_ParseTable
159
160 Description: Parses the memory that read the NTR binary FAT image.
161
162 Arguments: archive: The WFSTableFormat structure to initialize
163 The FAT image must be configured in advance in the members 'buffer' and 'length'.
164
165
166 Returns: None.
167 *---------------------------------------------------------------------------*/
WFS_ParseTable(WFSTableFormat * archive)168 void WFS_ParseTable(WFSTableFormat *archive)
169 {
170 const u8 *src = archive->buffer;
171 u32 pos = 0;
172 int i;
173 /* Get the base offset */
174 archive->origin = MI_LoadLE32(&src[pos]);
175 pos += sizeof(u32);
176 /* Extract information about each region from the given buffer */
177 for (i = 0; i < WFS_TABLE_REGION_MAX; ++i)
178 {
179 u32 len = MI_LoadLE32(&src[pos]);
180 pos += sizeof(u32);
181 archive->region[i].offset = pos;
182 archive->region[i].length = len;
183 pos += MATH_ROUNDUP(len, 32);
184 if (pos > archive->length)
185 {
186 OS_TPanic("specified invalid archive buffer!");
187 }
188 }
189 }
190
191
192 /*---------------------------------------------------------------------------*
193 $Log: wfs_format.c,v $
194 Revision 1.1 2007/04/13 04:12:37 yosizaki
195 Initial upload.
196
197 $NoKeywords: $
198 *---------------------------------------------------------------------------*/
199