|
| 1 | +#include <stdio.h> |
| 2 | +#include <stdlib.h> |
| 3 | +#include <string.h> |
| 4 | + |
| 5 | +#define BLOCK 8192 |
| 6 | +#define GCIHEAD 64 |
| 7 | +#define GCICOMMENT 0x520 |
| 8 | + |
| 9 | +#define be16(x) ((((x)>>8)&0xFF)|(((x)<<8))&0xFF00) |
| 10 | +#define be32(x) (((x)<<24)|(((x)>>8)&0xFF00)|(((x)<<8)&0xFF0000)|((x)>>24)) |
| 11 | + |
| 12 | +#define CLIMAGIC "CL@MAG" |
| 13 | + |
| 14 | +#define myfree(x) if(x!=NULL)free(x) |
| 15 | + |
| 16 | +typedef unsigned short u16; |
| 17 | + |
| 18 | +int main (int argc, char *argv[]) { |
| 19 | + FILE * pFile; |
| 20 | + long gcisize; |
| 21 | + long clisize; |
| 22 | + char * gcibuffer; |
| 23 | + char * clibuffer; |
| 24 | + size_t result; |
| 25 | + char *magic = CLIMAGIC; |
| 26 | + |
| 27 | + char outpath[256]; |
| 28 | + char clipath[256]; |
| 29 | + |
| 30 | + printf("\nCLI Embedder 0.1 by suloku 15'\n"); |
| 31 | + printf("******************************\n\n"); |
| 32 | + |
| 33 | + if(argc != 2){ |
| 34 | + printf("This program will embedd a cli file into a gci file created with dol2gci.\n\n"); |
| 35 | + printf("Usage: cliembed.exe mydol.gci\n"); |
| 36 | + printf(" or drag and drop to executable file\n"); |
| 37 | + printf("\nCli file must have the same name and be in the same path as gci file:\n\tswiss.gci and swiss.cli"); |
| 38 | + printf("\n\nPress enter to continue..."); |
| 39 | + getchar(); |
| 40 | + exit(-1); |
| 41 | + } |
| 42 | + |
| 43 | + //Prepare |
| 44 | + strcpy(outpath, argv[1]); |
| 45 | + outpath[strlen(outpath)-4] = '\0'; |
| 46 | + strcat(outpath, "-CLI.gci"); |
| 47 | + |
| 48 | + strcpy(clipath, argv[1]); |
| 49 | + clipath[strlen(clipath)-3] = '\0'; |
| 50 | + strcat(clipath, "cli"); |
| 51 | + |
| 52 | + printf("Embedding %s into %s\n", clipath, argv[1]); |
| 53 | + printf("\nOutfile: %s\n\n", outpath); |
| 54 | + |
| 55 | + //READ DOL |
| 56 | + pFile = fopen ( argv[1] , "rb" ); |
| 57 | + if (pFile==NULL) {printf ("Can't open %s", argv[1]); printf("\n\nPress enter to continue..."); getchar(); exit (1);} |
| 58 | + // obtain file size: |
| 59 | + fseek (pFile , 0 , SEEK_END); |
| 60 | + gcisize = ftell (pFile); |
| 61 | + rewind (pFile); |
| 62 | + // allocate memory to contain the whole file: |
| 63 | + gcibuffer = (char*) malloc (sizeof(char)*gcisize); |
| 64 | + if (gcibuffer == NULL) {printf ("Memory error"); printf("\n\nPress enter to continue..."); getchar(); exit (2);} |
| 65 | + // copy the file into the buffer: |
| 66 | + result = fread (gcibuffer,1,gcisize,pFile); |
| 67 | + if (result != gcisize) {printf ("Reading error"); printf("\n\nPress enter to continue..."); getchar(); exit (3);} |
| 68 | + /* the whole file is now loaded in the memory buffer. */ |
| 69 | + // terminate |
| 70 | + fclose (pFile); |
| 71 | + |
| 72 | + //READ CLI |
| 73 | + pFile = fopen ( clipath , "rb" ); |
| 74 | + if (pFile==NULL) {printf ("Can't open %s", clipath); printf("\n\nPress enter to continue..."); getchar(); exit (1);} |
| 75 | + |
| 76 | + // obtain file size: |
| 77 | + fseek (pFile , 0 , SEEK_END); |
| 78 | + clisize = ftell (pFile); |
| 79 | + rewind (pFile); |
| 80 | + |
| 81 | + // allocate memory to contain the whole file: |
| 82 | + clibuffer = (char*) malloc (sizeof(char)*clisize); |
| 83 | + if (clibuffer == NULL) {printf ("Memory error"); printf("\n\nPress enter to continue..."); getchar(); exit (2);} |
| 84 | + |
| 85 | + // copy the file into the buffer: |
| 86 | + result = fread (clibuffer,1,clisize,pFile); |
| 87 | + if (result != clisize) {printf ("Reading error"); printf("\n\nPress enter to continue..."); getchar(); exit (3);} |
| 88 | + |
| 89 | + /* the whole file is now loaded in the memory buffer. */ |
| 90 | + |
| 91 | + // terminate |
| 92 | + fclose (pFile); |
| 93 | + |
| 94 | + printf ("GCI size: %d bytes (%d blocks)\n", (gcisize-GCIHEAD), !((gcisize-GCIHEAD)%BLOCK)?((gcisize-GCIHEAD)/BLOCK):((gcisize-GCIHEAD)/BLOCK)+1); |
| 95 | + printf ("Cli size: %d bytes\n", clisize); |
| 96 | + |
| 97 | + long offset = 0; |
| 98 | + int i = 0; |
| 99 | + int found = 0; |
| 100 | + char padmagic = 0xCD; |
| 101 | + while(1){ |
| 102 | + if (memcmp(&gcibuffer[offset], &padmagic, 1) == 0 ){ |
| 103 | + //printf("Found pads at %d\n", offset); |
| 104 | + for (i=0; i<16*2;i++){ |
| 105 | + if (memcmp(&gcibuffer[offset+i], &padmagic, 1) != 0){ |
| 106 | + break; |
| 107 | + } |
| 108 | + } |
| 109 | + if (i==((16*2))) found = 1; |
| 110 | + } |
| 111 | + if (found) break; |
| 112 | + if (offset >= gcisize) break; |
| 113 | + offset++; |
| 114 | + } |
| 115 | + if(!found){ |
| 116 | + printf("\nCan't find space (at least 32 0xCD bytes) to embed cli file!"); |
| 117 | + printf("\nDo you want to add 1 block to your gci file? (y/n)"); |
| 118 | + char c; |
| 119 | + |
| 120 | + while (1){ |
| 121 | + c=getchar(); |
| 122 | + getchar(); |
| 123 | + if (c=='y' || c=='Y'){ |
| 124 | + break; |
| 125 | + }else if (c=='n' || c=='N'){ |
| 126 | + printf("\n\nThis gci file doesn't have enough space to embed the cli file.\n\nPress enter to continue..."); |
| 127 | + getchar(); exit (3); |
| 128 | + } |
| 129 | + } |
| 130 | + //User wants to fatten gci file to embed the cli file |
| 131 | + strcpy(outpath, argv[1]); |
| 132 | + outpath[strlen(outpath)-4] = '\0'; |
| 133 | + strcat(outpath, "-fat.gci"); |
| 134 | + printf("\n\nCreating padded gci file at %s\n", outpath); |
| 135 | + |
| 136 | + //Create a pad block |
| 137 | + char* padding = (char*) malloc (sizeof(char)*BLOCK); |
| 138 | + memset (padding, 0xCD, BLOCK); |
| 139 | + //Update gci header to add one block |
| 140 | + u16 blocksize; |
| 141 | + memcpy(&blocksize,gcibuffer+0x38, 2); |
| 142 | + blocksize = be16(blocksize); |
| 143 | + blocksize = blocksize + 1; |
| 144 | + printf("New GCI blocksize: %d\n", blocksize); |
| 145 | + blocksize=be16(blocksize); |
| 146 | + memcpy(gcibuffer+0x38, &blocksize, 2); |
| 147 | + |
| 148 | + //write fatted gci file |
| 149 | + pFile = fopen (outpath, "wb"); |
| 150 | + if (pFile==NULL) {printf ("Can't open %s", outpath); printf("\n\nPress enter to continue..."); getchar(); exit (1);} |
| 151 | + int ret; |
| 152 | + ret = fwrite (gcibuffer , sizeof(char), gcisize, pFile); |
| 153 | + //printf ("Written = %d, expected %d\n", ret, gcisize); |
| 154 | + ret = fwrite (padding , sizeof(char), BLOCK, pFile); |
| 155 | + //printf ("Written = %d, expected %d\n", ret, BLOCK); |
| 156 | + fclose (pFile); |
| 157 | + printf("\n\n%s created! Now use that file with this program to embed the cli file. Remember that the cli file must have the same name as the gci file.\n\n Press enter to continue...", outpath); |
| 158 | + getchar(); |
| 159 | + myfree(padding); |
| 160 | + myfree (gcibuffer); |
| 161 | + myfree (clibuffer); |
| 162 | + return 0; |
| 163 | + } else{ |
| 164 | + printf("GCI pad starts at: %d\n", offset); |
| 165 | + printf("Padding size: %d\n", gcisize-offset); |
| 166 | + int remaining = (gcisize-offset)-clisize-strlen(magic)*2; |
| 167 | + printf("Remaining pad after embed: %d\n", remaining); |
| 168 | + |
| 169 | + if( remaining <= 0){printf ("\nSorry, your CLI file can't fit in this gci file, it is %d bytes too big.", remaining*(-1)); printf("\n\nPress enter to continue..."); getchar(); exit (3);} |
| 170 | + |
| 171 | + //add cli file to dol buffer |
| 172 | + |
| 173 | + memcpy(gcibuffer+gcisize-clisize-strlen(magic)*2, magic, strlen(magic)); |
| 174 | + memcpy(gcibuffer+gcisize-clisize-strlen(magic), clibuffer, clisize); |
| 175 | + memcpy(gcibuffer+gcisize-strlen(magic), magic, strlen(magic)); |
| 176 | + |
| 177 | + printf("Writing cli to gci file...\n"); |
| 178 | + |
| 179 | + pFile = fopen (outpath, "wb"); |
| 180 | + if (pFile==NULL) {printf ("Can't open %s", outpath); printf("\n\nPress enter to continue..."); getchar(); exit (1);} |
| 181 | + fwrite (gcibuffer , sizeof(char), gcisize, pFile); |
| 182 | + fclose (pFile); |
| 183 | + } |
| 184 | + |
| 185 | + myfree (gcibuffer); |
| 186 | + myfree (clibuffer); |
| 187 | + |
| 188 | + printf("\nEmbedding complete! Press enter to continue..."); |
| 189 | + getchar(); |
| 190 | + return 0; |
| 191 | +} |
0 commit comments