ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/ps2launchargs/source/uLaunchELF/vmcfs/src/vmc_misc.c
Revision: 1101
Committed: Wed Feb 7 05:08:54 2018 UTC (7 years, 8 months ago) by iritscen
Content type: text/x-csrc
File size: 28436 byte(s)
Log Message:
Added following to ps2launchargs:\n-Source code.\n-DLL needed to run ps2client.\n-Instructions for building uLaunchELF.

File Contents

# Content
1 #include "vmc.h"
2
3
4 // Misc fonctions
5
6 //----------------------------------------------------------------------------
7 // Search a direntry corresponding to a path
8 //----------------------------------------------------------------------------
9 unsigned int getDirentryFromPath ( struct direntry* retval, const char* path, struct gen_privdata* gendata, int unit )
10 {
11
12 PROF_START ( getDirentryFromPathProf );
13
14 DEBUGPRINT ( 6, "vmcfs: Searching Direntry corresponding to path: %s\n", path );
15
16 // Skip past the first slash if they opened a file such as
17 // vmc0: / file.txt ( which means the path passed here will be / file.txt, we
18 // want to skip that first slash, to ease comparisons.
19 int pathoffset = 0;
20
21 if ( path[ 0 ] == '/' )
22 pathoffset = 1;
23
24 if ( ( path[ 0 ] == '/' || path[ 0 ] == '.' ) && path[ 1 ] == '\0' ) // rootdirectory
25 {
26
27 gendata->dirent_page = 0;
28 readPage ( gendata->fd, ( unsigned char* ) retval, gendata->first_allocatable * g_Vmc_Image[ unit ].header.pages_per_cluster );
29
30 PROF_END ( getDirentryFromPathProf );
31
32 return ROOT_CLUSTER;
33
34 }
35
36 struct direntry dirent; // Our temporary directory entry
37
38 int status = 0; // The status of our search, if 0 at the end, we didn't find path
39 unsigned int current_cluster = 0; // The cluster we are currently scanning for directory entries
40 int length = 1; // The number of items in the current directory
41 int i = 0;
42
43 // Our main loop that goes through files / folder searching for the right one
44 for ( i = 0; i < length; i++ )
45 {
46
47 gendata->dirent_page = i % g_Vmc_Image[ unit ].header.pages_per_cluster;
48
49 DEBUGPRINT ( 6, "vmcfs: Reading in allocatable cluster %u / page %u\n", ( current_cluster + gendata->first_allocatable ), ( current_cluster + gendata->first_allocatable ) * g_Vmc_Image[ unit ].header.pages_per_cluster + gendata->dirent_page );
50
51 // Reads either the first or second page of a cluster, depending
52 // on the value currently stored in i
53 readPage ( gendata->fd, ( unsigned char* ) &dirent, ( current_cluster + gendata->first_allocatable ) * g_Vmc_Image[ unit ].header.pages_per_cluster + gendata->dirent_page );
54
55 // Check if this was the first entry ( aka the rootdirectory )
56 if ( i == 0 && current_cluster == 0 )
57 length = dirent.length;
58
59 DEBUGPRINT ( 5, "vmcfs: Direntry Informations\n" );
60 DEBUGPRINT ( 5, "vmcfs: Object Type : %s\n", ( dirent.mode & DF_DIRECTORY ) ?"Folder":"File" );
61 DEBUGPRINT ( 5, "vmcfs: Object Name : %s\n", dirent.name );
62 DEBUGPRINT ( 5, "vmcfs: Object Exists : %s\n", ( dirent.mode & DF_EXISTS ) ?"Yes":"No" );
63 DEBUGPRINT ( 5, "vmcfs: Object Length : %u\n", dirent.length );
64 DEBUGPRINT ( 5, "vmcfs: Object Cluster : %u\n", dirent.cluster );
65
66 // Now that we have a pages worth of data, check if it is the
67 // Directory we are searching for.
68
69 if ( memcmp ( dirent.name, path + pathoffset, strlen ( dirent.name ) ) == 0 )
70 {
71
72 // Increase the path offset by the length of the directory
73 pathoffset += strlen ( dirent.name );
74
75 // If the next item in the pathname is the null terminator,
76 // we must be at the end of the path string, and that means
77 // we found the correct entry, so we can break.
78 if ( path[ pathoffset ] == '\0' || ( path[ pathoffset ] == '/' && path[ pathoffset + 1 ] == '\0' ) )
79 {
80
81 DEBUGPRINT ( 6, "vmcfs: Breaking from function\n" );
82 DEBUGPRINT ( 6, "vmcfs: dir_cluster = %u\n", dirent.cluster );
83 DEBUGPRINT ( 6, "vmcfs: dirent.name = %s\n", dirent.name );
84 DEBUGPRINT ( 6, "vmcfs: dirent.length = %u\n", dirent.length );
85
86 status = 1;
87
88 break;
89
90 }
91 // Otherwise we found the subfolder, but not the
92 // requested entry, keep going
93 else
94 {
95
96 DEBUGPRINT ( 6, "vmcfs: Recursing into subfolder\n" );
97 DEBUGPRINT ( 6, "vmcfs: dir_cluster = %u\n", dirent.cluster );
98 DEBUGPRINT ( 6, "vmcfs: dirent.name = %s\n", dirent.name );
99 DEBUGPRINT ( 6, "vmcfs: dirent.length = %u\n", dirent.length );
100
101 i = -1; // will be 0 when we continue, essentially starting the loop over again
102 current_cluster = dirent.cluster; // dirent.cluster refer to fat table and current_cluster to allocatable place
103 length = dirent.length; // set length to current directory length
104 pathoffset++; // add one to skip past the / in the folder name
105
106 continue;
107
108 }
109
110 }
111
112 // If we just read the second half of a cluster, we need to set
113 // current_cluster to the next cluster in the chain.
114 if ( i % g_Vmc_Image[ unit ].header.pages_per_cluster )
115 {
116
117 current_cluster = getFatEntry ( gendata->fd, current_cluster, gendata->indir_fat_clusters, FAT_VALUE );
118
119 }
120
121 }
122
123 // When we get here, that means one of two things:
124 // 1 ) We found the requested folder / file
125 // 2 ) We searched through all files / folders, and could not find it.
126 // To determine which one it was, check the status variable.
127 if ( status == 0 )
128 {
129
130 PROF_END ( getDirentryFromPathProf )
131
132 return NOFOUND_CLUSTER;
133
134 }
135
136 // Copy the last directory entry's contents into 'retval'
137 memcpy ( retval, &dirent, sizeof ( dirent ) );
138
139 PROF_END ( getDirentryFromPathProf )
140
141 // Return the cluster where the desired directory entry can be found
142 return current_cluster;
143
144 }
145
146
147 //----------------------------------------------------------------------------
148 // Add 2 pseudo entries for a new directory
149 //----------------------------------------------------------------------------
150 unsigned int addPseudoEntries ( struct gen_privdata* gendata, struct direntry* parent, int unit )
151 {
152
153 // Get a free cluster we can use to store the entries '.' and '..'
154 unsigned int pseudo_entries_cluster = getFreeCluster ( gendata, unit );
155
156 if ( pseudo_entries_cluster == ERROR_CLUSTER )
157 {
158
159 DEBUGPRINT ( 2, "vmcfs: Not enough free space to add pseudo entries. Aborting.\n" );
160
161 return ERROR_CLUSTER;
162
163 }
164
165 // Create the first 2 psuedo entries for the folder, and write them
166 DEBUGPRINT ( 5, "vmcfs: Adding pseudo entries into fat table cluster %u\n", pseudo_entries_cluster );
167
168 struct direntry pseudo_entries;
169
170 memset ( &pseudo_entries, 0, sizeof ( pseudo_entries ) );
171
172 // fill pseudo entries
173 strcpy ( pseudo_entries.name, "." );
174 pseudo_entries.dir_entry = parent->length;
175 pseudo_entries.length = 0;
176 pseudo_entries.cluster = parent->cluster;
177 pseudo_entries.mode = DF_EXISTS | DF_0400 | DF_DIRECTORY | DF_READ | DF_WRITE | DF_EXECUTE; // 0x8427
178
179 getPs2Time ( &pseudo_entries.created );
180 getPs2Time ( &pseudo_entries.modified );
181
182 // write first pseudo entry
183 writePage ( gendata->fd, ( unsigned char* ) &pseudo_entries, ( pseudo_entries_cluster + gendata->first_allocatable ) * g_Vmc_Image[ unit ].header.pages_per_cluster );
184
185 strcpy ( pseudo_entries.name, ".." );
186 pseudo_entries.dir_entry = 0;
187 pseudo_entries.cluster = 0;
188
189 // write second pseudo entry
190 writePage ( gendata->fd, ( unsigned char* ) &pseudo_entries, ( pseudo_entries_cluster + gendata->first_allocatable ) * g_Vmc_Image[ unit ].header.pages_per_cluster + 1 );
191
192 // set cluster as EOF
193 setFatEntry ( gendata->fd, pseudo_entries_cluster, EOF_CLUSTER, gendata->indir_fat_clusters, FAT_SET );
194
195 return pseudo_entries_cluster;
196
197 }
198
199
200 //----------------------------------------------------------------------------
201 // Add an object into vmc image.
202 // This fonction get a free cluster where it can insert the object, insert it and return the cluster number.
203 // Object can be a file or a folder.
204 //----------------------------------------------------------------------------
205 unsigned int addObject ( struct gen_privdata* gendata, unsigned int parent_cluster, struct direntry* parent, struct direntry* dirent, int unit )
206 {
207
208 int i = 0;
209 unsigned int retval = ERROR_CLUSTER;
210 unsigned int current_cluster = parent->cluster;
211
212 // Find to the last cluster in the list of files / folder to add our new object after it
213 for ( i = 0; i < parent->length; i += g_Vmc_Image[ unit ].header.pages_per_cluster )
214 {
215
216 DEBUGPRINT ( 6, "vmcfs: Following fat table cluster: %u\n", current_cluster );
217
218 if ( getFatEntry ( gendata->fd, current_cluster, gendata->indir_fat_clusters, FAT_VALUE ) == EOF_CLUSTER )
219 {
220
221 DEBUGPRINT ( 6, "vmcfs: Last used cluster in fat table %u\n", current_cluster );
222 break;
223
224 }
225
226 current_cluster = getFatEntry ( gendata->fd, current_cluster, gendata->indir_fat_clusters, FAT_VALUE );
227
228 }
229
230 // Check if we need a new cluster or if we can add our object at the end of an allocatable cluster
231 if ( parent->length % g_Vmc_Image[ unit ].header.pages_per_cluster == 0 ) // if its even, we need a new cluster for our file
232 {
233
234 // Get a free cluster because our object require an additional cluster
235 unsigned int nextfree_cluster = getFreeCluster ( gendata, unit );
236
237 if ( nextfree_cluster == ERROR_CLUSTER )
238 {
239
240 DEBUGPRINT ( 2, "vmcfs: Not enough free space. Aborting.\n" );
241
242 return ERROR_CLUSTER;
243
244 }
245
246 DEBUGPRINT ( 6, "vmcfs: Added new object in fat table cluster %u ( Page %u ) \n", current_cluster, current_cluster * g_Vmc_Image[ unit ].header.pages_per_cluster );
247
248 setFatEntry ( gendata->fd, current_cluster, nextfree_cluster, gendata->indir_fat_clusters, FAT_SET ); // update the last cluster in the directory entry list to point to our new cluster
249 setFatEntry ( gendata->fd, nextfree_cluster, EOF_CLUSTER, gendata->indir_fat_clusters, FAT_SET ); // set the free cluster we just found to be EOF
250
251 // If the object is a folder, we have to add 2 psuedoentries
252 if ( dirent->mode & DF_DIRECTORY )
253 {
254
255 // Link the new folder to the entries we just created
256 dirent->cluster = addPseudoEntries( gendata, parent, unit );
257
258 if ( dirent->cluster == ERROR_CLUSTER )
259 return ERROR_CLUSTER;
260
261 // Set the length of the directory to 2, for the 2 psuedoentries we just added
262 dirent->length = 2;
263
264 }
265
266 // write the page containing our direntry object information
267 writePage ( gendata->fd, ( unsigned char* ) dirent, ( nextfree_cluster + gendata->first_allocatable ) * g_Vmc_Image[ unit ].header.pages_per_cluster );
268
269 // now we need to update the length of the parent directory
270 parent->length++;
271 writePage ( gendata->fd, ( unsigned char* ) parent, ( parent_cluster + gendata->first_allocatable ) * g_Vmc_Image[ unit ].header.pages_per_cluster + gendata->dirent_page );
272
273 gendata->dirent_page = 0;
274 retval = nextfree_cluster;
275
276 }
277 else // otherwise we can just add the directory entry to the end of the last cluster
278 {
279
280 DEBUGPRINT ( 5, "vmcfs: Added new object in fat table cluster %u ( Page %u ) \n", current_cluster, current_cluster * g_Vmc_Image[ unit ].header.pages_per_cluster + 1 );
281
282 // If the object is a folder, we have to add 2 psuedoentries
283 if ( dirent->mode & DF_DIRECTORY )
284 {
285
286 // Link the new folder to the entries we just created
287 dirent->cluster = addPseudoEntries( gendata, parent, unit );
288
289 if ( dirent->cluster == ERROR_CLUSTER )
290 return ERROR_CLUSTER;
291
292 // Set the length of the directory to 2, for the 2 psuedoentries we just added
293 dirent->length = 2;
294
295 }
296
297 // write the page containing our direntry object information
298 writePage ( gendata->fd, ( unsigned char* ) dirent, ( current_cluster + gendata->first_allocatable ) * g_Vmc_Image[ unit ].header.pages_per_cluster + 1 );// write the page containing our directory information ( + 1 because we are writing the second page in the cluster )
299
300 // now we need to update the length of the parent directory
301 parent->length++;
302 writePage ( gendata->fd, ( unsigned char* ) parent, ( parent_cluster + gendata->first_allocatable ) * g_Vmc_Image[ unit ].header.pages_per_cluster + gendata->dirent_page );
303
304 gendata->dirent_page = 1;
305 retval = current_cluster;
306
307 }
308
309 return retval;
310
311 }
312
313
314 //----------------------------------------------------------------------------
315 // Remove an object from vmc image.
316 // Object can be a file or a directory.
317 // Follow fat table to find the last cluster of the direntry chain cluster. ( EOF_CLUSTER )
318 // Change bit mask of tested cluster if it's not EOF. ( only for files )
319 // Set as free the last cluster of the direntry.
320 // Finaly, set deleted flag of the direntry. ( DF_EXISTS flag )
321 //----------------------------------------------------------------------------
322 void removeObject ( struct gen_privdata* gendata, unsigned int dirent_cluster, struct direntry* dirent, int unit )
323 {
324
325 unsigned int current_cluster = 0;
326 unsigned int last_cluster = dirent->cluster;
327
328 DEBUGPRINT ( 3, "vmcfs: Searching last cluster of direntry\n" );
329
330 while ( 1 )
331 {
332
333 current_cluster = getFatEntry ( gendata->fd, last_cluster, gendata->indir_fat_clusters, FAT_VALUE );
334
335 if ( current_cluster == FREE_CLUSTER )
336 {
337
338 // FREE_CLUSTER mean nothing to remove or error, so return
339 DEBUGPRINT ( 10, "vmcfs: Testing cluster %u ... value is FREE_CLUSTER\n", last_cluster );
340
341 return;
342
343 }
344 else if ( current_cluster == EOF_CLUSTER )
345 {
346
347 // EOF_CLUSTER mean last cluster of the direntry is found
348 DEBUGPRINT ( 3, "vmcfs: Last cluster of direntry at %u\n", last_cluster );
349
350 break;
351
352 }
353 else
354 {
355
356 // Otherwise change bit mask of tested cluster
357 DEBUGPRINT ( 10, "vmcfs: Testing cluster %u ... value is %u\n", last_cluster, current_cluster );
358
359 setFatEntry ( gendata->fd, last_cluster, current_cluster, gendata->indir_fat_clusters, FAT_RESET );
360
361 }
362
363 last_cluster = current_cluster;
364
365 }
366
367 // Set last cluster of direntry as free.
368 setFatEntry ( gendata->fd, last_cluster, FREE_CLUSTER, gendata->indir_fat_clusters, FAT_RESET ); // set the last cluster of the file as free
369
370 // Set object as deleted. ( Remove DF_EXISTS flag )
371 dirent->mode = dirent->mode ^ DF_EXISTS;
372 writePage ( gendata->fd, ( unsigned char* ) dirent, ( dirent_cluster + gendata->first_allocatable ) * g_Vmc_Image[ unit ].header.pages_per_cluster + gendata->dirent_page );
373
374 }
375
376
377 //----------------------------------------------------------------------------
378 // Return a free cluster.
379 //----------------------------------------------------------------------------
380 unsigned int getFreeCluster ( struct gen_privdata* gendata, int unit )
381 {
382
383 unsigned int i = 0;
384 unsigned int value = 0;
385 unsigned int cluster_mask = MASK_CLUSTER;
386
387 for ( i = g_Vmc_Image[ unit ].last_free_cluster; i < gendata->last_allocatable; i++ )
388 {
389
390 value = getFatEntry ( gendata->fd, i - gendata->first_allocatable, gendata->indir_fat_clusters, FAT_VALUE );
391
392 if ( value == FREE_CLUSTER )
393 {
394
395 DEBUGPRINT ( 10, "vmcfs: Testing fat table cluster %d ... value is FREE_CLUSTER\n", i - gendata->first_allocatable );
396
397 DEBUGPRINT ( 6, "vmcfs: Free cluster found at %d in fat table\n", i - gendata->first_allocatable );
398 g_Vmc_Image[ unit ].last_free_cluster = i;
399
400 return ( i - gendata->first_allocatable );
401
402 }
403 else if ( value == EOF_CLUSTER )
404 {
405
406 DEBUGPRINT ( 10, "vmcfs: Testing fat table cluster %d ... value is EOF_CLUSTER\n", i - gendata->first_allocatable );
407
408 }
409 else
410 {
411
412 DEBUGPRINT ( 10, "vmcfs: Testing fat table cluster %d ... value is %d\n", i - gendata->first_allocatable, value );
413
414 cluster_mask = getFatEntry ( gendata->fd, i - gendata->first_allocatable, gendata->indir_fat_clusters, FAT_MASK );
415
416 if ( cluster_mask != MASK_CLUSTER )
417 {
418
419 DEBUGPRINT ( 6, "vmcfs: Free cluster found at %d in fat table\n", i - gendata->first_allocatable );
420 g_Vmc_Image[ unit ].last_free_cluster = i;
421
422 return ( i - gendata->first_allocatable );
423
424 }
425
426 }
427
428 }
429
430 return ERROR_CLUSTER;
431
432 }
433
434
435 //----------------------------------------------------------------------------
436 // Set default specification to superblock header when card is not formated
437 //----------------------------------------------------------------------------
438 int setDefaultSpec ( int unit )
439 {
440
441 DEBUGPRINT ( 4, "vmcfs: SuperBlock set by default\n" );
442
443 memset ( &g_Vmc_Image[ unit ].header, g_Vmc_Image[ unit ].erase_byte, sizeof ( struct superblock ) );
444
445 strcpy ( g_Vmc_Image[ unit ].header.magic, "Sony PS2 Memory Card Format 1.2.0.0" );
446
447 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: magic[40] : %s\n" , g_Vmc_Image[ unit ].header.magic );
448
449 g_Vmc_Image[ unit ].header.page_size = 0x200;
450 g_Vmc_Image[ unit ].header.pages_per_cluster = 0x2;
451 g_Vmc_Image[ unit ].header.pages_per_block = 0x10;
452 g_Vmc_Image[ unit ].header.unused0 = 0xFF00;
453
454 g_Vmc_Image[ unit ].cluster_size = g_Vmc_Image[ unit ].header.page_size * g_Vmc_Image[ unit ].header.pages_per_cluster;
455 g_Vmc_Image[ unit ].erase_byte = 0xFF;
456 g_Vmc_Image[ unit ].last_idc = EOF_CLUSTER;
457 g_Vmc_Image[ unit ].last_cluster = EOF_CLUSTER;
458
459 if ( g_Vmc_Image[ unit ].card_size %( g_Vmc_Image[ unit ].header.page_size + 0x10 ) == 0 )
460 {
461
462 g_Vmc_Image[ unit ].ecc_flag = TRUE;
463 g_Vmc_Image[ unit ].total_pages = g_Vmc_Image[ unit ].card_size / ( g_Vmc_Image[ unit ].header.page_size + 0x10 );
464 g_Vmc_Image[ unit ].header.clusters_per_card = g_Vmc_Image[ unit ].card_size / ( ( g_Vmc_Image[ unit ].header.page_size + 0x10 ) * g_Vmc_Image[ unit ].header.pages_per_cluster );
465
466 }
467 else if ( g_Vmc_Image[ unit ].card_size %g_Vmc_Image[ unit ].header.page_size == 0 )
468 {
469
470 g_Vmc_Image[ unit ].ecc_flag = FALSE;
471 g_Vmc_Image[ unit ].total_pages = g_Vmc_Image[ unit ].card_size / g_Vmc_Image[ unit ].header.page_size;
472 g_Vmc_Image[ unit ].header.clusters_per_card = g_Vmc_Image[ unit ].card_size / ( g_Vmc_Image[ unit ].header.page_size * g_Vmc_Image[ unit ].header.pages_per_cluster );
473
474 }
475 else
476 {
477
478 // Size error
479 return 0;
480
481 }
482
483 g_Vmc_Image[ unit ].header.mc_type = 0x2;
484 g_Vmc_Image[ unit ].header.mc_flag = 0x2B;
485
486 DEBUGPRINT ( 4, "vmcfs: Image file Info: Number of pages : %d\n", g_Vmc_Image[ unit ].total_pages );
487 DEBUGPRINT ( 4, "vmcfs: Image file Info: Size of a cluster : %d bytes\n", g_Vmc_Image[ unit ].cluster_size );
488 DEBUGPRINT ( 4, "vmcfs: Image file Info: ECC shunk found : %s\n", g_Vmc_Image[ unit ].ecc_flag ? "YES" : "NO" );
489 DEBUGPRINT ( 3, "vmcfs: Image file Info: Vmc card type : %s MemoryCard.\n", ( g_Vmc_Image[ unit ].header.mc_type == PSX_MEMORYCARD ? "PSX" : ( g_Vmc_Image[ unit ].header.mc_type == PS2_MEMORYCARD ? "PS2" : "PDA" ) ) );
490 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: page_size : 0x%02x\n", g_Vmc_Image[ unit ].header.page_size );
491 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: pages_per_cluster : 0x%02x\n", g_Vmc_Image[ unit ].header.pages_per_cluster );
492 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: pages_per_block : 0x%02x\n", g_Vmc_Image[ unit ].header.pages_per_block );
493 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: clusters_per_card : 0x%02x\n", g_Vmc_Image[ unit ].header.clusters_per_card );
494
495 g_Vmc_Image[ unit ].header.first_allocatable = ( ( ( ( g_Vmc_Image[ unit ].total_pages - 1 ) * ( g_Vmc_Image[ unit ].cluster_size / g_Vmc_Image[ unit ].header.page_size ) ) / g_Vmc_Image[ unit ].cluster_size ) + 1 ) + 8 + ( ( g_Vmc_Image[ unit ].total_pages - 1 ) / ( g_Vmc_Image[ unit ].total_pages * g_Vmc_Image[ unit ].header.pages_per_cluster * ( g_Vmc_Image[ unit ].cluster_size / g_Vmc_Image[ unit ].header.page_size ) ) ) + 1;
496 g_Vmc_Image[ unit ].header.last_allocatable = ( g_Vmc_Image[ unit ].header.clusters_per_card - g_Vmc_Image[ unit ].header.first_allocatable ) - ( ( g_Vmc_Image[ unit ].header.pages_per_block / g_Vmc_Image[ unit ].header.pages_per_cluster ) * g_Vmc_Image[ unit ].header.pages_per_cluster );
497 g_Vmc_Image[ unit ].header.root_cluster = 0;
498
499 g_Vmc_Image[ unit ].header.backup_block1 = ( g_Vmc_Image[ unit ].total_pages / g_Vmc_Image[ unit ].header.pages_per_block ) - 1;
500 g_Vmc_Image[ unit ].header.backup_block2 = g_Vmc_Image[ unit ].header.backup_block1 - 1;
501 memset ( g_Vmc_Image[ unit ].header.unused1, g_Vmc_Image[ unit ].erase_byte, 8 );
502
503 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: first_allocatable : 0x%02x\n", g_Vmc_Image[ unit ].header.first_allocatable );
504 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: last_allocatable : 0x%02x\n", g_Vmc_Image[ unit ].header.last_allocatable );
505 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: root_cluster : 0x%02x\n", g_Vmc_Image[ unit ].header.root_cluster );
506 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: backup_block1 : 0x%02x\n", g_Vmc_Image[ unit ].header.backup_block1 );
507 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: backup_block2 : 0x%02x\n", g_Vmc_Image[ unit ].header.backup_block2 );
508
509 unsigned int last_blk_sector = 8;
510 int i = 0;
511
512 for ( i = 0; i <= ( ( g_Vmc_Image[ unit ].total_pages - 1 ) / 65536 ); i++ )
513 {
514 if ( ( ( ( last_blk_sector + i ) * ( g_Vmc_Image[ unit ].cluster_size / g_Vmc_Image[ unit ].header.page_size ) ) %g_Vmc_Image[ unit ].header.pages_per_block ) == 0 )
515 {
516 last_blk_sector = last_blk_sector + i;
517 }
518 g_Vmc_Image[ unit ].header.indir_fat_clusters[ i ]= last_blk_sector + i;
519 }
520
521 for ( i = 0; g_Vmc_Image[ unit ].header.indir_fat_clusters[ i ]!= 0; i++ )
522 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: indir_fat_clusters[%d] : 0x%02x\n", i, g_Vmc_Image[ unit ].header.indir_fat_clusters[ i ]);
523
524 memset ( g_Vmc_Image[ unit ].header.bad_block_list, g_Vmc_Image[ unit ].erase_byte, sizeof ( unsigned int ) * 32 );
525
526 g_Vmc_Image[ unit ].header.unused2 = 0;
527 g_Vmc_Image[ unit ].header.unused3 = 0x100;
528 g_Vmc_Image[ unit ].header.size_in_megs = ( g_Vmc_Image[ unit ].total_pages * g_Vmc_Image[ unit ].header.page_size ) / ( g_Vmc_Image[ unit ].cluster_size * g_Vmc_Image[ unit ].cluster_size );
529 g_Vmc_Image[ unit ].header.unused4 = 0xFFFFFFFF;
530 memset ( g_Vmc_Image[ unit ].header.unused5, g_Vmc_Image[ unit ].erase_byte, 12 );
531 g_Vmc_Image[ unit ].header.max_used = ( 97 * g_Vmc_Image[ unit ].header.clusters_per_card ) / 100;
532 memset ( g_Vmc_Image[ unit ].header.unused6, g_Vmc_Image[ unit ].erase_byte, 8 );
533 g_Vmc_Image[ unit ].header.unused7 = 0xFFFFFFFF;
534
535 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: mc_type : 0x%02x\n", g_Vmc_Image[ unit ].header.mc_type );
536 DEBUGPRINT ( 4, "vmcfs: SuperBlock Info: mc_flag : 0x%02x\n", g_Vmc_Image[ unit ].header.mc_flag );
537
538 g_Vmc_Image[ unit ].last_free_cluster = g_Vmc_Image[ unit ].header.first_allocatable;
539
540 return 1;
541
542 }
543
544
545 //----------------------------------------------------------------------------
546 // Used for timing functions, use this to optimize stuff
547 //----------------------------------------------------------------------------
548 #ifdef PROFILING
549
550 iop_sys_clock_t iop_clock_finished; // Global clock finished data
551
552 void profilerStart ( iop_sys_clock_t* iopclock )
553 {
554
555 GetSystemTime ( iopclock );
556
557 }
558
559 void profilerEnd ( const char* function, const char* name, iop_sys_clock_t* iopclock1 )
560 {
561
562 // Make this the first item, so we don't add time that need not be added
563 GetSystemTime ( &iop_clock_finished );
564
565 unsigned int sec1, usec1;
566 unsigned int sec2, usec2;
567
568 SysClock2USec ( &iop_clock_finished, &sec2, &usec2 );
569 SysClock2USec ( iopclock1, &sec1, &usec1 );
570
571 printf ( "vmcfs: Profiler[ %s ]: %s %ld. %ld seconds\n", function, name, sec2 - sec1, ( usec2 - usec1 ) / 1000 );
572
573 }
574
575 #endif
576
577
578 //----------------------------------------------------------------------------
579 // Get date and time from cdvd fonction and put them into a "vmc_datetime" struct pointer.
580 //----------------------------------------------------------------------------
581 int getPs2Time ( vmc_datetime* tm )
582 {
583
584 cd_clock_t cdtime;
585 s32 tmp;
586
587 static vmc_datetime timeBuf = {
588 0, 0x00, 0x00, 0x0A, 0x01, 0x01, 2008 // used if can not get time...
589 };
590
591 if ( CdReadClock ( &cdtime ) != 0 && cdtime.stat == 0 )
592 {
593
594 tmp = cdtime.second >> 4;
595 timeBuf.sec = ( unsigned int ) ( ( ( tmp << 2 ) + tmp ) << 1 ) + ( cdtime.second & 0x0F );
596 tmp = cdtime.minute >> 4;
597 timeBuf.min = ( ( ( tmp << 2 ) + tmp ) << 1 ) + ( cdtime.minute & 0x0F );
598 tmp = cdtime.hour >> 4;
599 timeBuf.hour = ( ( ( tmp << 2 ) + tmp ) << 1 ) + ( cdtime.hour & 0x0F );
600 // timeBuf.hour = ( timeBuf.hour + 4 ) %24;// TEMP FIX ( need to deal with timezones? ) ... aparently not!
601 tmp = cdtime.day >> 4;
602 timeBuf.day = ( ( ( tmp << 2 ) + tmp ) << 1 ) + ( cdtime.day & 0x0F );
603 tmp = cdtime.month >> 4;
604 timeBuf.month = ( ( ( tmp << 2 ) + tmp ) << 1 ) + ( cdtime.month & 0x0F );
605 tmp = cdtime.year >> 4;
606 timeBuf.year = ( ( ( tmp << 2 ) + tmp ) << 1 ) + ( cdtime.year & 0xF ) + 2000;
607
608 }
609
610 memcpy ( tm, &timeBuf, sizeof ( vmc_datetime ) );
611
612 return 0;
613
614 }
615
616
617 //----------------------------------------------------------------------------
618 // XOR table use for Error Correcting Code ( ECC ) calculation.
619 //----------------------------------------------------------------------------
620 const unsigned char ECC_XOR_Table[ 256 ]= {
621 0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4,
622 0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00,
623 0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77,
624 0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3,
625 0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66,
626 0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2,
627 0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5,
628 0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11,
629 0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55,
630 0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1,
631 0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96,
632 0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22,
633 0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87,
634 0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33,
635 0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44,
636 0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0,
637 0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44,
638 0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0,
639 0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87,
640 0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33,
641 0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96,
642 0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22,
643 0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55,
644 0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1,
645 0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5,
646 0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11,
647 0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66,
648 0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2,
649 0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77,
650 0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3,
651 0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4,
652 0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00,
653 };
654
655
656 //----------------------------------------------------------------------------
657 // Calculate ECC for a 128 bytes chunk of data
658 //----------------------------------------------------------------------------
659 int calculateECC ( char* ECC_Chunk, const unsigned char* Data_Chunk )
660 {
661 int i, c;
662
663 ECC_Chunk[ 0 ]= ECC_Chunk[ 1 ]= ECC_Chunk[ 2 ]= 0;
664
665 for ( i = 0; i < 0x80; i++ )
666 {
667
668 c = ECC_XOR_Table[ Data_Chunk[ i ] ];
669
670 ECC_Chunk[ 0 ] ^= c;
671
672 if ( c & 0x80 )
673 {
674
675 ECC_Chunk[ 1 ] ^= ~i;
676 ECC_Chunk[ 2 ] ^= i;
677
678 }
679
680 }
681
682 ECC_Chunk[ 0 ] = ~ECC_Chunk[ 0 ];
683 ECC_Chunk[ 0 ] &= 0x77;
684 ECC_Chunk[ 1 ] = ~ECC_Chunk[ 1 ];
685 ECC_Chunk[ 1 ] &= 0x7f;
686 ECC_Chunk[ 2 ] = ~ECC_Chunk[ 2 ];
687 ECC_Chunk[ 2 ] &= 0x7f;
688
689 return 1;
690
691 }
692
693
694 //----------------------------------------------------------------------------
695 // Build ECC from a complet page of data
696 //----------------------------------------------------------------------------
697 int buildECC ( int unit, char* Page_Data, char* ECC_Data )
698 {
699
700 char Data_Chunk[ 4 ][ 128 ];
701 char ECC_Chunk[ 4 ][ 3 ];
702 char ECC_Pad[ 4 ];
703
704 // This is to divide the page in 128 bytes chunks
705 memcpy ( Data_Chunk[ 0 ], Page_Data + 0, 128 );
706 memcpy ( Data_Chunk[ 1 ], Page_Data + 128, 128 );
707 memcpy ( Data_Chunk[ 2 ], Page_Data + 256, 128 );
708 memcpy ( Data_Chunk[ 3 ], Page_Data + 384, 128 );
709
710 // Ask for 128 bytes chunk ECC calculation, it returns 3 bytes per chunk
711 calculateECC ( ECC_Chunk[ 0 ], Data_Chunk[ 0 ]);
712 calculateECC ( ECC_Chunk[ 1 ], Data_Chunk[ 1 ]);
713 calculateECC ( ECC_Chunk[ 2 ], Data_Chunk[ 2 ]);
714 calculateECC ( ECC_Chunk[ 3 ], Data_Chunk[ 3 ]);
715
716 // Prepare Padding as ECC took only 12 bytes and stand on 16 bytes
717 memset ( ECC_Pad, g_Vmc_Image[ unit ].erase_byte, sizeof ( ECC_Pad ) );
718
719 // "MemCopy" our four 3 bytes ECC chunks into our 16 bytes ECC data buffer
720 // Finaly "MemCopy" our 4 bytes PAD chunks into last 4 bytes of our ECC data buffer
721 memcpy ( ECC_Data + 0, ECC_Chunk[ 0 ], 3 );
722 memcpy ( ECC_Data + 3, ECC_Chunk[ 1 ], 3 );
723 memcpy ( ECC_Data + 6, ECC_Chunk[ 2 ], 3 );
724 memcpy ( ECC_Data + 9, ECC_Chunk[ 3 ], 3 );
725 memcpy ( ECC_Data + 12, ECC_Pad , 4 );
726
727 return 1;
728
729 }

Properties

Name Value
svn:executable *