bool WaveFileWriter::Start(const std::string& filename, unsigned int HLESampleRate) { // Check if the file is already open if (file) { PanicAlertT("The file %s was already open, the file header will not be written.", filename.c_str()); return false; } file.Open(filename, "wb"); if (!file) { PanicAlertT("The file %s could not be opened for writing. Please check if it's already opened " "by another program.", filename.c_str()); return false; } audio_size = 0; if (basename.empty()) SplitPath(filename, nullptr, &basename, nullptr); current_sample_rate = HLESampleRate; // ----------------- // Write file header // ----------------- Write4("RIFF"); Write(100 * 1000 * 1000); // write big value in case the file gets truncated Write4("WAVE"); Write4("fmt "); Write(16); // size of fmt block Write(0x00020001); // two channels, uncompressed const u32 sample_rate = HLESampleRate; Write(sample_rate); Write(sample_rate * 2 * 2); // two channels, 16bit Write(0x00100004); Write4("data"); Write(100 * 1000 * 1000 - 32); // We are now at offset 44 if (file.Tell() != 44) PanicAlert("Wrong offset: %lld", (long long)file.Tell()); return true; }
static void WriteData(lcd * pLCD, const uint8_t Data) { SetMode(pLCD, modeWriteData); Write4(pLCD, Data>>4); Write4(pLCD, Data); }
static void WriteCommand(lcd * pLCD, const uint8_t Command) { SetMode(pLCD, modeWriteCommand); Write4(pLCD, Command>>4); Write4(pLCD, Command); }
/* fetchkey(): This massages the key into a form that's easier to handle. When it returns, the key will be stored in keybuf if keysize <= 4; otherwise, it will be in memory. */ static void fetchkey(unsigned char *keybuf, glui32 key, glui32 keysize, glui32 options) { int ix; if (options & serop_KeyIndirect) { if (keysize <= 4) { for (ix=0; ix<keysize; ix++) keybuf[ix] = Mem1(key+ix); } } else { switch (keysize) { case 4: Write4(keybuf, key); break; case 2: Write2(keybuf, key); break; case 1: Write1(keybuf, key); break; default: fatal_error("Direct search key must hold one, two, or four bytes."); } } }
bool WaveFileWriter::Start(const char *filename, unsigned int HLESampleRate) { if (!conv_buffer) conv_buffer = new short[BUF_SIZE]; // Check if the file is already open if (file) { PanicAlertT("The file %s was already open, the file header will not be written.", filename); return false; } file.Open(filename, "wb"); if (!file) { PanicAlertT("The file %s could not be opened for writing. Please check if it's already opened by another program.", filename); return false; } // ----------------- // Write file header // ----------------- Write4("RIFF"); Write(100 * 1000 * 1000); // write big value in case the file gets truncated Write4("WAVE"); Write4("fmt "); Write(16); // size of fmt block Write(0x00020001); //two channels, uncompressed const u32 sample_rate = HLESampleRate; Write(sample_rate); Write(sample_rate * 2 * 2); //two channels, 16bit Write(0x00100004); Write4("data"); Write(100 * 1000 * 1000 - 32); // We are now at offset 44 if (file.Tell() != 44) PanicAlert("wrong offset: %lld", (long long)file.Tell()); return true; }
int main(int argc, char** argv) { if (argc != 4) { fprintf(stderr, "usage: %s <src-img> <tgt-img> <patch-file>\n", argv[0]); return 2; } int num_src_chunks; ImageChunk* src_chunks; if (ReadImage(argv[1], &num_src_chunks, &src_chunks) == NULL) { fprintf(stderr, "failed to break apart source image\n"); return 1; } int num_tgt_chunks; ImageChunk* tgt_chunks; if (ReadImage(argv[2], &num_tgt_chunks, &tgt_chunks) == NULL) { fprintf(stderr, "failed to break apart target image\n"); return 1; } // Verify that the source and target images have the same chunk // structure (ie, the same sequence of gzip and normal chunks). if (num_src_chunks != num_tgt_chunks) { fprintf(stderr, "source and target don't have same number of chunks!\n"); return 1; } int i; for (i = 0; i < num_src_chunks; ++i) { if (src_chunks[i].type != tgt_chunks[i].type) { fprintf(stderr, "source and target don't have same chunk " "structure! (chunk %d)\n", i); return 1; } } // Confirm that given the uncompressed chunk data in the target, we // can recompress it and get exactly the same bits as are in the // input target image. If this fails, treat the chunk as a normal // non-gzipped chunk. for (i = 0; i < num_tgt_chunks; ++i) { if (tgt_chunks[i].type == CHUNK_GZIP) { if (ReconstructGzipChunk(tgt_chunks+i) < 0) { printf("failed to reconstruct target gzip chunk %d; " "treating as normal chunk\n", i); ChangeGzipChunkToNormal(tgt_chunks+i); ChangeGzipChunkToNormal(src_chunks+i); } else { printf("reconstructed target gzip chunk %d\n", i); } } } // Compute bsdiff patches for each chunk's data (the uncompressed // data, in the case of gzip chunks). unsigned char** patch_data = malloc(num_src_chunks * sizeof(unsigned char*)); size_t* patch_size = malloc(num_src_chunks * sizeof(size_t)); for (i = 0; i < num_src_chunks; ++i) { patch_data[i] = MakePatch(src_chunks+i, tgt_chunks+i, patch_size+i); printf("patch %d is %d bytes (of %d)\n", i, patch_size[i], tgt_chunks[i].type == CHUNK_NORMAL ? tgt_chunks[i].len : tgt_chunks[i].gzip_len); } // Figure out how big the imgdiff file header is going to be, so // that we can correctly compute the offset of each bsdiff patch // within the file. size_t total_header_size = 12; for (i = 0; i < num_src_chunks; ++i) { total_header_size += 4 + 8*3; if (src_chunks[i].type == CHUNK_GZIP) { total_header_size += 8*2 + 4*6 + tgt_chunks[i].gzip_header_len + 8; } } size_t offset = total_header_size; FILE* f = fopen(argv[3], "wb"); // Write out the headers. fwrite("IMGDIFF1", 1, 8, f); Write4(num_src_chunks, f); for (i = 0; i < num_tgt_chunks; ++i) { Write4(tgt_chunks[i].type, f); Write8(src_chunks[i].start, f); Write8(src_chunks[i].type == CHUNK_NORMAL ? src_chunks[i].len : (src_chunks[i].gzip_len + src_chunks[i].gzip_header_len + 8), f); Write8(offset, f); if (tgt_chunks[i].type == CHUNK_GZIP) { Write8(src_chunks[i].len, f); Write8(tgt_chunks[i].len, f); Write4(tgt_chunks[i].level, f); Write4(tgt_chunks[i].method, f); Write4(tgt_chunks[i].windowBits, f); Write4(tgt_chunks[i].memLevel, f); Write4(tgt_chunks[i].strategy, f); Write4(tgt_chunks[i].gzip_header_len, f); fwrite(tgt_chunks[i].gzip_header, 1, tgt_chunks[i].gzip_header_len, f); fwrite(tgt_chunks[i].gzip_footer, 1, GZIP_FOOTER_LEN, f); } offset += patch_size[i]; } // Append each chunk's bsdiff patch, in order. for (i = 0; i < num_tgt_chunks; ++i) { fwrite(patch_data[i], 1, patch_size[i], f); } fclose(f); return 0; }
int main(int argc, char** argv) { int zip_mode = 0; if (argc >= 2 && strcmp(argv[1], "-z") == 0) { zip_mode = 1; --argc; ++argv; } size_t bonus_size = 0; unsigned char* bonus_data = NULL; if (argc >= 3 && strcmp(argv[1], "-b") == 0) { struct stat st; if (stat(argv[2], &st) != 0) { printf("failed to stat bonus file %s: %s\n", argv[2], strerror(errno)); return 1; } bonus_size = st.st_size; bonus_data = malloc(bonus_size); FILE* f = fopen(argv[2], "rb"); if (f == NULL) { printf("failed to open bonus file %s: %s\n", argv[2], strerror(errno)); return 1; } if (fread(bonus_data, 1, bonus_size, f) != bonus_size) { printf("failed to read bonus file %s: %s\n", argv[2], strerror(errno)); return 1; } fclose(f); argc -= 2; argv += 2; } if (argc != 4) { usage: printf("usage: %s [-z] [-b <bonus-file>] <src-img> <tgt-img> <patch-file>\n", argv[0]); return 2; } int num_src_chunks; ImageChunk* src_chunks; int num_tgt_chunks; ImageChunk* tgt_chunks; int i; if (zip_mode) { if (ReadZip(argv[1], &num_src_chunks, &src_chunks, 1) == NULL) { printf("failed to break apart source zip file\n"); return 1; } if (ReadZip(argv[2], &num_tgt_chunks, &tgt_chunks, 0) == NULL) { printf("failed to break apart target zip file\n"); return 1; } } else { if (ReadImage(argv[1], &num_src_chunks, &src_chunks) == NULL) { printf("failed to break apart source image\n"); return 1; } if (ReadImage(argv[2], &num_tgt_chunks, &tgt_chunks) == NULL) { printf("failed to break apart target image\n"); return 1; } // Verify that the source and target images have the same chunk // structure (ie, the same sequence of deflate and normal chunks). if (!zip_mode) { // Merge the gzip header and footer in with any adjacent // normal chunks. MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks); MergeAdjacentNormalChunks(src_chunks, &num_src_chunks); } if (num_src_chunks != num_tgt_chunks) { printf("source and target don't have same number of chunks!\n"); printf("source chunks:\n"); DumpChunks(src_chunks, num_src_chunks); printf("target chunks:\n"); DumpChunks(tgt_chunks, num_tgt_chunks); return 1; } for (i = 0; i < num_src_chunks; ++i) { if (src_chunks[i].type != tgt_chunks[i].type) { printf("source and target don't have same chunk " "structure! (chunk %d)\n", i); printf("source chunks:\n"); DumpChunks(src_chunks, num_src_chunks); printf("target chunks:\n"); DumpChunks(tgt_chunks, num_tgt_chunks); return 1; } } } for (i = 0; i < num_tgt_chunks; ++i) { if (tgt_chunks[i].type == CHUNK_DEFLATE) { // Confirm that given the uncompressed chunk data in the target, we // can recompress it and get exactly the same bits as are in the // input target image. If this fails, treat the chunk as a normal // non-deflated chunk. if (ReconstructDeflateChunk(tgt_chunks+i) < 0) { printf("failed to reconstruct target deflate chunk %d [%s]; " "treating as normal\n", i, tgt_chunks[i].filename); ChangeDeflateChunkToNormal(tgt_chunks+i); if (zip_mode) { ImageChunk* src = FindChunkByName(tgt_chunks[i].filename, src_chunks, num_src_chunks); if (src) { ChangeDeflateChunkToNormal(src); } } else { ChangeDeflateChunkToNormal(src_chunks+i); } continue; } // If two deflate chunks are identical (eg, the kernel has not // changed between two builds), treat them as normal chunks. // This makes applypatch much faster -- it can apply a trivial // patch to the compressed data, rather than uncompressing and // recompressing to apply the trivial patch to the uncompressed // data. ImageChunk* src; if (zip_mode) { src = FindChunkByName(tgt_chunks[i].filename, src_chunks, num_src_chunks); } else { src = src_chunks+i; } if (src == NULL || AreChunksEqual(tgt_chunks+i, src)) { ChangeDeflateChunkToNormal(tgt_chunks+i); if (src) { ChangeDeflateChunkToNormal(src); } } } } // Merging neighboring normal chunks. if (zip_mode) { // For zips, we only need to do this to the target: deflated // chunks are matched via filename, and normal chunks are patched // using the entire source file as the source. MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks); } else { // For images, we need to maintain the parallel structure of the // chunk lists, so do the merging in both the source and target // lists. MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks); MergeAdjacentNormalChunks(src_chunks, &num_src_chunks); if (num_src_chunks != num_tgt_chunks) { // This shouldn't happen. printf("merging normal chunks went awry\n"); return 1; } } // Compute bsdiff patches for each chunk's data (the uncompressed // data, in the case of deflate chunks). DumpChunks(src_chunks, num_src_chunks); printf("Construct patches for %d chunks...\n", num_tgt_chunks); unsigned char** patch_data = malloc(num_tgt_chunks * sizeof(unsigned char*)); size_t* patch_size = malloc(num_tgt_chunks * sizeof(size_t)); for (i = 0; i < num_tgt_chunks; ++i) { if (zip_mode) { ImageChunk* src; if (tgt_chunks[i].type == CHUNK_DEFLATE && (src = FindChunkByName(tgt_chunks[i].filename, src_chunks, num_src_chunks))) { patch_data[i] = MakePatch(src, tgt_chunks+i, patch_size+i); } else { patch_data[i] = MakePatch(src_chunks, tgt_chunks+i, patch_size+i); } } else { if (i == 1 && bonus_data) { printf(" using %zu bytes of bonus data for chunk %d\n", bonus_size, i); src_chunks[i].data = realloc(src_chunks[i].data, src_chunks[i].len + bonus_size); memcpy(src_chunks[i].data+src_chunks[i].len, bonus_data, bonus_size); src_chunks[i].len += bonus_size; } patch_data[i] = MakePatch(src_chunks+i, tgt_chunks+i, patch_size+i); } printf("patch %3d is %zd bytes (of %zd)\n", i, patch_size[i], tgt_chunks[i].source_len); } // Figure out how big the imgdiff file header is going to be, so // that we can correctly compute the offset of each bsdiff patch // within the file. size_t total_header_size = 12; for (i = 0; i < num_tgt_chunks; ++i) { total_header_size += 4; switch (tgt_chunks[i].type) { case CHUNK_NORMAL: total_header_size += 8*4; break; case CHUNK_DEFLATE: total_header_size += 8*6 + 4*5; break; case CHUNK_RAW: total_header_size += 4 + patch_size[i]; break; } } size_t offset = total_header_size; FILE* f = fopen(argv[3], "wb"); // Write out the headers. fwrite("IMGDIFFX", 1, 8, f); Write4(num_tgt_chunks, f); for (i = 0; i < num_tgt_chunks; ++i) { Write4(tgt_chunks[i].type, f); switch (tgt_chunks[i].type) { case CHUNK_NORMAL: printf("chunk %3d: normal (%10zd, %10zd) %10zd\n", i, tgt_chunks[i].start, tgt_chunks[i].len, patch_size[i]); Write8(tgt_chunks[i].source_start, f); Write8(tgt_chunks[i].source_len, f); Write8(offset, f); Write8(patch_size[i], f); offset += patch_size[i]; break; case CHUNK_DEFLATE: printf("chunk %3d: deflate (%10zd, %10zd) %10zd %s\n", i, tgt_chunks[i].start, tgt_chunks[i].deflate_len, patch_size[i], tgt_chunks[i].filename); Write8(tgt_chunks[i].source_start, f); Write8(tgt_chunks[i].source_len, f); Write8(offset, f); Write8(patch_size[i], f); Write8(tgt_chunks[i].source_uncompressed_len, f); Write8(tgt_chunks[i].len, f); Write4(tgt_chunks[i].level, f); Write4(tgt_chunks[i].method, f); Write4(tgt_chunks[i].windowBits, f); Write4(tgt_chunks[i].memLevel, f); Write4(tgt_chunks[i].strategy, f); offset += patch_size[i]; break; case CHUNK_RAW: printf("chunk %3d: raw (%10zd, %10zd)\n", i, tgt_chunks[i].start, tgt_chunks[i].len); Write4(patch_size[i], f); fwrite(patch_data[i], 1, patch_size[i], f); break; } } // Append each chunk's bsdiff patch, in order. for (i = 0; i < num_tgt_chunks; ++i) { if (tgt_chunks[i].type != CHUNK_RAW) { fwrite(patch_data[i], 1, patch_size[i], f); } } fclose(f); return 0; }
static int write_long(dest_t *dest, glui32 val) { unsigned char buf[4]; Write4(buf, val); return write_buffer(dest, buf, 4); }