1 /*---------------------------------------------------------------------------*
2 Project: NitroSDK - WFS - libraries
3 File: wfs_archive.c
4
5 Copyright 2007-2009 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/client.h>
17
18
19 /*---------------------------------------------------------------------------*/
20 /* Functions */
21
22 /*---------------------------------------------------------------------------*
23 Name: WFSi_ArchiveReadCallback
24
25 Description: Child WFS archive read access callback.
26
27 Arguments: archive: FSArchive structure
28 buffer: Transfer destination
29 offset: Transfer source
30 length: Transfer size
31
32 Returns: Process result.
33 *---------------------------------------------------------------------------*/
WFSi_ArchiveReadCallback(FSArchive * archive,void * buffer,u32 offset,u32 length)34 static FSResult WFSi_ArchiveReadCallback(FSArchive *archive, void *buffer, u32 offset, u32 length)
35 {
36 FSResult result = FS_RESULT_ERROR;
37 WFSClientContext * const context = (WFSClientContext*)FS_GetArchiveBase(archive);
38 const WFSTableFormat * const table = WFS_GetTableFormat(context);
39 if (table)
40 {
41 MI_CpuCopy8(&table->buffer[offset], buffer, length);
42 result = FS_RESULT_SUCCESS;
43 }
44 return result;
45 }
46
47 /*---------------------------------------------------------------------------*
48 Name: WFSi_ArchiveReadDoneCallback
49
50 Description: Child WFS archive read completion callback.
51
52 Arguments: context: WFSClientContext structure
53 succeeded: TRUE if the read succeeded, FALSE if it failed
54 arg: Argument specified in the callback
55
56 Returns: None.
57 *---------------------------------------------------------------------------*/
WFSi_ArchiveReadDoneCallback(WFSClientContext * context,BOOL succeeded,void * arg)58 static void WFSi_ArchiveReadDoneCallback(WFSClientContext *context, BOOL succeeded, void *arg)
59 {
60 FSFile * const file = (FSFile*)arg;
61 FSResult result = FS_RESULT_ERROR;
62 if (succeeded)
63 {
64 file->prop.file.pos += file->arg.readfile.len;
65 result = FS_RESULT_SUCCESS;
66 }
67 FS_NotifyArchiveAsyncEnd(FS_GetAttachedArchive(file), result);
68 (void)context;
69 }
70
71 /*---------------------------------------------------------------------------*
72 Name: WFSi_RomArchiveProc
73
74 Description: User procedure for a child ROM archive.
75
76 Arguments: file: FSFile structure
77 command: Command
78
79 Returns: Process result.
80 *---------------------------------------------------------------------------*/
WFSi_RomArchiveProc(FSFile * file,FSCommandType command)81 static FSResult WFSi_RomArchiveProc(FSFile *file, FSCommandType command)
82 {
83 FSResult result = FS_RESULT_ERROR;
84 switch (command)
85 {
86 case FS_COMMAND_READFILE:
87 {
88 void *buffer = file->arg.readfile.dst;
89 u32 offset = file->prop.file.pos;
90 u32 length = file->arg.readfile.len;
91 if (length == 0)
92 {
93 result = FS_RESULT_SUCCESS;
94 }
95 else
96 {
97 FSArchive * const archive = FS_GetAttachedArchive(file);
98 WFSClientContext * const context = (WFSClientContext*)FS_GetArchiveBase(archive);
99 const WFSTableFormat * const table = WFS_GetTableFormat(context);
100 if (table != NULL)
101 {
102 WFS_RequestClientRead(context, buffer, offset, length,
103 WFSi_ArchiveReadDoneCallback, file);
104 result = FS_RESULT_PROC_ASYNC;
105 }
106 }
107 }
108 break;
109 case FS_COMMAND_WRITEFILE:
110 result = FS_RESULT_UNSUPPORTED;
111 break;
112 default:
113 result = FS_RESULT_PROC_UNKNOWN;
114 break;
115 }
116 return result;
117 }
118
119 /*---------------------------------------------------------------------------*
120 Name: WFSi_EmptyArchiveProc
121
122 Description: This is an empty procedure that follows a call to WFS_EndClient().
123
124 Arguments: file: FSFile structure
125 command: Command
126
127 Returns: Processing result.
128 *---------------------------------------------------------------------------*/
WFSi_EmptyArchiveProc(FSFile * file,FSCommandType command)129 static FSResult WFSi_EmptyArchiveProc(FSFile *file, FSCommandType command)
130 {
131 FSResult result = FS_RESULT_PROC_UNKNOWN;
132 // Output a warning message and generate an error for commands that cannot be ignored without causing a problem.
133 if ((command != FS_COMMAND_CLOSEFILE) &&
134 ((command < FS_COMMAND_STATUS_BEGIN) || (command >= FS_COMMAND_STATUS_END)))
135 {
136 static BOOL once = FALSE;
137 if (!once)
138 {
139 once = TRUE;
140 OS_TWarning("WFS-Client has been finalized. (all the commands will fail)\n");
141 }
142 result = FS_RESULT_ERROR;
143 }
144 (void)file;
145 return result;
146 }
147
148
149 /*---------------------------------------------------------------------------*
150 Name: WFSi_SubThreadForEndClient
151
152 Description: Archive configuration thread in line with WFS_EndClient.
153
154 Arguments: arg: Unused
155
156 Returns: None.
157 *---------------------------------------------------------------------------*/
158 #define WFSi_STACK_SIZE 512
159 #define WFSi_STACK_PRIORITY 0
160 #define WFSi_MESG_QUEUE_DEPTH 1
161
162 static OSThread WFSi_SubThread;
163 static OSMessageQueue WFSi_MesgQueue;
164 static OSMessage WFSi_MesgArray[ WFSi_MESG_QUEUE_DEPTH ];
165 static u64 WFSi_Stack[ WFSi_STACK_SIZE / sizeof(u64) ];
166
167 static void WFSi_SubThreadForEndClient(void* arg);
WFSi_SubThreadForEndClient(void * arg)168 static void WFSi_SubThreadForEndClient(void* arg)
169 {
170 #pragma unused(arg)
171 FSArchive* archive;
172 OSMessage mesg;
173
174 (void)OS_ReceiveMessage(&WFSi_MesgQueue, &mesg, OS_MESSAGE_BLOCK);
175 archive = (FSArchive*)mesg;
176
177 (void)FS_SuspendArchive(archive);
178 FS_SetArchiveProc(archive, WFSi_EmptyArchiveProc, (u32)FS_ARCHIVE_PROC_ALL);
179 (void)FS_ResumeArchive(archive);
180
181 OS_ExitThread();
182 }
183
184 /*---------------------------------------------------------------------------*
185 Name: WFSi_SetThreadForEndClient
186
187 Description: WFSi_SubThreadForEndClient thread settings.
188
189 Arguments: archive: ROM archive WFSClientContext structure
190
191 Returns: None.
192 *---------------------------------------------------------------------------*/
WFSi_SetThreadForEndClient(FSArchive * archive)193 static void WFSi_SetThreadForEndClient(FSArchive* archive)
194 {
195 OSMessage mesg = (OSMessage)archive;
196
197 OS_InitMessageQueue( &WFSi_MesgQueue, &WFSi_MesgArray[0], WFSi_MESG_QUEUE_DEPTH );
198 OS_CreateThread( &WFSi_SubThread,
199 WFSi_SubThreadForEndClient,
200 (void*)0,
201 WFSi_Stack+WFSi_STACK_SIZE/sizeof(u64),
202 WFSi_STACK_SIZE,
203 WFSi_STACK_PRIORITY );
204 OS_WakeupThreadDirect( &WFSi_SubThread );
205 (void)OS_SendMessage( &WFSi_MesgQueue, mesg, OS_MESSAGE_BLOCK );
206 }
207
208
209 /*---------------------------------------------------------------------------*
210 Name: WFSi_RestoreRomArchive
211
212 Description: This is an unmount callback invoked when WFS_EndClient() is called.
213
214 Arguments: context: WFSClientContext structure.
215
216 Returns: None.
217 *---------------------------------------------------------------------------*/
WFSi_RestoreRomArchive(WFSClientContext * context)218 static void WFSi_RestoreRomArchive(WFSClientContext *context)
219 {
220 FSArchive *archive = FS_FindArchive("rom", 3);
221
222 //Only create thread and send message
223 WFSi_SetThreadForEndClient(archive);
224
225 (void)context;
226 }
227
228 /*---------------------------------------------------------------------------*
229 Name: WFS_ReplaceRomArchive
230
231 Description: Mounts the WFS archive.
232
233 Arguments: context: WFSClientContext structure
234
235 Returns: None.
236 *---------------------------------------------------------------------------*/
WFS_ReplaceRomArchive(WFSClientContext * context)237 void WFS_ReplaceRomArchive(WFSClientContext *context)
238 {
239 const WFSTableFormat * const table = WFS_GetTableFormat(context);
240 if (table != NULL)
241 {
242 FSArchive *archive = FS_FindArchive("rom", 3);
243 if (FS_IsArchiveLoaded(archive))
244 {
245 (void)FS_UnloadArchive(archive);
246 }
247 FS_SetArchiveProc(archive, WFSi_RomArchiveProc, (u32)FS_ARCHIVE_PROC_ALL);
248 context->unmount_callback = WFSi_RestoreRomArchive;
249 (void)FS_LoadArchive(archive, (u32)context,
250 table->region[WFS_TABLE_REGION_FAT].offset,
251 table->region[WFS_TABLE_REGION_FAT].length,
252 table->region[WFS_TABLE_REGION_FNT].offset,
253 table->region[WFS_TABLE_REGION_FNT].length,
254 WFSi_ArchiveReadCallback, NULL);
255 FS_AttachOverlayTable(MI_PROCESSOR_ARM9,
256 table->buffer +
257 table->region[WFS_TABLE_REGION_OV9].offset,
258 table->region[WFS_TABLE_REGION_OV9].length);
259 FS_AttachOverlayTable(MI_PROCESSOR_ARM7,
260 table->buffer +
261 table->region[WFS_TABLE_REGION_OV7].offset,
262 table->region[WFS_TABLE_REGION_OV7].length);
263 }
264 }
265
266
267 /*---------------------------------------------------------------------------*
268 $Log: wfs_archive.c,v $
269 Revision 1.1 2007/06/11 06:38:39 yosizaki
270 Initial upload.
271
272 $NoKeywords: $
273 *---------------------------------------------------------------------------*/
274