pfs0.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdbool.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "nx/pfs0.h"
  7. #include "util/log.h"
  8. #include "util/file.h"
  9. void pfs0_get_header(pfs0_struct_ptr *ptr, uint64_t offset)
  10. {
  11. memset(&ptr->header, 0, sizeof(pfs0_header_t));
  12. read_file(&ptr->header, sizeof(pfs0_header_t), offset, ptr->file);
  13. }
  14. void pfs0_populate_file_table(pfs0_struct_ptr *ptr)
  15. {
  16. ptr->file_table = malloc(ptr->file_table_size);
  17. memset(ptr->file_table, 0x0, ptr->file_table_size);
  18. read_file(ptr->file_table, ptr->file_table_size, ptr->file_table_offset, ptr->file);
  19. }
  20. void pfs0_populate_string_table(pfs0_struct_ptr *ptr)
  21. {
  22. ptr->string_table = malloc(ptr->header.total_files * sizeof(pfs0_string_table_t));
  23. uint8_t *data_temp = malloc(ptr->header.string_table_size);
  24. memset(ptr->string_table, 0, ptr->header.total_files * sizeof(pfs0_string_table_t));
  25. memset(data_temp, 0, ptr->header.string_table_size);
  26. read_file(data_temp, ptr->header.string_table_size, ptr->string_table_offset, ptr->file);
  27. for (uint32_t i = 0; i < ptr->header.total_files; i++)
  28. {
  29. size_t offset = ptr->file_table[i].name_offset;
  30. for (uint8_t j = 0; ; j++, offset++)
  31. {
  32. ptr->string_table[i].name[j] = data_temp[offset];
  33. if (ptr->string_table[i].name[j] == 0x00)
  34. {
  35. write_log("found string %s\n", ptr->string_table[i].name);
  36. break;
  37. }
  38. }
  39. }
  40. free(data_temp);
  41. }
  42. bool pfs0_check_valid_magic(uint32_t magic)
  43. {
  44. if (magic != PFS0_MAGIC)
  45. {
  46. write_log("\ngot wrong magic %u\n", magic);
  47. return false;
  48. }
  49. return true;
  50. }
  51. void pfs0_populate_table_size_offsets(pfs0_struct_ptr *ptr, uint64_t offset)
  52. {
  53. ptr->file_table_offset = offset;
  54. ptr->file_table_size = ptr->header.total_files * sizeof(pfs0_file_table_t);
  55. ptr->string_table_offset = ptr->file_table_offset + ptr->file_table_size;
  56. ptr->raw_data_offset = ptr->string_table_offset + ptr->header.string_table_size;
  57. }
  58. size_t pfs0_get_total_raw_data_size(pfs0_struct_ptr *ptr)
  59. {
  60. size_t total_size = 0;
  61. for (uint32_t i = 0; i < ptr->header.total_files; i++)
  62. total_size += ptr->file_table[i].data_size;
  63. return total_size;
  64. }
  65. int pfs0_search_string_table(pfs0_struct_ptr *ptr, const char *search_name)
  66. {
  67. for (uint32_t position = 0; position < ptr->header.total_files; position++)
  68. if (strstr(ptr->string_table[position].name, search_name))
  69. return position;
  70. write_log("failed to find %s\n", search_name);
  71. return -1;
  72. }
  73. bool pfs0_extract_file(pfs0_struct_ptr *ptr, int location)
  74. {
  75. FILE *new_file = fopen(ptr->string_table[location].name, "wb");
  76. if (!new_file)
  77. {
  78. write_log("failed to create new file %s\n", ptr->string_table[location].name);
  79. return false;
  80. }
  81. uint64_t curr_off = ptr->raw_data_offset + ptr->file_table[location].data_offset;
  82. size_t file_size = ptr->file_table[location].data_size;
  83. write_log("extracting %s: size %lu\n", ptr->string_table[location].name, file_size);
  84. for (size_t offset = 0, buf_size = 0x800000; offset < file_size; offset += buf_size)
  85. {
  86. if (offset + buf_size > file_size)
  87. buf_size = file_size - offset;
  88. uint8_t *buf = malloc(buf_size);
  89. read_file(buf, buf_size, curr_off + offset, ptr->file);
  90. fwrite(buf, buf_size, 1, new_file);
  91. free(buf);
  92. }
  93. fclose(new_file);
  94. return true;
  95. }
  96. bool pfs0_extract_all(pfs0_struct_ptr *ptr)
  97. {
  98. for (uint32_t i = 0; i < ptr->header.total_files; i++)
  99. if (!pfs0_extract_file(ptr, i))
  100. return false;
  101. return true;
  102. }
  103. void pfs0_free_structs(pfs0_struct_ptr *ptr)
  104. {
  105. if (ptr->file_table != NULL)
  106. free(ptr->file_table);
  107. if (ptr->string_table != NULL)
  108. free(ptr->string_table);
  109. }
  110. bool pfs0_process(pfs0_struct_ptr *ptr, uint64_t offset, FILE *fp)
  111. {
  112. if (!ptr || !fp)
  113. {
  114. write_log("missing params in pfs0_process\n");
  115. return false;
  116. }
  117. ptr->file = fp;
  118. // now lets call my pfs0 functions!.
  119. pfs0_get_header(ptr, offset);
  120. if (!pfs0_check_valid_magic(ptr->header.magic))
  121. {
  122. return false;
  123. }
  124. // fill out the tables.
  125. pfs0_populate_table_size_offsets(ptr, offset + PFS0_HEADER_SIZE);
  126. pfs0_populate_file_table(ptr);
  127. pfs0_populate_string_table(ptr);
  128. ptr->raw_data_size = pfs0_get_total_raw_data_size(ptr);
  129. return true;
  130. }
  131. bool pfs0_start(FILE *file, uint64_t offset) // poor naming, but this basically is like main() for the pfs0.
  132. {
  133. pfs0_struct_ptr ptr = {0};
  134. ptr.file = file;
  135. // now lets call my pfs0 functions!.
  136. pfs0_get_header(&ptr, offset);
  137. if (!pfs0_check_valid_magic(ptr.header.magic))
  138. return false;
  139. // fill out the tables.
  140. pfs0_populate_table_size_offsets(&ptr, offset + PFS0_HEADER_SIZE);
  141. pfs0_populate_file_table(&ptr);
  142. pfs0_populate_string_table(&ptr);
  143. ptr.raw_data_size = pfs0_get_total_raw_data_size(&ptr);
  144. // extract the contents of the pfs0.
  145. pfs0_extract_all(&ptr);
  146. // free structs that were used.
  147. pfs0_free_structs(&ptr);
  148. return true;
  149. }