void applyIPSpatch(const char* ips_path, long ips_size, unsigned char* base, int base_len) { FILE* f = NULL; if ((f = fopen(ips_path, "rb")) == NULL) return; char buf[6]; memset(buf, 0, sizeof buf); fread(buf, 1, 5, f); if (strcmp(buf, IPS_SIGNATURE)) { fclose(f); return; } int Offset, Size; UINT8* mem8 = NULL; UINT8 ch = 0; int bRLE = 0; while (!feof(f)) { // read patch address offset fread(buf, 1, 3, f); buf[3] = 0; if (strcmp(buf, IPS_TAG_EOF) == 0) break; Offset = BYTE3_TO_UINT(buf); // read patch length fread(buf, 1, 2, f); Size = BYTE2_TO_UINT(buf); bRLE = (Size == 0); if (bRLE) { fread(buf, 1, 2, f); Size = BYTE2_TO_UINT(buf); ch = fgetc(f); } #if 0 if ((base_size > 0) && (Size + Offset > base_size)) break; // out of range #endif while (Size--) { mem8 = base + Offset; Offset++; *mem8 = bRLE ? ch : fgetc(f); } } fclose(f); }
static void PatchFile(const char* ips_path, UINT8* base) { char buf[6]; FILE* f = NULL; int Offset, Size; UINT8* mem8 = NULL; if (NULL == (f = fopen(ips_path, "rb"))) return; memset(buf, 0, sizeof buf); fread(buf, 1, 5, f); if (strcmp(buf, IPS_SIGNATURE)) { return; } else { UINT8 ch = 0; int bRLE = 0; while (!feof(f)) { // read patch address offset fread(buf, 1, 3, f); buf[3] = 0; if (strcmp(buf, IPS_TAG_EOF) == 0) break; Offset = BYTE3_TO_UINT(buf); // read patch length fread(buf, 1, 2, f); Size = BYTE2_TO_UINT(buf); bRLE = (Size == 0); if (bRLE) { fread(buf, 1, 2, f); Size = BYTE2_TO_UINT(buf); ch = fgetc(f); } while (Size--) { mem8 = base + Offset; Offset++; *mem8 = bRLE ? ch : fgetc(f); } } } fclose(f); }
/** * Reads a record from the patch file. * * This code both detects, and reads the next record in the * filePointer at the given location and writes the results into the * patchData struct supplied. * * @param struct *patchData A pointer to a patchData struct that the * information will be written to. * @param FILE *filePointer a pointer to the patch file being read. * * @return int: 1 if successful, 0 otherwise. */ int IPSReadRecord(struct patchData *patch, FILE *filePointer) { unsigned char offset[3], size[2]; if(fread(&offset, BYTE, 3, filePointer) && fread(&size, BYTE, 2, filePointer)) { /* Fix linear reads */ patch->size = BYTE2_TO_UINT(size); patch->offset = BYTE3_TO_UINT(offset); if(patch->size == 0) { return IPSReadRLE(patch, filePointer); } patch->data = (char*)malloc(patch->size + 1); return fread(patch->data, BYTE, patch->size, filePointer); } return 0; }
/** * Read an RLE-Encoded patch... * * RLE patches are simple patches with a single byte repeating a * specified quantity of times. The first 16 bits are the size of the * patch, or the number of times to repeat the insert, and the value * immediately succeeding this number is the patch character itself... * * @param struct patchData *patch A patch struct pointer holding the * offset, the size, and the data... * @param FILE *filePointer a file pointer to the current location in * the patch file. * * @return Returns 1 on success, 0 on failure. */ int IPSReadRLE(struct patchData *patch, FILE *filePointer) { char size[2]; if(fread(&size, BYTE, 2, filePointer)) { unsigned int count; char data = '\0'; patch->size = BYTE2_TO_UINT(size); if(!fread(&data, BYTE, 1, filePointer)) { return 0; } patch->data = (char*)malloc((patch->size * sizeof(char)) + 1); for(count = 0; count < patch->size; count++) { patch->data[count] = (char)data; } return 1; } return 0; }