int CheatLoad(const char *filename) { FILE *fp; int i; char id[4]; char desc[256]; IOCheck_struct check = { 0, 0 }; if (!filename) return -1; if ((fp = fopen(filename, "rb")) == NULL) return -1; yread(&check, (void *)id, 1, 4, fp); if (strncmp(id, "YCHT", 4) != 0) { fclose(fp); return -2; } CheatClearCodes(); yread(&check, (void *)&numcheats, sizeof(int), 1, fp); #ifndef WORDS_BIGENDIAN DoubleWordSwap(numcheats); #endif if (numcheats >= cheatsize) { cheatlist = realloc(cheatlist, sizeof(cheatlist_struct) * (cheatsize * 2)); memset((void *)cheatlist, 0, sizeof(cheatlist_struct) * (cheatsize * 2)); cheatsize *= 2; } for(i = 0; i < numcheats; i++) { u8 descsize; yread(&check, (void *)&cheatlist[i].type, sizeof(int), 1, fp); yread(&check, (void *)&cheatlist[i].addr, sizeof(u32), 1, fp); yread(&check, (void *)&cheatlist[i].val, sizeof(u32), 1, fp); yread(&check, (void *)&descsize, sizeof(u8), 1, fp); yread(&check, (void *)desc, sizeof(char), descsize, fp); CheatChangeDescriptionByIndex(i, desc); yread(&check, (void *)&cheatlist[i].enable, sizeof(int), 1, fp); #ifndef WORDS_BIGENDIAN DoubleWordSwap(cheatlist[i].type); DoubleWordSwap(cheatlist[i].addr); DoubleWordSwap(cheatlist[i].val); DoubleWordSwap(cheatlist[i].enable); #endif } fclose (fp); return 0; }
int insert_plot(const char *input_filename, const char *out_filename) { uint32_t offsets[2]; int ret; unsigned char *text_buffer; FILE *fp; uint32_t section_offset=0, t1t2size=0; if ((text_buffer = (unsigned char *)calloc(0x800000, sizeof(unsigned char))) == NULL) { printf("Error allocating memory\n"); return -2; } ret=insert_section(input_filename, text_buffer, §ion_offset, t1t2size, offsets); if ((fp = fopen(out_filename, "wb")) == NULL) { printf("Error opening %s for writing\n", out_filename); free(text_buffer); return -3; } fwrite((void *)text_buffer, 1, DoubleWordSwap(offsets[1]), fp); fclose(fp); return 0; }
int CheatSave(const char *filename) { FILE *fp; int i; int num; IOCheck_struct check = { 0, 0 }; if (!filename) return -1; if ((fp = fopen(filename, "wb")) == NULL) return -1; fprintf(fp, "YCHT"); num = numcheats; #ifndef WORDS_BIGENDIAN DoubleWordSwap(num); #endif ywrite(&check, (void *)&num, sizeof(int), 1, fp); for(i = 0; i < numcheats; i++) { u8 descsize; cheatlist_struct cheat; memcpy(&cheat, &cheatlist[i], sizeof(cheatlist_struct)); #ifndef WORDS_BIGENDIAN DoubleWordSwap(cheat.type); DoubleWordSwap(cheat.addr); DoubleWordSwap(cheat.val); DoubleWordSwap(cheat.enable); #endif ywrite(&check, (void *)&cheat.type, sizeof(int), 1, fp); ywrite(&check, (void *)&cheat.addr, sizeof(u32), 1, fp); ywrite(&check, (void *)&cheat.val, sizeof(u32), 1, fp); descsize = (u8)strlen(cheatlist[i].desc)+1; ywrite(&check, (void *)&descsize, sizeof(u8), 1, fp); ywrite(&check, (void *)cheatlist[i].desc, sizeof(char), descsize, fp); ywrite(&check, (void *)&cheat.enable, sizeof(int), 1, fp); } fclose (fp); return 0; }
int dump_d00(const char *input_filename, const char *output_dir) { char drive[_MAX_DRIVE], dir[_MAX_DIR], fn[_MAX_FNAME]; FILE *input_fp; int done = 0; unsigned long num_offsets=0; unsigned long i; pointer_struct *offset_data; // Main program if (fopen_s(&input_fp, input_filename, "rb") != 0) { printf("Could not open input file\n"); return -1; } // figure out how many text sections to dump fread((void *)&num_offsets, 4, 1, input_fp); num_offsets = DoubleWordSwap(num_offsets); // printf("number of offsets = %x - %d\n", num_offsets, num_offsets); // allocate and grab offset list if ((offset_data = (pointer_struct *)malloc(sizeof(pointer_struct) * num_offsets)) == NULL) { printf("Unable to allocate offset/size list\n"); fclose(input_fp); return -2; } for (i = 0; i < num_offsets; i++) { fread((void *)&offset_data[i].offset, 4, 1, input_fp); fread((void *)&offset_data[i].size, 4, 1, input_fp); offset_data[i].offset = DoubleWordSwap(offset_data[i].offset) * 0x800; offset_data[i].size = DoubleWordSwap(offset_data[i].size); // printf("offset_data[%d] offset = %08x size = %08x\n", i, offset_data[i].offset, offset_data[i].size); } for (i = 0; i < num_offsets; i++) { unsigned long temp_long=0; unsigned long temp_long2=0; // figure out the absolute offset of the text section fseek(input_fp, offset_data[i].offset, SEEK_SET); fread((void *)&temp_long, 4, 1, input_fp); temp_long = DoubleWordSwap(temp_long); fseek(input_fp, offset_data[i].offset + temp_long + 0x40, SEEK_SET); fread((void *)&temp_long2, 4, 1, input_fp); temp_long2 = DoubleWordSwap(temp_long2); // horray! Now we know the absolute offset of the text section! offset_data[i].offset += (temp_long + temp_long2); // Now grab the text section's size fseek(input_fp, offset_data[i].offset, SEEK_SET); fread((void *)&offset_data[i].size, 4, 1, input_fp); offset_data[i].size = DoubleWordSwap(offset_data[i].size); } // start a for loop that goes through each offset for (i = 0; i < num_offsets; i++) { char output_filename[_MAX_PATH]; _splitpath(output_dir, drive, dir, fn, NULL); strcat(dir, fn); // generate output filename sprintf(fn, "scen%d\0", i + 1); _makepath(output_filename, drive, dir, fn, ".sjs"); dump_section(input_fp, &offset_data[i], output_filename); } fclose(input_fp); free(offset_data); return 0; }
int dump_fntsys(const char *filename, uint32_t addr, textoffindex_struct *toi, uint32_t num_toi, char *out_dir) { uint32_t i, j; long size; unsigned char *buf; FILE *fp = fopen(filename, "rb"), *output_fp; if (fp) { fseek(fp, 0, SEEK_END); size = ftell(fp); fseek(fp, 0, SEEK_SET); if ((buf = (unsigned char *)malloc(size)) == NULL) { printf("Error allocating memory\n"); return -1; } fread((void *)buf, 1, size, fp); fclose(fp); for (i = 0; i < num_toi; i++) { long end; char drive[_MAX_DRIVE], dir[_MAX_DIR], fn[_MAX_FNAME]; char output_filename[_MAX_PATH]; uint32_t *off=buf; uint32_t tbl_off, text_off, num_tbl; _splitpath(out_dir, drive, dir, fn, NULL); strcat(dir, fn); _splitpath(filename, NULL, NULL, fn, NULL); itoa(i+1, fn+strlen(fn), 10); _makepath(output_filename, drive, dir, fn, ".sjs"); printf("Writing %s...", output_filename); if ((output_fp = fopen(output_filename, "wt")) == NULL) { printf("Error opening %s for writing\n", output_filename); fclose(fp); return -2; } tbl_off=(DoubleWordSwap(off[toi[i].tbl_index])-addr); text_off=(DoubleWordSwap(off[toi[i].text_index])-addr); num_tbl=(text_off-tbl_off)/2; if (i != num_toi-1) end = (DoubleWordSwap(off[toi[i+1].tbl_index])-addr); else end = size-1; fprintf(output_fp, "Langrisser III dumper [0x%x to 0x%x]\n\n", text_off, end); fprintf(output_fp, "Cyber Warrior X\n"); fprintf(output_fp, "\n"); for (j = 0; j < num_tbl; j++) { uint32_t offset = text_off+(WordSwap(*(uint16_t *)(buf+tbl_off+(j*2)))*2); unsigned long counter=0; for (;;) { int data_size; unsigned char data[256]; int ret = Table_Match_Code_To_Char(trans_table, buf + offset + counter, data, &data_size); if (ret > 0) { fwrite((void *)data, data_size, 1, output_fp); counter += ret; } else { if (buf[offset + counter] == 0xFF && buf[offset + counter + 1] == 0xFF) { // end of a string fprintf(output_fp, "<$FFFF>\n"); break; } else { // just insert the character as <$hex> //printf("can't figure out character %02X%02X%02X%02X\n", temp_buffer[offset + counter], temp_buffer[offset + counter + 1], temp_buffer[offset + counter + 2], temp_buffer[offset + counter + 3]); fprintf(output_fp, "<$%02X>", buf[offset + counter]); } } } } fclose(output_fp); printf("done.\n"); } free(buf); } return 0; }
int insert_section(const char *filename, unsigned char *text_buffer, uint32_t *section_offset, uint32_t t1t2size, uint32_t *offsets) { int line_counter=0; uint16_t *tbl; FILE *fp; char text[2048], text2[512]; uint32_t section_size; int text_counter; uint32_t offset, size; unsigned char buf[0x20000], *bufp; int j,k; if ((fp = fopen(filename, "rt")) == NULL) return -1; printf("Inserting %s...", filename); tbl = (uint16_t *)(text_buffer+section_offset[0]+t1t2size+4); // Bypass header if it exists for (;;) { if (fscanf(fp, "%[^\n]\n", text) != 1) break; line_counter++; if (strstr(text, "Langrisser III dumper")) { if (fscanf(fp, "%[^\n]\n", text) != 1) break; line_counter++; if (strstr(text, "Cyber Warrior X")) { if (fscanf(fp, "%[^\n]\n", text) == 1) line_counter++; break; } } else if (strlen(text) != 0) break; } section_size = 0; text_counter = 0; size = 0; offset = 0; bufp=buf; for(;;) { if (strlen(text) > 0) { for (;;) { char *p = strrchr(text, '<'); if (p == NULL) { printf("Error in %s on line %d parsing script file: Missing or invalid end tag. \"%s\"\n", filename, line_counter, text); return -3; } sscanf(p+2, "%[^>]>", text2); if (strcmp(text2, "FFFE") != 0 && strcmp(text2, "FFFF") != 0) { // Fetch another line if (fscanf(fp, "%[^\n]\n", text2) == 1) { strcat(text, text2); line_counter++; } } else break; } for (j = 0; j < (int)strlen(text);) { if (isascii(text[j])) { if (text[j] == '<' && text[j+1] == '$') { if (sscanf(text+j+2, "%[^>]>", text2) != 1) { printf("Error in %s on line %d parsing script file: Missing '>'\n", filename, line_counter); return -3; } for (k = 0; k < (int)strlen(text2); k+=2) { char tmp[3] = { text2[k], text2[k+1], '\0' }; bufp[0] = (unsigned char)strtol(tmp, NULL, 16); bufp++; size++; } if (bufp[-2] == 0xF7) { tbl[text_counter] = offset; text_counter++; section_size += size; offset += size; size = 0; } char *p = strchr(text+j, '>'); if (p == NULL) { printf("Error in %s on line %d parsing script file: Missing '>'\n", filename, line_counter); return -3; } j += p-(text+j)+1; } else if (text[j] == '[' && text[j+1] == 'd' && memcmp(text+j, "[diehardt's name]", 17) == 0) { unsigned char data[] = { 0xF6, 0x00, 0x00, 0x00 }; memcpy(bufp, data, sizeof(data)); j += 17; bufp += sizeof(data); size += sizeof(data); } else { bufp[0] = text[j]; bufp++; j++; size++; } } else { int tmp; int ret; if ((ret = Table_Match_Char_To_Code(trans_table, (unsigned char *)text+j, strlen(text)-j, bufp, &tmp)) != 0) { j += ret; bufp += tmp; size += tmp; } else { printf("Warning on %s on line %d parsing script file: Unknown character 0x%02X\n", filename, line_counter, (unsigned char)text[j]); bufp[0] = text[j]; bufp++; j++; size++; } } } if (size % 2 == 1) { bufp[0] = 0xFF; bufp++; size++; } tbl[text_counter] = offset; text_counter++; section_size += size; offset += size; size = 0; } // read next line of text if (fscanf(fp, "%[^\n]\n", text) != 1) break; line_counter++; } // 4 byte align if (((text_counter*2)+section_size) % 4 != 0) { int n=4 - ((text_counter*2)+section_size) % 4; memset(bufp, 0xFF, n); bufp+=n; section_size+=n; } // Adjust table entries for (j = 0; j < text_counter; j++) tbl[j] = WordSwap(4+(text_counter*2)+tbl[j]); *(uint32_t *)(text_buffer+section_offset[0]+t1t2size) = DoubleWordSwap(4+(text_counter*2)+section_size); memcpy(text_buffer+section_offset[0]+t1t2size+4+(text_counter*2), buf, section_size); // Update header offsets[0] = DoubleWordSwap(section_offset[0]/2048); offsets[1] = DoubleWordSwap(t1t2size+4+(text_counter*2)+section_size); section_offset[0] += t1t2size+4+(text_counter*2)+section_size; if (section_offset[0] & 0x7FF) { section_offset[0] += 0x800; section_offset[0] &= ~0x7FF; } section_size = 0; fclose(fp); printf("done.\n"); return 0; }
int insert_d00(const char *orig_filename, const char *input_files, const char *out_filename) { char filename[_MAX_PATH]; int i; FILE *origfp, *outfp; uint32_t section_offset=0x800; unsigned char *text_buffer; //uint16_t *tbl; uint32_t offset, size; uint32_t *offsets; //int text_counter; int num_sections; int ret; origfp = fopen(orig_filename, "rb"); if (origfp == NULL) { printf("Error opening %s for reading\n", out_filename); return -1; } if ((text_buffer = (unsigned char *)calloc(0x800000, sizeof(unsigned char))) == NULL) { printf("Error allocating memory\n"); fclose(origfp); return -2; } offsets = (uint32_t *)(text_buffer+4); fread((void *)&num_sections, 4, 1, origfp); *((uint32_t *)text_buffer) = num_sections; num_sections = DoubleWordSwap(num_sections); for (i = 0; i < num_sections; i++) { // Section: // 0x00000000: table1(each entry is 4 bytes), first entry is offset to second table // 0x????????: data for table1 here // 0x????????: table2(each entry is 4 bytes). Last entry in table is offset to table 3 // 0x????????: data for table 2 // 0x????????: table 3. First entry is size of table 3 + table 3 data(text strings)(4 bytes), after that it's offsets to strings(2 bytes per entry), after that strings. uint32_t tbl1offset, tbl2offset, t1t2size; fseek(origfp, 4+(i*8), SEEK_SET); fread((void *)&offset, 4, 1, origfp); offset = DoubleWordSwap(offset); fread((void *)&size, 4, 1, origfp); size = DoubleWordSwap(size); fseek(origfp, offset*2048, SEEK_SET); // Table 1 fread((void *)&tbl1offset, 4, 1, origfp); tbl1offset = DoubleWordSwap(tbl1offset); fseek(origfp, (offset*2048)+tbl1offset+(16*4), SEEK_SET); // Table 2 fread((void *)&tbl2offset, 4, 1, origfp); tbl2offset = DoubleWordSwap(tbl2offset); t1t2size = tbl1offset+tbl2offset; // Backup table 1 and table 1 data, table 2 and table 2 data fseek(origfp, offset*2048, SEEK_SET); fread(text_buffer+section_offset, 1, t1t2size, origfp); sprintf(filename, input_files, i+1); ret = insert_section(filename, text_buffer, §ion_offset, t1t2size, offsets+(i*2)); if (ret == -1) { fseek(origfp, offset*2048, SEEK_SET); fread(text_buffer+section_offset, 1, size, origfp); offsets[(i*2)] = DoubleWordSwap(section_offset/2048); offsets[(i*2)+1] = DoubleWordSwap(size); section_offset += size; if (section_offset & 0x7FF) { section_offset += 0x800; section_offset &= ~0x7FF; } ret = 0; } if (ret != 0) { fclose(origfp); free(text_buffer); return ret; } } if ((outfp = fopen(out_filename, "wb")) == NULL) { printf("Error opening %s for writing\n", out_filename); ret = -1; } else { fwrite((void *)text_buffer, 1, section_offset, outfp); fflush(outfp); ret = 0; } if (origfp) fclose(origfp); if (outfp) fclose(outfp); if (text_buffer) free(text_buffer); return ret; }