#include "ips.h" int8_t IPSOpenPatch(struct IPSPatch *ips, const char *fileName) { char header[5]; size_t nRead; ips->patch = fopen(fileName, "rb"); if(ips->patch == NULL) { return IPS_ERROR; } fseek(ips->patch, 0, SEEK_SET); nRead = fread(header, 1, 5, ips->patch); if(nRead != 5) { return IPS_ERROR_FILE_TYPE; } if((header[0] != 'P') || (header[1] != 'A') || (header[2] != 'T') || (header[3] != 'C') || (header[4] != 'H')) { return IPS_ERROR_FILE_TYPE; } return IPS_OK; } int8_t IPSOpenInOUT(struct IPSPatch *ips, const char *inName, const char *outName) { int err; size_t nRead; long nTotal; uint8_t buffer[256]; if(strcmp(inName, outName) == 0) { char tmpFileName[64]; uint32_t fileExtOffset; strncpy(tmpFileName, inName, 52); fileExtOffset = strlen(inName); if(fileExtOffset > 52) { fileExtOffset = 52; } tmpFileName[fileExtOffset++] = '.'; tmpFileName[fileExtOffset++] = 's'; tmpFileName[fileExtOffset++] = 'a'; tmpFileName[fileExtOffset++] = 'v'; tmpFileName[fileExtOffset++] = '\0'; err = rename(inName, tmpFileName); if(err < 0) { return IPS_ERROR_SAVE; } ips->source = fopen(tmpFileName, "rb"); } else { ips->source = fopen(inName, "rb"); } if(ips->source == NULL) { return IPS_ERROR; } fseek(ips->source, 0, SEEK_SET); ips->destination = fopen(outName, "wb"); if(ips->destination == NULL) { return IPS_ERROR; } fseek(ips->source, 0, SEEK_END); nTotal = ftell(ips->source); fseek(ips->source, 0, SEEK_SET); nTotal -= ftell(ips->source); ips->sourceSize = (uint32_t)nTotal; if(nTotal <= 0) { return IPS_ERROR; } fseek(ips->destination, 0, SEEK_SET); for(nTotal=0; nTotalsourceSize; nTotal+=nRead) { nRead = fread(buffer, 1, 256, ips->source); fwrite(buffer, 1, nRead, ips->destination); } fflush(ips->destination); fseek(ips->destination, 0, SEEK_SET); return IPS_OK; } int8_t IPSOpen(struct IPSPatch *ips, const char *patchName, const char *inName, const char *outName) { int8_t err; ips->source = NULL; ips->destination = NULL; ips->patch = NULL; ips->record.offset = 0; ips->record.size = 0; err = IPSOpenPatch(ips, patchName); if(err != IPS_OK) { goto error; } err = IPSOpenInOUT(ips, inName, outName); if(err != IPS_OK) { goto error; } return IPS_OK; error: if(ips->patch != NULL) { fclose(ips->patch); } if(ips->source != NULL) { fclose(ips->source); } if(ips->destination != NULL) { fclose(ips->destination); } ips->source = NULL; ips->destination = NULL; ips->patch = NULL; return IPS_ERROR; } void IPSClose(struct IPSPatch *ips) { fclose(ips->patch); fclose(ips->source); fclose(ips->destination); } int8_t IPSReadRecord(struct IPSPatch *ips) { uint8_t buffer[5]; size_t nRead; nRead = fread(buffer, 1, 3, ips->patch); if(nRead < 3) { return IPS_ERROR_READ; } if((buffer[0] == 'E') && (buffer[1] == 'O') && (buffer[2] == 'F')) { return IPS_PATCH_END; } ips->record.offset = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2] ); nRead = fread(buffer, 1, 2, ips->patch); if(nRead < 2) { return IPS_ERROR_READ; } ips->record.size = (buffer[0] << 8) | (buffer[1] ); if(ips->record.size == 0) { ips->record.offset |= IPS_RECORD_RLE << 24; nRead = fread(buffer, 1, 2, ips->patch); if(nRead < 2) { return IPS_ERROR_READ; } ips->record.size = (buffer[0] << 8) | (buffer[1] ); nRead = fread(&(ips->record.rleData), 1, 1, ips->patch); if(nRead < 1) { return IPS_ERROR_READ; } } return IPS_OK; } int8_t IPSProcessRecord (struct IPSPatch *ips) { uint32_t i; uint8_t byte; fseek(ips->destination, IPS_RECORD_OFFSET(ips->record), SEEK_SET); if(IPS_RECORD_INFO(ips->record) == IPS_RECORD_RLE) { for(i=0; irecord.size; ++i) { fwrite(&(ips->record.rleData), 1, 1, ips->destination); } return IPS_OK; } for(i=0; irecord.size; ++i) { fread (&byte, 1, 1, ips->patch); fwrite(&byte, 1, 1, ips->destination); } return IPS_OK; }