int read_all_with_crc(int fd, void *buf, int size) { int ret; ret = read_all(fd, buf, size); if (ret) crc32_sum = Crc32_ComputeBuf(crc32_sum, buf, size); return ret; }
int slip_encode(int format, const unsigned char *src, int src_bytes, unsigned char *dst, int dst_len) { switch(format) { case SLIP_FORMAT_SLIP: { int offset=0; if (offset+2>dst_len) return WHY("Dest buffer full"); dst[offset++]=SLIP_END; int ret=encode_slip(src, src_bytes, dst + offset, dst_len - offset); if (ret<0) return ret; offset+=ret; unsigned char crc[4]; write_uint32(crc, Crc32_ComputeBuf( 0, src, src_bytes)); ret=encode_slip(crc, 4, dst + offset, dst_len - offset); if (ret<0) return ret; offset+=ret; dst[offset++]=SLIP_END; return offset; } case SLIP_FORMAT_UPPER7: /* The purpose of this encoder is to work nicely with the RFD900 radios, including allowing the reception of RSSI information in the middle of packets. RSSI reports look like: L/R RSSI: 48/0 L/R noise: 62/0 pkts: 0 txe=0 rxe=0 stx=0 srx=0 ecc=0/0 temp=21 dco=0 So we are using 0x80-0xff to hold data, and { and } to frame packets. */ if (config.debug.slip) dump("pre-slipped packet",src,src_bytes); { if (src_bytes<1) return 0; if (src_bytes>0x3fff) return WHYF("UPPER7 SLIP encoder packets must be <=0x3fff bytes"); if (dst_len<(9+src_bytes+(src_bytes/7)+1)) return WHYF("UPPER7 SLIP encoder requires 9+(8/7)*bytes to encode"); int i,j; int out_len=0; // Start of packet marker dst[out_len++]='{'; // Length of (unencoded) packet dst[out_len++]=0x80+((src_bytes>>7)&0x7f); dst[out_len++]=0x80+((src_bytes>>0)&0x7f); // Add 32-bit CRC // (putting the CRC at the front allows it to be calculated progressively // on the receiver side, if we decide to support that) uint32_t crc=Crc32_ComputeBuf( 0, src, src_bytes); dst[out_len++]=0x80|((crc>>25)&0x7f); dst[out_len++]=0x80|((crc>>(25-7))&0x7f); dst[out_len++]=0x80|((crc>>(25-7-7))&0x7f); dst[out_len++]=0x80|((crc>>(25-7-7-7))&0x7f); dst[out_len++]=0x80|((crc>>0)&0x7f); for(i=0;i<src_bytes;i+=7) { // Create 8 bytes of output consisting of 8x7 bits // Generate vector of 7 bytes to encode unsigned char v[7]; for(j=0;j<7&&i+j<src_bytes;j++) v[j]=src[i+j]; for(;j<7;j++) v[j]=0; if (out_len+8>dst_len) return WHYF("Ran out of space in UPPER7 SLIP encoder (used all %d bytes after encoding %d of %d bytes)", dst_len,i,src_bytes); // We could use a nice for loop to do this, but for 8 bytes, let's // just do it explicitly. dst[out_len++]=0x80| (v[0]>>1); dst[out_len++]=0x80|((v[0]&0x01)<<6)|(v[1]>>2); dst[out_len++]=0x80|((v[1]&0x03)<<5)|(v[2]>>3); dst[out_len++]=0x80|((v[2]&0x07)<<4)|(v[3]>>4); dst[out_len++]=0x80|((v[3]&0x0f)<<3)|(v[4]>>5); dst[out_len++]=0x80|((v[4]&0x1f)<<2)|(v[5]>>6); dst[out_len++]=0x80|((v[5]&0x3f)<<1)|(v[6]>>7); dst[out_len++]=0x80|((v[6]&0x7f)<<0); } // Mark end of packet dst[out_len++]='}'; // Detect fatal miscalculations on byte counts if (out_len>dst_len) { FATALF("overran output buffer in SLIP UPPER7 encapsulation of packet (used %d of %d bytes)",out_len,dst_len); } return out_len; } default: return WHYF("Unsupported slip encoding #%d",format); } }
/* state->src and state->src_size contain the freshly read bytes we must accumulate any partial state between calls. */ int slip_decode(struct slip_decode_state *state) { switch(state->encapsulator) { case SLIP_FORMAT_SLIP: { /* Examine received bytes for end of packet marker. The challenge is that we need to make sure that the packet encapsulation is self-synchronising in the event that a data error occurs (including failure to receive an arbitrary number of bytes). */ while(state->src_offset < state->src_size){ // clear the valid bit flag if we hit the end of the destination buffer if (state->dst_offset >= sizeof state->dst) state->state&=~DC_VALID; if (state->state&DC_ESC){ // clear escape bit state->state&=~DC_ESC; switch(state->src[state->src_offset]) { case SLIP_ESC_END: // escaped END byte state->dst[state->dst_offset++]=SLIP_END; break; case SLIP_ESC_ESC: // escaped escape character state->dst[state->dst_offset++]=SLIP_ESC; break; case SLIP_ESC_0a: state->dst[state->dst_offset++]=SLIP_0a; break; case SLIP_ESC_0d: state->dst[state->dst_offset++]=SLIP_0d; break; case SLIP_ESC_0f: state->dst[state->dst_offset++]=SLIP_0f; break; case SLIP_ESC_1b: state->dst[state->dst_offset++]=SLIP_1b; break; default: /* Unknown escape character. This is an error. */ if (config.debug.packetradio) WARNF("Packet radio stream contained illegal escaped byte 0x%02x -- resetting parser.",state->src[state->src_offset]); state->dst_offset=0; // skip everything until the next SLIP_END state->state=0; } }else{ // non-escape character switch(state->src[state->src_offset]) { case SLIP_ESC: // set escape bit state->state|=DC_ESC; break; case SLIP_END: if (state->dst_offset>4){ uint32_t src_crc = read_uint32(state->dst + state->dst_offset -4); uint32_t crc=Crc32_ComputeBuf( 0, state->dst, state->dst_offset -4); if (src_crc != crc){ DEBUGF("Dropping frame due to CRC failure (%08x vs %08x)", src_crc, crc); dump("frame", state->dst, state->dst_offset); state->dst_offset=0; state->state=0; break; } // return once we've successfully parsed a valid packet that isn't empty state->packet_length=state->dst_offset -4; return 1; } // set the valid flag to begin parsing the next packet state->state=DC_VALID; break; default: if (state->state&DC_VALID) state->dst[state->dst_offset++]=state->src[state->src_offset]; } } state->src_offset++; } return 0; } case SLIP_FORMAT_UPPER7: { if (config.debug.slip) { if (state->rssi_len>=RSSI_TEXT_SIZE) state->rssi_len=RSSI_TEXT_SIZE-1; state->rssi_text[state->rssi_len]=0; DEBUGF("RX state=%d, rssi_len=%u, rssi_text='%s',src=%p, src_size=%u", state->state,state->rssi_len,state->rssi_text, state->src,state->src_size); } while(state->src_offset<state->src_size) { if (upper7_decode(state,state->src[state->src_offset++])==1) { if (config.debug.slip) { dump("de-slipped packet",state->dst,state->packet_length); } // Check that CRC matches uint32_t crc=Crc32_ComputeBuf( 0, state->dst, state->packet_length); if (crc!=state->crc) { if (config.debug.packetradio||config.debug.rejecteddata) DEBUGF("Rejected packet of %u bytes due to CRC mis-match (%08x vs %08x)", state->packet_length,crc,state->crc); if (config.debug.rejecteddata) { dump("bad packet",state->dst,state->packet_length); } } else { if (config.debug.packetradio) DEBUGF("Accepted packet of %u bytes (CRC ok)",state->packet_length); return 1; } } } } return 0; default: return WHYF("Unknown SLIP encapsulation format #%d",state->encapsulator); } }
int patch_gcm(file_handle *file, ExecutableFile *filesToPatch, int numToPatch, int multiDol) { int i, num_patched = 0; // If the current device isn't SD Gecko, init SD Gecko Slot A or B to write patches. if(deviceHandler_initial != &initial_SD0 && deviceHandler_initial != &initial_SD1) { deviceHandler_setStatEnabled(0); if(deviceHandler_FAT_init(&initial_SD0)) { savePatchDevice = 0; } else if(deviceHandler_FAT_init(&initial_SD1)) { savePatchDevice = 1; } deviceHandler_setStatEnabled(1); } // Already using SD Gecko if(deviceHandler_initial == &initial_SD0) savePatchDevice = 0; else if(deviceHandler_initial == &initial_SD1) savePatchDevice = 1; if(savePatchDevice == -1) { DrawFrameStart(); DrawMessageBox(D_FAIL, "No writable device present\nA SD Gecko must be inserted in\n order to utilise patches for this game."); DrawFrameFinish(); sleep(5); return 0; } char patchFileName[256]; char patchDirName[256]; char patchBaseDirName[256]; char gameID[8]; memset(&gameID, 0, 8); memset(&patchDirName, 0, 256); memset(&patchBaseDirName, 0, 256); strncpy((char*)&gameID, (char*)&GCMDisk, 4); sprintf(&patchDirName[0],"%s:/swiss_patches/%s",(savePatchDevice ? "sdb":"sda"), &gameID[0]); sprintf(&patchBaseDirName[0],"%s:/swiss_patches",(savePatchDevice ? "sdb":"sda")); print_gecko("Patch dir will be: %s if required\r\n", patchDirName); *(u32*)VAR_EXECD_OFFSET = 0xFFFFFFFF; // Go through all the possible files we think need patching.. for(i = 0; i < numToPatch; i++) { u32 patched = 0, crc32 = 0; sprintf(txtbuffer, "Patching File %i/%i",i+1,numToPatch); DrawFrameStart(); DrawProgressBar((int)(((float)(i+1)/(float)numToPatch)*100), txtbuffer); DrawFrameFinish(); // Round up to 32 bytes if(filesToPatch[i].size % 0x20) { filesToPatch[i].size += (0x20-(filesToPatch[i].size%0x20)); } if(filesToPatch[i].size > 8*1024*1024) { print_gecko("Skipping %s %iKB too large\r\n", filesToPatch[i].name, filesToPatch[i].size/1024); continue; } print_gecko("Checking %s %iKb\r\n", filesToPatch[i].name, filesToPatch[i].size/1024); if(strstr(filesToPatch[i].name, "execD.")) { *(u32*)VAR_EXECD_OFFSET = filesToPatch[i].offset; } if(strstr(filesToPatch[i].name, "iwanagaD.dol") || strstr(filesToPatch[i].name, "switcherD.dol")) { continue; // skip unused PSO files } int sizeToRead = filesToPatch[i].size; u8 *buffer = (u8*)memalign(32, sizeToRead); deviceHandler_seekFile(file,filesToPatch[i].offset, DEVICE_HANDLER_SEEK_SET); if(deviceHandler_readFile(file,buffer,sizeToRead)!= sizeToRead) { DrawFrameStart(); DrawMessageBox(D_FAIL, "Failed to read!"); DrawFrameFinish(); sleep(5); return 0; } if(curDevice != DVD_DISC) { u32 ret = Patch_DVDLowLevelRead(buffer, sizeToRead, filesToPatch[i].type); if(READ_PATCHED_ALL != ret) { DrawFrameStart(); DrawMessageBox(D_FAIL, "Failed to find necessary functions for patching!"); DrawFrameFinish(); sleep(5); } else patched += 1; } if(swissSettings.debugUSB && usb_isgeckoalive(1) && !swissSettings.wiirdDebug) { patched += Patch_Fwrite(buffer, sizeToRead); } if(swissSettings.wiirdDebug || getEnabledCheatsSize() > 0) { Patch_CheatsHook(buffer, sizeToRead, filesToPatch[i].type); } if(curDevice == DVD_DISC && is_gamecube()) { patched += Patch_DVDLowLevelReadForDVD(buffer, sizeToRead, filesToPatch[i].type); patched += Patch_DVDReset(buffer, sizeToRead); } patched += Patch_VidMode(buffer, sizeToRead, filesToPatch[i].type); patched += Patch_FontEnc(buffer, sizeToRead); if(swissSettings.forceWidescreen) Patch_WideAspect(buffer, sizeToRead, filesToPatch[i].type); if(swissSettings.forceAnisotropy) Patch_TexFilt(buffer, sizeToRead, filesToPatch[i].type); if(patched) { // File handle for a patch we might need to write FILE *patchFile = 0; memset(patchFileName, 0, 256); // Make a base patches dir if we don't have one already if(mkdir(&patchBaseDirName[0], 0777) != 0) { if(errno != EEXIST) { return -2; } } if(mkdir(&patchDirName[0], 0777) != 0) { if(errno != EEXIST) { return -2; } } sprintf(patchFileName, "%s/%i",patchDirName, num_patched); // Work out the crc32 crc32 = Crc32_ComputeBuf( 0, buffer, (u32) sizeToRead); // See if this file already exists, if it does, match crc patchFile = fopen( patchFileName, "rb" ); if(patchFile) { //print_gecko("Old Patch exists\r\n"); u32 oldCrc32 = 0; fseek(patchFile, 0L, SEEK_END); u32 file_size = ftell(patchFile); fseek(patchFile, file_size-4, SEEK_SET); fread(&oldCrc32, 1, 4, patchFile); if(oldCrc32 == crc32) { num_patched++; fclose(patchFile); free(buffer); print_gecko("CRC matched, no need to patch again\r\n"); continue; } else { remove(patchFileName); fclose(patchFile); print_gecko("CRC mismatch, writing patch again\r\n"); } } // Otherwise, write a file out for this game with the patched buffer inside. print_gecko("Writing patch file: %s %i bytes (disc offset %08X)\r\n", patchFileName, sizeToRead, filesToPatch[i].offset); patchFile = fopen(patchFileName, "wb"); fwrite(buffer, 1, sizeToRead, patchFile); u32 magic = SWISS_MAGIC; fwrite(&filesToPatch[i].offset, 1, 4, patchFile); fwrite(&filesToPatch[i].size, 1, 4, patchFile); fwrite(&magic, 1, 4, patchFile); fwrite(&crc32, 1, 4, patchFile); fclose(patchFile); num_patched++; } free(buffer); } return num_patched; }
int write_all_with_crc(int fd, void *buf, int size) { crc32_sum = Crc32_ComputeBuf(crc32_sum, buf, size); return write_all(fd, buf, size); }