Advertisement
BigETI

gc_mem.cpp

Jan 11th, 2015
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 22.84 KB | None | 0 0
  1. #include "gc_mem.h"
  2. #include <ctime>
  3.  
  4. #define Convert5To8(_v)         (((((int16_t)(_v)) << 3) | (((int16_t)(_v)) >> 2)) & 0xFF)
  5. #define Convert3To8(_v)         (((((int16_t)(_v)) << 5) | (((int16_t)(_v)) << 2) | (((int16_t)(_v)) >> 1)) & 0xFF)
  6. #define Convert4To8(_v)         (((((int16_t)(_v)) << 4) | ((int16_t)(_v))) & 0xFF)
  7.  
  8. #define GC_PALETTE_COUNT    (0x100)
  9.  
  10. #define TGA_CMP_HEADER_LEN      (12)
  11.  
  12. struct IHDR_chunk
  13. {
  14.     unsigned short width, height;
  15.     unsigned char bpp, dummy;
  16. };
  17.  
  18. static const IHDR_chunk banner_ihdr_chunk_buffer = { GC_BANNER_WIDTH, GC_BANNER_HEIGHT, 32, 0 }, icon_ihdr_chunk_buffer = { GC_ICON_WIDTH, GC_ICON_HEIGHT, 32, 0 };
  19. static const char tga_header[TGA_CMP_HEADER_LEN] = { 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
  20.  
  21. __fastcall GCMem::DirEntry::DirEntry(FILE *file)
  22. {
  23.     Read(file);
  24. }
  25.  
  26. GCMem::DirEntry::~DirEntry()
  27. {
  28.  
  29. }
  30.  
  31. void __fastcall GCMem::DirEntry::Read(FILE *file)
  32. {
  33.     if (fread(this, sizeof(DirEntry), 1, file) != 1) memset(this, 0xFF, sizeof(DirEntry));
  34. }
  35.  
  36. bool __fastcall GCMem::DirEntry::IsValid()
  37. {
  38.     return (*((uint32_t *)game_code) != 0xFFFFFFFF);
  39. }
  40.  
  41. GCMem::DirEntry::REGION __fastcall GCMem::DirEntry::GetRegion()
  42. {
  43.     REGION ret = REGION_UNKNOWN;
  44.     switch (game_code[3])
  45.     {
  46.     case 'J': ret = REGION_JAPAN; break;
  47.     case 'E': ret = REGION_USA; break;
  48.     case 'P': ret = REGION_EUR; break;
  49.     }
  50.     return ret;
  51. }
  52.  
  53. std::string __fastcall GCMem::DirEntry::GetRegionName()
  54. {
  55.     std::string ret = "Unknown";
  56.     switch (game_code[3])
  57.     {
  58.     case 'J': ret = "Japan"; break;
  59.     case 'E': ret = "USA"; break;
  60.     case 'P': ret = "Europe"; break;
  61.     }
  62.     return ret;
  63. }
  64.  
  65. std::string __fastcall GCMem::DirEntry::GetGameCode()
  66. {
  67.     std::string ret;
  68.     for (int i = 0; i < 0x4; i++) ret.push_back(game_code[i]);
  69.     return ret;
  70. }
  71.  
  72. std::string __fastcall GCMem::DirEntry::GetMakerCode()
  73. {
  74.     std::string ret;
  75.     for (int i = 0; i < 0x2; i++) ret.push_back(maker_code[i]);
  76.     return ret;
  77. }
  78.  
  79. std::string __fastcall GCMem::DirEntry::GetMakerName()
  80. {
  81.     std::string ret = "Unknown";
  82.     switch (*((uint16_t *)maker_code))
  83.     {
  84.     case 0x3130: ret = "Nintendo"; break;
  85.     case 0x3830: ret = "Capcom"; break;
  86.     case 0x3134: ret = "Ubisoft"; break;
  87.     case 0x4634: ret = "Eidos"; break;
  88.     case 0x3135: ret = "Acclaim"; break;
  89.     case 0x3235: ret = "Activision"; break;
  90.     case 0x4435: ret = "Midway"; break;
  91.     case 0x4735: ret = "Hudson"; break;
  92.     case 0x3436: ret = "Lucas Arts"; break;
  93.     case 0x3936: ret = "Electronic Arts"; break;
  94.     case 0x5336: ret = "TDK Mediactive"; break;
  95.     case 0x5038: ret = "Sega"; break;
  96.     case 0x3441: ret = "Mirage Studios"; break;
  97.     case 0x4641: ret = "Namco"; break;
  98.     case 0x3242: ret = "Bandai"; break;
  99.     case 0x4144: ret = "Tomy"; break;
  100.     case 0x4D45: ret = "Konami"; break;
  101.     }
  102.     return ret;
  103. }
  104.  
  105. GCMem::DirEntry::COLOR_FORMAT __fastcall GCMem::DirEntry::GetColorFormat()
  106. {
  107.     return (graphics_format & 0x1) ? COLOR_FORMAT_CI8 : COLOR_FORMAT_RGB5A3;
  108. }
  109.  
  110. std::string __fastcall GCMem::DirEntry::GetColorFormatName()
  111. {
  112.     std::string ret;
  113.     if (graphics_format & 0x1) ret = "CI8";
  114.     else ret = "RGB5A3";
  115.     return ret;
  116. }
  117.  
  118. bool __fastcall GCMem::DirEntry::IsBannerPresent()
  119. {
  120.     return (graphics_format & 0x2) != 0;
  121. }
  122.  
  123. GCMem::DirEntry::ICON_ANIMATION_TYPE __fastcall GCMem::DirEntry::GetIconAnimationType()
  124. {
  125.     return (graphics_format & 0x3) ? ICON_ANIMATION_FORWARD : ICON_ANIMATION_PING_PONG;
  126. }
  127.  
  128. std::string __fastcall GCMem::DirEntry::GetIconAnimationTypeName()
  129. {
  130.     return (graphics_format & 0x3) ? "forward" : "ping pong";
  131. }
  132.  
  133. std::string __fastcall GCMem::DirEntry::GetGameTitle()
  134. {
  135.     std::string ret;
  136.     for (int i = 0; i < 0x20; i++)
  137.     {
  138.         if (game_title[i] == '\0') break;
  139.         ret.push_back(game_title[i]);
  140.     }
  141.     return ret;
  142. }
  143.  
  144. uint32_t __fastcall GCMem::DirEntry::GetSaveTimeStamp()
  145. {
  146.     return (((save_time >> 24) & 0xFF) | ((save_time >> 8) & 0xFF00) | ((save_time << 8) & 0xFF0000) | ((save_time << 24) & 0xFF000000)) + 946684800;
  147. }
  148.  
  149. std::string __fastcall GCMem::DirEntry::GetSaveTime()
  150. {
  151.     time_t time(GetSaveTimeStamp());
  152.     struct tm _tm;
  153.     localtime_s(&_tm, &time);
  154.     char buffer[32];
  155.     std::strftime(buffer, 32, "%a, %d.%m.%Y %H:%M:%S", &_tm);
  156.     return buffer;
  157. }
  158.  
  159. uint32_t __fastcall GCMem::DirEntry::GetBannerOffsetInSave()
  160. {
  161.     return ((image_offset >> 24) & 0xFF) | ((image_offset >> 8) & 0xFF00) | ((image_offset << 8) & 0xFF0000) | ((image_offset << 24) & 0xFF000000);
  162. }
  163.  
  164. uint32_t __fastcall GCMem::DirEntry::GetBannerOffsetInFile()
  165. {
  166.     return GetSaveDataOffsetInFile() + GetBannerOffsetInSave();
  167. }
  168.  
  169. GCMem::DirEntry::ICON_FORMAT __fastcall GCMem::DirEntry::GetIconFormat(uint8_t index)
  170. {
  171.     ICON_FORMAT ret = ICON_FORMAT_NONE;
  172.     if (index < 8)
  173.     {
  174.         //index = 7 - index;
  175.         switch ((((icon_format >> 8) & 0xFF) | ((icon_format << 8) & 0xFF00) >> index) & 0x3)
  176.         {
  177.         case 0x1: ret = ICON_FORMAT_CI8_REUSE_PALETTE; break;
  178.         case 0x2: ret = ICON_FORMAT_RGB5A3; break;
  179.         case 0x3: ret = ICON_FORMAT_CI8_UNIQUE_PALETTE; break;
  180.         }
  181.     }
  182.     return ret;
  183. }
  184.  
  185. std::string __fastcall GCMem::DirEntry::GetIconFormatName(uint8_t index)
  186. {
  187.     std::string ret = "Unknown";
  188.     if (index < 8)
  189.     {
  190.         //index = 7 - index;
  191.         switch ((((icon_format >> 8) & 0xFF) | ((icon_format << 8) & 0xFF00) >> index) & 0x3)
  192.         {
  193.         case 0x1: ret = "CI8 (reuse palette)"; break;
  194.         case 0x2: ret = "RGB5A3"; break;
  195.         case 0x3: ret = "CI8 (unique palette)"; break;
  196.         }
  197.     }
  198.     return ret;
  199. }
  200.  
  201. GCMem::DirEntry::ANIMATION_SPEED __fastcall GCMem::DirEntry::GetAnimationSpeed(uint8_t index)
  202. {
  203.     ANIMATION_SPEED ret = ANIMATION_SPEED_NONE;
  204.     if (index < 8)
  205.     {
  206.         //index = 7 - index;
  207.         switch ((((animation_speed >> 8) & 0xFF) | ((animation_speed << 8) & 0xFF00) >> index) & 0x3)
  208.         {
  209.         case 0x1: ret = ANIMATION_SPEED_4; break;
  210.         case 0x2: ret = ANIMATION_SPEED_8; break;
  211.         case 0x3: ret = ANIMATION_SPEED_12; break;
  212.         }
  213.     }
  214.     return ret;
  215. }
  216.  
  217. std::string __fastcall GCMem::DirEntry::GetAnimationSpeedName(uint8_t index)
  218. {
  219.     std::string ret = "None";
  220.     if (index < 8)
  221.     {
  222.         //index = 7 - index;
  223.         switch ((((animation_speed >> 8) & 0xFF) | ((animation_speed << 8) & 0xFF00) >> index) & 0x3)
  224.         {
  225.         case 0x1: ret = "4"; break;
  226.         case 0x2: ret = "8"; break;
  227.         case 0x3: ret = "12"; break;
  228.         }
  229.     }
  230.     return ret;
  231. }
  232.  
  233. bool __fastcall GCMem::DirEntry::IsSavePublic()
  234. {
  235.     return (file_permissions & 0x4) != 0;
  236. }
  237.  
  238. bool __fastcall GCMem::DirEntry::CopyDisabled()
  239. {
  240.     return (file_permissions & 0x8) != 0;
  241. }
  242.  
  243. bool __fastcall GCMem::DirEntry::MovingDisabled()
  244. {
  245.     return (file_permissions & 0x10) != 0;
  246. }
  247.  
  248. uint8_t __fastcall GCMem::DirEntry::GetCounter()
  249. {
  250.     return counter;
  251. }
  252.  
  253. uint16_t __fastcall GCMem::DirEntry::GetBlockIndex()
  254. {
  255.     return ((block_index >> 8) & 0xFF) | ((block_index << 8) & 0xFF00);
  256. }
  257.  
  258. uint32_t __fastcall GCMem::DirEntry::GetSaveDataOffsetInFile()
  259. {
  260.     return (GetBlockIndex() * 0x2000);
  261. }
  262.  
  263. uint16_t __fastcall GCMem::DirEntry::GetSaveSize()
  264. {
  265.     return ((save_size >> 8) & 0xFF) | ((save_size << 8) & 0xFF00);
  266. }
  267.  
  268. uint32_t __fastcall GCMem::DirEntry::GetComment1OffsetInSave()
  269. {
  270.     return ((comment_offset >> 24) & 0xFF) | ((comment_offset >> 8) & 0xFF00) | ((comment_offset << 8) & 0xFF0000) | ((comment_offset << 24) & 0xFF000000);
  271. }
  272.  
  273. uint32_t __fastcall GCMem::DirEntry::GetComment1OffsetInFile()
  274. {
  275.     return GetSaveDataOffsetInFile() + GetComment1OffsetInSave();
  276. }
  277.  
  278. uint32_t __fastcall GCMem::DirEntry::GetComment2OffsetInSave()
  279. {
  280.     return GetComment1OffsetInSave() + 0x20;
  281. }
  282.  
  283. uint32_t __fastcall GCMem::DirEntry::GetComment2OffsetInFile()
  284. {
  285.     return GetSaveDataOffsetInFile() + GetComment2OffsetInSave();
  286. }
  287.  
  288. __fastcall GCMem::GameData::GameData(FILE *file) : dir_entry(NULL)
  289. {
  290.     const int tile_height = GC_BANNER_HEIGHT / 4, rgb53a_tile_width = GC_BANNER_WIDTH / 4, ci8_tile_width = GC_BANNER_WIDTH / 8, icon_tile_height = GC_ICON_HEIGHT / 4, rgb53a_icon_tile_width = GC_ICON_WIDTH / 4, ci8_icon_tile_width = GC_ICON_WIDTH / 8;
  291.     Pixel t_banner_pixel_data[GC_BANNER_PIXEL_COUNT], t_icon_pixel_data[GC_ICON_PIXEL_COUNT];
  292.     long current_pos, icon_pos;
  293.     int i, j, k, l, m, raw_i, out_i, palette_index;
  294.     char c;
  295.     void *input_pixel = NULL;
  296.     uint16_t palette[GC_PALETTE_COUNT];
  297.     memset(banner_pixel_data, 0, sizeof(Pixel) * GC_BANNER_PIXEL_COUNT);
  298.     memset(t_banner_pixel_data, 0, sizeof(Pixel) * GC_BANNER_PIXEL_COUNT);
  299.     memset(icon_pixel_data, 0, sizeof(Pixel) * 8 * GC_ICON_PIXEL_COUNT);
  300.     memset(t_icon_pixel_data, 0, sizeof(Pixel) * GC_ICON_PIXEL_COUNT);
  301.     memset(palette, 0, sizeof(uint16_t) * GC_PALETTE_COUNT);
  302.     //memset(u_palette, 0, sizeof(uint16_t) * 8 * GC_PALETTE_COUNT);
  303.     try
  304.     {
  305.         dir_entry = new DirEntry(file);
  306.         current_pos = ftell(file);
  307.     }
  308.     catch (...)
  309.     {
  310.         dir_entry = NULL;
  311.     }
  312.     if (dir_entry)
  313.     {
  314.         if (dir_entry->IsValid())
  315.         {
  316.             fseek(file, dir_entry->GetComment1OffsetInFile(), SEEK_SET);
  317.             for (i = 0; i < 0x20; i++)
  318.             {
  319.                 if ((c = fgetc(file)) == '\0') break;
  320.                 comment1.push_back(c);
  321.             }
  322.             fseek(file, dir_entry->GetComment2OffsetInFile(), SEEK_SET);
  323.             for (i = 0; i < 0x20; i++)
  324.             {
  325.                 if ((c = fgetc(file)) == '\0') break;
  326.                 comment2.push_back(c);
  327.             }
  328.             fseek(file, dir_entry->GetBannerOffsetInFile(), SEEK_SET);
  329.             switch (dir_entry->GetColorFormat())
  330.             {
  331.             case DirEntry::COLOR_FORMAT_RGB5A3:
  332.                 try
  333.                 {
  334.                     input_pixel = ((void *)(new uint16_t[GC_BANNER_PIXEL_COUNT]));
  335.                 }
  336.                 catch (...)
  337.                 {
  338.                     input_pixel = NULL;
  339.                 }
  340.                 if (input_pixel)
  341.                 {
  342.                     fread(input_pixel, sizeof(uint16_t), GC_BANNER_PIXEL_COUNT, file);
  343.                     for (i = 0; i < GC_BANNER_PIXEL_COUNT; i++) (((uint8_t *)(&(((uint16_t *)input_pixel)[i])))[0] ^= (((uint8_t *)(&(((uint16_t *)input_pixel)[i])))[1] ^= (((uint8_t *)(&(((uint16_t *)input_pixel)[i])))[0] ^= ((uint8_t *)(&(((uint16_t *)input_pixel)[i])))[1])));
  344.                     for (i = 0; i < tile_height; i++)
  345.                     {
  346.                         for (j = 0; j < rgb53a_tile_width; j++)
  347.                         {
  348.                             for (k = 0; k < 4; k++)
  349.                             {
  350.                                 for (l = 0; l < 4; l++)
  351.                                 {
  352.                                     out_i = (j * 4) + (i * GC_BANNER_WIDTH * 4) + (GC_BANNER_WIDTH * k) + l;
  353.                                     if (((uint16_t *)input_pixel)[raw_i = (j * 16) + (i * GC_BANNER_WIDTH * 4) + (k * 4) + l] & 0x8000)
  354.                                     {
  355.                                         t_banner_pixel_data[out_i].red = Convert5To8(((((uint16_t *)input_pixel)[raw_i] >> 10) & 0x1F));
  356.                                         t_banner_pixel_data[out_i].green = Convert5To8(((((uint16_t *)input_pixel)[raw_i] >> 5) & 0x1F));
  357.                                         t_banner_pixel_data[out_i].blue = Convert5To8((((uint16_t *)input_pixel)[raw_i] & 0x1F));
  358.                                         t_banner_pixel_data[out_i].alpha = 0xFF;
  359.                                     }
  360.                                     else
  361.                                     {
  362.                                         t_banner_pixel_data[out_i].alpha = Convert3To8((((uint16_t *)input_pixel)[raw_i] >> 12) & 0x7);
  363.                                         t_banner_pixel_data[out_i].red = Convert4To8((((uint16_t *)input_pixel)[raw_i] >> 8) & 0xF);
  364.                                         t_banner_pixel_data[out_i].green = Convert4To8((((uint16_t *)input_pixel)[raw_i] >> 4) & 0xF);
  365.                                         t_banner_pixel_data[out_i].blue = Convert4To8(((uint16_t *)input_pixel)[raw_i] & 0xF);
  366.                                     }
  367.                                 }
  368.                             }
  369.                         }
  370.                     }
  371.                     for (i = 0; i < GC_BANNER_HEIGHT; i++) memcpy(&(banner_pixel_data[i * GC_BANNER_WIDTH]), &(t_banner_pixel_data[GC_BANNER_PIXEL_COUNT - ((i + 1) * GC_BANNER_WIDTH)]), sizeof(Pixel) * GC_BANNER_WIDTH);
  372.                     delete[]((uint16_t *)input_pixel);
  373.                 }
  374.                 break;
  375.             case DirEntry::COLOR_FORMAT_CI8:
  376.                 try
  377.                 {
  378.                     input_pixel = ((void *)(new uint8_t[GC_BANNER_PIXEL_COUNT]));
  379.                 }
  380.                 catch (...)
  381.                 {
  382.                     input_pixel = NULL;
  383.                 }
  384.                 if (input_pixel)
  385.                 {
  386.                     fread(input_pixel, sizeof(uint8_t), GC_BANNER_PIXEL_COUNT, file);
  387.                     fread(palette, sizeof(uint16_t), GC_PALETTE_COUNT, file);
  388.                     for (i = 0; i < GC_PALETTE_COUNT; i++) (((uint8_t *)(&(((uint16_t *)palette)[i])))[0] ^= (((uint8_t *)(&(((uint16_t *)palette)[i])))[1] ^= (((uint8_t *)(&(((uint16_t *)palette)[i])))[0] ^= ((uint8_t *)(&(((uint16_t *)palette)[i])))[1])));
  389.                     for (i = 0; i < tile_height; i++)
  390.                     {
  391.                         for (j = 0; j < ci8_tile_width; j++)
  392.                         {
  393.                             for (k = 0; k < 4; k++)
  394.                             {
  395.                                 for (l = 0; l < 8; l++)
  396.                                 {
  397.                                     out_i = (j * 8) + (i * GC_BANNER_WIDTH * 4) + (GC_BANNER_WIDTH * k) + l;
  398.                                     palette_index = (int)(((uint8_t *)input_pixel)[(j * 32) + (i * GC_BANNER_WIDTH * 4) + (k * 8) + l]);
  399.                                     if (palette[palette_index] & 0x8000)
  400.                                     {
  401.                                         t_banner_pixel_data[out_i].red = Convert5To8(((palette[palette_index] >> 10) & 0x1F));
  402.                                         t_banner_pixel_data[out_i].green = Convert5To8(((palette[palette_index] >> 5) & 0x1F));
  403.                                         t_banner_pixel_data[out_i].blue = Convert5To8((palette[palette_index] & 0x1F));
  404.                                         t_banner_pixel_data[out_i].alpha = 0xFF;
  405.                                     }
  406.                                     else
  407.                                     {
  408.                                         t_banner_pixel_data[out_i].alpha = Convert3To8((palette[palette_index] >> 12) & 0x7);
  409.                                         t_banner_pixel_data[out_i].red = Convert4To8((palette[palette_index] >> 8) & 0xF);
  410.                                         t_banner_pixel_data[out_i].green = Convert4To8((palette[palette_index] >> 4) & 0xF);
  411.                                         t_banner_pixel_data[out_i].blue = Convert4To8(palette[palette_index] & 0xF);
  412.                                     }
  413.                                 }
  414.                             }
  415.                         }
  416.                     }
  417.                     for (i = 0; i < GC_BANNER_HEIGHT; i++) memcpy(&(banner_pixel_data[i * GC_BANNER_WIDTH]), &(t_banner_pixel_data[GC_BANNER_PIXEL_COUNT - ((i + 1) * GC_BANNER_WIDTH)]), sizeof(Pixel) * GC_BANNER_WIDTH);
  418.                     delete[]((uint8_t *)input_pixel);
  419.                 }
  420.                 break;
  421.             }
  422.             icon_pos = ftell(file);
  423.             for (i = 0; i < 8; i++)
  424.             {
  425.                 switch (dir_entry->GetIconFormat(i))
  426.                 {
  427.                 case DirEntry::ICON_FORMAT_CI8_REUSE_PALETTE://t_icon_pixel_data
  428.                     fseek(file, GC_ICON_PIXEL_COUNT * sizeof(uint8_t), SEEK_CUR);
  429.                     break;
  430.                 case DirEntry::ICON_FORMAT_RGB5A3:
  431.                     //fseek(file, GC_ICON_PIXEL_COUNT * sizeof(uint16_t), SEEK_CUR);
  432.                     try
  433.                     {
  434.                         input_pixel = new uint16_t[GC_ICON_PIXEL_COUNT];
  435.                     }
  436.                     catch (...)
  437.                     {
  438.                         input_pixel = NULL;
  439.                     }
  440.                     if (input_pixel)
  441.                     {
  442.                         fread(input_pixel, sizeof(uint16_t), GC_ICON_PIXEL_COUNT, file);
  443.                         for (j = 0; j < GC_ICON_PIXEL_COUNT; j++) (((uint8_t *)(&(((uint16_t *)input_pixel)[j])))[0] ^= (((uint8_t *)(&(((uint16_t *)input_pixel)[j])))[1] ^= (((uint8_t *)(&(((uint16_t *)input_pixel)[j])))[0] ^= ((uint8_t *)(&(((uint16_t *)input_pixel)[j])))[1])));
  444.                         for (j = 0; j < icon_tile_height; j++)
  445.                         {
  446.                             for (k = 0; k < rgb53a_icon_tile_width; k++)
  447.                             {
  448.                                 for (l = 0; l < 4; l++)
  449.                                 {
  450.                                     for (m = 0; m < 4; m++)
  451.                                     {
  452.                                         out_i = (k * 4) + (j * GC_ICON_WIDTH * 4) + (GC_ICON_WIDTH * l) + l;
  453.                                         if (((uint16_t *)input_pixel)[raw_i = (k * 16) + (j * GC_ICON_WIDTH * 4) + (l * 4) + m] & 0x8000)
  454.                                         {
  455.                                             t_icon_pixel_data[out_i].red = Convert5To8(((((uint16_t *)input_pixel)[raw_i] >> 10) & 0x1F));
  456.                                             t_icon_pixel_data[out_i].green = Convert5To8(((((uint16_t *)input_pixel)[raw_i] >> 5) & 0x1F));
  457.                                             t_icon_pixel_data[out_i].blue = Convert5To8((((uint16_t *)input_pixel)[raw_i] & 0x1F));
  458.                                             t_icon_pixel_data[out_i].alpha = 0xFF;
  459.                                         }
  460.                                         else
  461.                                         {
  462.                                             t_icon_pixel_data[out_i].alpha = Convert3To8((((uint16_t *)input_pixel)[raw_i] >> 12) & 0x7);
  463.                                             t_icon_pixel_data[out_i].red = Convert4To8((((uint16_t *)input_pixel)[raw_i] >> 8) & 0xF);
  464.                                             t_icon_pixel_data[out_i].green = Convert4To8((((uint16_t *)input_pixel)[raw_i] >> 4) & 0xF);
  465.                                             t_icon_pixel_data[out_i].blue = Convert4To8(((uint16_t *)input_pixel)[raw_i] & 0xF);
  466.                                         }
  467.                                     }
  468.                                 }
  469.                             }
  470.                         }
  471.                         for (j = 0; j < GC_ICON_HEIGHT; j++) memcpy(&(icon_pixel_data[i][j * GC_ICON_WIDTH]), &(t_icon_pixel_data[GC_ICON_PIXEL_COUNT - ((j + 1) * GC_ICON_WIDTH)]), sizeof(Pixel) * GC_ICON_WIDTH);
  472.                         delete[]((uint16_t *)input_pixel);
  473.                     }
  474.                     else fseek(file, GC_ICON_PIXEL_COUNT * sizeof(uint16_t), SEEK_CUR);
  475.                     break;
  476.                 case DirEntry::ICON_FORMAT_CI8_UNIQUE_PALETTE:
  477.                     try
  478.                     {
  479.                         input_pixel = new uint8_t[GC_ICON_PIXEL_COUNT];
  480.                     }
  481.                     catch (...)
  482.                     {
  483.                         input_pixel = NULL;
  484.                     }
  485.                     if (input_pixel)
  486.                     {
  487.                         fread(input_pixel, sizeof(uint8_t), GC_ICON_PIXEL_COUNT, file);
  488.                         fread(palette, sizeof(uint16_t), GC_PALETTE_COUNT, file);
  489.                         for (j = 0; j < GC_PALETTE_COUNT; j++) (((uint8_t *)(&(((uint16_t *)palette)[j])))[0] ^= (((uint8_t *)(&(((uint16_t *)palette)[j])))[1] ^= (((uint8_t *)(&(((uint16_t *)palette)[j])))[0] ^= ((uint8_t *)(&(((uint16_t *)palette)[j])))[1])));
  490.                         for (j = 0; j < icon_tile_height; j++)
  491.                         {
  492.                             for (k = 0; k < ci8_icon_tile_width; k++)
  493.                             {
  494.                                 for (l = 0; l < 4; l++)
  495.                                 {
  496.                                     for (m = 0; m < 8; m++)
  497.                                     {
  498.                                         out_i = (k * 8) + (j * GC_ICON_WIDTH * 4) + (GC_ICON_WIDTH * l) + m;
  499.                                         palette_index = (int)(((uint8_t *)input_pixel)[(k * 32) + (j * GC_ICON_WIDTH * 4) + (l * 8) + m]);
  500.                                         if (palette[palette_index] & 0x8000)
  501.                                         {
  502.                                             t_icon_pixel_data[out_i].red = Convert5To8(((palette[palette_index] >> 10) & 0x1F));
  503.                                             t_icon_pixel_data[out_i].green = Convert5To8(((palette[palette_index] >> 5) & 0x1F));
  504.                                             t_icon_pixel_data[out_i].blue = Convert5To8((palette[palette_index] & 0x1F));
  505.                                             t_icon_pixel_data[out_i].alpha = 0xFF;
  506.                                         }
  507.                                         else
  508.                                         {
  509.                                             t_icon_pixel_data[out_i].alpha = Convert3To8((palette[palette_index] >> 12) & 0x7);
  510.                                             t_icon_pixel_data[out_i].red = Convert4To8((palette[palette_index] >> 8) & 0xF);
  511.                                             t_icon_pixel_data[out_i].green = Convert4To8((palette[palette_index] >> 4) & 0xF);
  512.                                             t_icon_pixel_data[out_i].blue = Convert4To8(palette[palette_index] & 0xF);
  513.                                         }
  514.                                     }
  515.                                 }
  516.                             }
  517.                         }
  518.                         for (j = 0; j < GC_ICON_HEIGHT; j++) memcpy(&(icon_pixel_data[i][j * GC_ICON_WIDTH]), &(t_icon_pixel_data[GC_ICON_PIXEL_COUNT - ((j + 1) * GC_ICON_WIDTH)]), sizeof(Pixel) * GC_ICON_WIDTH);
  519.                         delete[]((uint8_t *)input_pixel);
  520.                     }
  521.                     else fseek(file, GC_ICON_PIXEL_COUNT * sizeof(uint8_t), SEEK_CUR);
  522.                     break;
  523.                 }
  524.             }
  525.             fread(palette, sizeof(uint16_t), GC_PALETTE_COUNT, file);
  526.             for (i = 0; i < GC_PALETTE_COUNT; i++) (((uint8_t *)(&(((uint16_t *)palette)[i])))[0] ^= (((uint8_t *)(&(((uint16_t *)palette)[i])))[1] ^= (((uint8_t *)(&(((uint16_t *)palette)[i])))[0] ^= ((uint8_t *)(&(((uint16_t *)palette)[i])))[1])));
  527.             fseek(file, icon_pos, SEEK_SET);
  528.             for (i = 0; i < 8; i++)
  529.             {
  530.                 switch (dir_entry->GetIconFormat(i))
  531.                 {
  532.                 case DirEntry::ICON_FORMAT_CI8_REUSE_PALETTE:
  533.                     try
  534.                     {
  535.                         input_pixel = new uint16_t[GC_ICON_PIXEL_COUNT];
  536.                     }
  537.                     catch (...)
  538.                     {
  539.                         input_pixel = NULL;
  540.                     }
  541.                     if (input_pixel)
  542.                     {
  543.                         fread(input_pixel, sizeof(uint8_t), GC_ICON_PIXEL_COUNT, file);
  544.                         for (j = 0; j < icon_tile_height; j++)
  545.                         {
  546.                             for (k = 0; k < ci8_icon_tile_width; k++)
  547.                             {
  548.                                 for (l = 0; l < 4; l++)
  549.                                 {
  550.                                     for (m = 0; m < 8; m++)
  551.                                     {
  552.                                         out_i = (k * 8) + (j * GC_ICON_WIDTH * 4) + (GC_ICON_WIDTH * l) + m;
  553.                                         palette_index = (int)(((uint8_t *)input_pixel)[(k * 32) + (j * GC_ICON_WIDTH * 4) + (l * 8) + m]);
  554.                                         if (palette[palette_index] & 0x8000)
  555.                                         {
  556.                                             t_icon_pixel_data[out_i].red = Convert5To8(((palette[palette_index] >> 10) & 0x1F));
  557.                                             t_icon_pixel_data[out_i].green = Convert5To8(((palette[palette_index] >> 5) & 0x1F));
  558.                                             t_icon_pixel_data[out_i].blue = Convert5To8((palette[palette_index] & 0x1F));
  559.                                             t_icon_pixel_data[out_i].alpha = 0xFF;
  560.                                         }
  561.                                         else
  562.                                         {
  563.                                             t_icon_pixel_data[out_i].alpha = Convert3To8((palette[palette_index] >> 12) & 0x7);
  564.                                             t_icon_pixel_data[out_i].red = Convert4To8((palette[palette_index] >> 8) & 0xF);
  565.                                             t_icon_pixel_data[out_i].green = Convert4To8((palette[palette_index] >> 4) & 0xF);
  566.                                             t_icon_pixel_data[out_i].blue = Convert4To8(palette[palette_index] & 0xF);
  567.                                         }
  568.                                     }
  569.                                 }
  570.                             }
  571.                         }
  572.                         for (j = 0; j < GC_ICON_HEIGHT; j++) memcpy(&(icon_pixel_data[i][j * GC_ICON_WIDTH]), &(t_icon_pixel_data[GC_ICON_PIXEL_COUNT - ((j + 1) * GC_ICON_WIDTH)]), sizeof(Pixel) * GC_ICON_WIDTH);
  573.                         delete[]((uint8_t *)input_pixel);
  574.                     }
  575.                     break;
  576.                 case DirEntry::ICON_FORMAT_RGB5A3:
  577.                     fseek(file, GC_ICON_PIXEL_COUNT * sizeof(uint16_t), SEEK_CUR);
  578.                     break;
  579.                 case DirEntry::ICON_FORMAT_CI8_UNIQUE_PALETTE:
  580.                     fseek(file, GC_ICON_PIXEL_COUNT * sizeof(uint8_t), SEEK_CUR);
  581.                     break;
  582.                 }
  583.             }
  584.             fseek(file, current_pos, SEEK_SET);
  585.         }
  586.     }
  587. }
  588.  
  589. __fastcall GCMem::GameData::~GameData()
  590. {
  591.     delete dir_entry;
  592.     dir_entry = NULL;
  593. }
  594.  
  595. bool __fastcall GCMem::GameData::IsValid()
  596. {
  597.     return dir_entry ? dir_entry->IsValid() : false;
  598. }
  599.  
  600. GCMem::DirEntry &__fastcall GCMem::GameData::GetDirEntry()
  601. {
  602.     return *dir_entry;
  603. }
  604.  
  605. std::string __fastcall GCMem::GameData::GetComment1()
  606. {
  607.     return comment1;
  608. }
  609.  
  610. std::string __fastcall GCMem::GameData::GetComment2()
  611. {
  612.     return comment2;
  613. }
  614.  
  615. void __fastcall GCMem::GameData::StoreBannerAsTGA(std::string file_name)
  616. {
  617.     FILE *file = NULL;
  618.     fopen_s(&file, file_name.c_str(), "wb");
  619.     if (file)
  620.     {
  621.         fwrite(tga_header, sizeof(char), TGA_CMP_HEADER_LEN, file);
  622.         fwrite(&banner_ihdr_chunk_buffer, sizeof(IHDR_chunk), 1, file);
  623.         fwrite(banner_pixel_data, sizeof(Pixel), GC_BANNER_PIXEL_COUNT, file);
  624.         fclose(file);
  625.     }
  626. }
  627.  
  628. void __fastcall GCMem::GameData::StoreIconAsTGA(std::string file_name, uint8_t index)
  629. {
  630.     FILE *file = NULL;
  631.     if (index < 8)
  632.     {
  633.         fopen_s(&file, file_name.c_str(), "wb");
  634.         if (file)
  635.         {
  636.             fwrite(tga_header, sizeof(char), TGA_CMP_HEADER_LEN, file);
  637.             fwrite(&icon_ihdr_chunk_buffer, sizeof(IHDR_chunk), 1, file);
  638.             fwrite(icon_pixel_data[0], sizeof(Pixel), GC_ICON_PIXEL_COUNT, file);
  639.             fclose(file);
  640.         }
  641.     }
  642. }
  643.  
  644. __fastcall GCMem::GCMem(std::string file_name)
  645. {
  646.     FILE *file = NULL;
  647.     long long file_size;
  648.     int i;
  649.     GameData *game_data = NULL;
  650.     std::vector<GameData *>::iterator game_it;
  651.     fopen_s(&file, file_name.c_str(), "rb");
  652.     if (file)
  653.     {
  654.         fseek(file, 0, SEEK_END);
  655.         file_size = _ftelli64(file);
  656.         fseek(file, 0, SEEK_SET);
  657.         if (file_size == 16777216)
  658.         {
  659.             fseek(file, 0x2000, SEEK_SET);
  660.             for (i = 0; i < 0x80; i++)
  661.             {
  662.                 if (game_data) game_data->GetDirEntry().Read(file);
  663.                 else
  664.                 {
  665.                     try
  666.                     {
  667.                         game_data = new GCMem::GameData(file);
  668.                     }
  669.                     catch (...)
  670.                     {
  671.                         game_data = NULL;
  672.                     }
  673.                     if (game_data == NULL) break;
  674.                 }
  675.                 if (game_data->IsValid())
  676.                 {
  677.                     try
  678.                     {
  679.                         games.push_back(game_data);
  680.                         game_data = NULL;
  681.                     }
  682.                     catch (...)
  683.                     {
  684.                         delete game_data;
  685.                         game_data = NULL;
  686.                         for (game_it = games.begin(); game_it != games.end(); game_it++) delete (*game_it);
  687.                         games.clear();
  688.                     }
  689.                 }
  690.             }
  691.         }
  692.         fclose(file);
  693.     }
  694. }
  695.  
  696. __fastcall GCMem::~GCMem()
  697. {
  698.     std::vector<GameData *>::iterator game_it;
  699.     for (game_it = games.begin(); game_it != games.end(); game_it++) delete (*game_it);
  700.     games.clear();
  701. }
  702.  
  703. GCMem::GameData &__fastcall GCMem::Game(uint8_t index)
  704. {
  705.     if (index >= games.size()) throw -1;
  706.     return (*(games[index]));
  707. }
  708.  
  709. uint8_t __fastcall GCMem::GameCount()
  710. {
  711.     return ((uint8_t)(games.size()));
  712. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement