Rev 7867 | Rev 7869 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 7867 | Rev 7868 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | #include |
1 | #include |
2 | #include |
2 | #include |
3 | #include |
3 | #include |
4 | #include |
4 | #include |
5 | #include |
5 | #include |
6 | #include |
- | |
Line 7... | Line 6... | ||
7 | 6 | ||
8 | typedef struct { |
7 | typedef struct { |
9 | size_t length; |
8 | size_t length; |
10 | size_t capacity; |
9 | size_t capacity; |
Line 52... | Line 51... | ||
52 | static void mkdir(const char *name) { |
51 | static void mkdir(const char *name) { |
53 | struct { |
52 | struct { |
54 | int fn; |
53 | int fn; |
55 | int unused[4]; |
54 | int unused[4]; |
56 | char b; |
55 | char b; |
57 | const char *path __attribute__((packed)); |
56 | const char *path; |
58 | } info; |
57 | } __attribute__((packed)) info; |
59 | memset(&info, 0, sizeof(info)); |
58 | memset(&info, 0, sizeof(info)); |
60 | info.fn = 9; |
59 | info.fn = 9; |
61 | info.b = 0; |
60 | info.b = 0; |
62 | info.path = name; |
61 | info.path = name; |
63 | asm volatile ("int $0x40"::"a"(70), "b"(&info)); |
62 | asm volatile ("int $0x40"::"a"(70), "b"(&info)); |
Line 327... | Line 326... | ||
327 | this->sectorsPerFat = *(uint16_t *)((uintptr_t)this->image + 0x16); |
326 | this->sectorsPerFat = *(uint16_t *)((uintptr_t)this->image + 0x16); |
328 | this->firstFat = (0 + this->reservedSectorCount) * this->bytesPerSector; |
327 | this->firstFat = (0 + this->reservedSectorCount) * this->bytesPerSector; |
329 | this->rootDirectory = this->firstFat + this->numberOfFats |
328 | this->rootDirectory = this->firstFat + this->numberOfFats |
330 | * this->sectorsPerFat * this->bytesPerSector; |
329 | * this->sectorsPerFat * this->bytesPerSector; |
331 | this->dataRegion = this->rootDirectory + this->maxRootEntries * 32; |
330 | this->dataRegion = this->rootDirectory + this->maxRootEntries * 32; |
332 | con_printf("\nBytes per sector: %d\n", this->bytesPerSector); |
331 | printf("\nBytes per sector: %d\n", this->bytesPerSector); |
333 | con_printf("Sectors per claster: %d\n", this->sectorsPerClaster); |
332 | printf("Sectors per claster: %d\n", this->sectorsPerClaster); |
334 | con_printf("Reserver sector count: %d\n", this->reservedSectorCount); |
333 | printf("Reserver sector count: %d\n", this->reservedSectorCount); |
335 | con_printf("Number of FATs: %d\n", this->numberOfFats); |
334 | printf("Number of FATs: %d\n", this->numberOfFats); |
336 | con_printf("Max root entries: %d\n", this->maxRootEntries); |
335 | printf("Max root entries: %d\n", this->maxRootEntries); |
337 | con_printf("Total sectors: %d\n", this->totalSectors); |
336 | printf("Total sectors: %d\n", this->totalSectors); |
338 | con_printf("Sectors per FAT: %d\n", this->sectorsPerFat); |
337 | printf("Sectors per FAT: %d\n", this->sectorsPerFat); |
339 | con_printf("First FAT: %d\n", this->firstFat); |
338 | printf("First FAT: %d\n", this->firstFat); |
340 | con_printf("Root directory: %d\n", this->rootDirectory); |
339 | printf("Root directory: %d\n", this->rootDirectory); |
341 | con_printf("Data region: %d\n\n", this->dataRegion); |
340 | printf("Data region: %d\n\n", this->dataRegion); |
342 | return 1; |
341 | return 1; |
343 | } |
342 | } |
Line 344... | Line 343... | ||
344 | 343 | ||
345 | static int fat12__error(Fat12 *this, const char *errorMessage) { |
344 | static int fat12__error(Fat12 *this, const char *errorMessage) { |
346 | this->errorMessage = errorMessage; |
345 | this->errorMessage = errorMessage; |
347 | return 0; |
346 | return 0; |
Line 348... | Line 347... | ||
348 | } |
347 | } |
349 | 348 | ||
350 | static int handleError(const Fat12 *fat12) { |
- | |
351 | con_printf("Error in Fat12: %s\n", fat12->errorMessage); |
349 | static int handleError(const Fat12 *fat12) { |
352 | con_exit(0); |
350 | printf("Error in Fat12: %s\n", fat12->errorMessage); |
Line -... | Line 351... | ||
- | 351 | return -1; |
|
- | 352 | } |
|
- | 353 | ||
- | 354 | void writeFile(const char *fileName, int size, const uint8_t *data) { |
|
- | 355 | // FILE *fp = NULL; |
|
- | 356 | // if (!(fp = fopen(fileName, "wb"))) { perror(NULL); } |
|
- | 357 | // fwrite(data, 1, size, fp); |
|
- | 358 | // fclose(fp); |
|
- | 359 | struct Info { |
|
- | 360 | int number; |
|
- | 361 | int reserved0; |
|
- | 362 | int reserved1; |
|
- | 363 | int dataSize; |
|
- | 364 | const void *data; |
|
- | 365 | char zero; |
|
- | 366 | const char *name; |
|
- | 367 | } __attribute__((packed)) *info = calloc(sizeof(struct Info), 1); |
|
- | 368 | ||
- | 369 | info->number = 2; // create/overwrite file |
|
- | 370 | info->dataSize = size; |
|
- | 371 | info->data = data; |
|
- | 372 | info->zero = 0; |
|
- | 373 | info->name = fileName; |
|
353 | return -1; |
374 | asm volatile ("int $0x40" :: "a"(70), "b"(info)); |
354 | } |
- | |
355 | 375 | } |
|
Line 356... | Line 376... | ||
356 | static int callback(const char *name, size_t size, const uint8_t *data, void *param) { |
376 | |
357 | FILE *fp = NULL; |
377 | static int callback(const char *name, size_t size, const uint8_t *data, void *param) { |
358 | String *outputPath = param; |
378 | String *outputPath = param; |
Line 371... | Line 391... | ||
371 | *fileNameDelim = '\0'; |
391 | *fileNameDelim = '\0'; |
372 | mkdir_p(outputPath->data); |
392 | mkdir_p(outputPath->data); |
373 | *fileNameDelim = '/'; |
393 | *fileNameDelim = '/'; |
374 | } |
394 | } |
375 | } |
395 | } |
376 | con_printf("Extracting %s\n", outputPath->data); |
396 | printf("Extracting %s\n", outputPath->data); |
377 | if (!(fp = fopen(outputPath->data, "wb"))) { perror(NULL); } |
- | |
378 | fwrite(data, 1, size, fp); |
397 | writeFile(outputPath->data, size, data); |
379 | fclose(fp); |
- | |
380 | outputPath->data[outputPath->length] = '\0'; |
398 | outputPath->data[outputPath->length] = '\0'; |
381 | return 0; |
399 | return 0; |
382 | } |
400 | } |
Line 383... | Line 401... | ||
383 | 401 | ||
384 | 402 | ||
385 | 403 | ||
386 | int main(int argc, char **argv) { |
404 | int main(int argc, char **argv) { |
387 | Fat12 fat12 = { 0 }; |
- | |
388 | char *imageFile = NULL; |
- | |
389 | String outputFolder = { 0 }; |
- | |
390 | int exit = 0; |
- | |
Line 391... | Line 405... | ||
391 | 405 | Fat12 fat12 = { 0 }; |
|
392 | char app_title[] = "UnImg - kolibri.img file unpacker"; |
406 | char *imageFile = NULL; |
393 | if (con_init_console_dll_param(-1, -1, -1, 350, app_title)) return -1; |
407 | String outputFolder = { 0 }; |
394 | - | ||
395 | if (argc < 2) { |
- | |
396 | con_write_asciiz(" Usage:\n"); |
408 | |
397 | con_write_asciiz(" unimg \"/path/to/kolibri.img\" \"/optional/extract/path\" [-e]\n"); |
409 | if (argc < 2) { |
398 | con_write_asciiz(" where optional key [-e] is exit on success"); |
410 | puts(" Usage:\n"); |
399 | con_exit(0); |
411 | puts(" unimg \"/path/to/kolibri.img\" \"/optional/extract/path\"\n"); |
400 | return -1; |
412 | return -1; |
Line 401... | Line 413... | ||
401 | } else { |
413 | } else { |
402 | imageFile = argv[1]; |
414 | imageFile = argv[1]; |
Line 414... | Line 426... | ||
414 | strcat(outputFolder.data, strrchr(imageFile, '/')); |
426 | strcat(outputFolder.data, strrchr(imageFile, '/')); |
415 | } |
427 | } |
Line 416... | Line 428... | ||
416 | 428 | ||
Line 417... | Line -... | ||
417 | outputFolder.length = strlen(outputFolder.data); |
- | |
418 | - | ||
419 | // handle -e parameter - exit on success |
- | |
420 | if (argc >= 3 && !strcmp(argv[argc - 1], "-e")) { exit = 1; } |
429 | outputFolder.length = strlen(outputFolder.data); |
421 | 430 | ||
422 | if (!fat12__open(&fat12, imageFile)) { |
431 | if (!fat12__open(&fat12, imageFile)) { |
Line 423... | Line 432... | ||
423 | return handleError(&fat12); |
432 | return handleError(&fat12); |
424 | } |
433 | } |
425 | 434 | ||
Line 426... | Line 435... | ||
426 | if (!fat12__forEachFile(&fat12, callback, &outputFolder)) { |
435 | if (!fat12__forEachFile(&fat12, callback, &outputFolder)) { |
427 | return handleError(&fat12); |
- | |
428 | } |
436 | return handleError(&fat12); |