int main(void) { static const kernel_ulong_t unknown_loop_cmd = (kernel_ulong_t) 0xbadc0dedfeed4cedULL; static const kernel_ulong_t magic = (kernel_ulong_t) 0xdeadbeefbadc0dedULL; static const kernel_ulong_t kernel_mask = ((kernel_ulong_t) -1) - ((unsigned long) -1L); TAIL_ALLOC_OBJECT_CONST_PTR(struct loop_info, info); TAIL_ALLOC_OBJECT_CONST_PTR(struct loop_info64, info64); /* Unknown loop commands */ ioctl(-1, unknown_loop_cmd, magic); printf("ioctl(-1, _IOC(_IOC_READ|_IOC_WRITE%s, 0x4c, %#x, %#x), " "%#lx) = -1 EBADF (%m)\n", _IOC_DIR((unsigned int) unknown_loop_cmd) & _IOC_NONE ? "|_IOC_NONE" : "", _IOC_NR((unsigned int) unknown_loop_cmd), _IOC_SIZE((unsigned int) unknown_loop_cmd), (unsigned long) magic); ioctl(-1, LOOP_SET_BLOCK_SIZE + 1, magic); printf("ioctl(-1, _IOC(0, 0x4c, %#x, %#x), %#lx) = " "-1 EBADF (%m)\n", _IOC_NR(LOOP_SET_BLOCK_SIZE + 1), _IOC_SIZE(LOOP_SET_BLOCK_SIZE + 1), (unsigned long) magic); ioctl(-1, LOOP_CTL_GET_FREE + 1, magic); printf("ioctl(-1, _IOC(0, 0x4c, %#x, %#x), %#lx) = " "-1 EBADF (%m)\n", _IOC_NR(LOOP_CTL_GET_FREE + 1), _IOC_SIZE(LOOP_CTL_GET_FREE + 1), (unsigned long) magic); /* LOOP_SET_FD */ ioctl(-1, LOOP_SET_FD, magic); printf("ioctl(-1, LOOP_SET_FD, %d) = -1 EBADF (%m)\n", (unsigned int) magic); /* LOOP_CLR_FD */ ioctl(-1, LOOP_CLR_FD); printf("ioctl(-1, LOOP_CLR_FD) = -1 EBADF (%m)\n"); /* LOOP_SET_STATUS */ ioctl(-1, LOOP_SET_STATUS, NULL); printf("ioctl(-1, LOOP_SET_STATUS, NULL) = -1 EBADF (%m)\n"); fill_memory(info, sizeof(*info)); info->lo_flags = 0xdeface00; info->lo_name[0] = '\0'; info->lo_encrypt_key[0] = '\0'; info->lo_encrypt_key_size = 1; printf("ioctl(-1, LOOP_SET_STATUS, "); print_loop_info(info, true, NULL, "\\0", NULL); ioctl(-1, LOOP_SET_STATUS, info); printf(") = -1 EBADF (%m)\n"); fill_memory(info, sizeof(*info)); info->lo_encrypt_type = LO_CRYPT_NONE; info->lo_flags = LO_FLAGS_READ_ONLY; memset(info->lo_name, 'A', sizeof(info->lo_name)); memset(info->lo_encrypt_key, 'B', sizeof(info->lo_encrypt_key)); ioctl(-1, LOOP_SET_STATUS, (void *) info + ALIGNOF(info)); printf("ioctl(-1, LOOP_SET_STATUS, %p) = -1 EBADF (%m)\n", (void *) info + ALIGNOF(info)); printf("ioctl(-1, LOOP_SET_STATUS, "); print_loop_info(info, false, "LO_CRYPT_NONE", NULL, "LO_FLAGS_READ_ONLY"); ioctl(-1, LOOP_SET_STATUS, info); printf(") = -1 EBADF (%m)\n"); /* LOOP_GET_STATUS */ ioctl(-1, LOOP_GET_STATUS, NULL); printf("ioctl(-1, LOOP_GET_STATUS, NULL) = -1 EBADF (%m)\n"); ioctl(-1, LOOP_GET_STATUS, (unsigned long) info | kernel_mask); printf("ioctl(-1, LOOP_GET_STATUS, %p) = -1 EBADF (%m)\n", info); /* LOOP_SET_STATUS64 */ ioctl(-1, LOOP_SET_STATUS64, NULL); printf("ioctl(-1, LOOP_SET_STATUS64, NULL) = -1 EBADF (%m)\n"); fill_memory(info64, sizeof(*info64)); info64->lo_flags = 0xdec0de00; info64->lo_file_name[0] = '\0'; info64->lo_crypt_name[0] = '\0'; info64->lo_encrypt_key[0] = '\0'; info64->lo_encrypt_key_size = 1; printf("ioctl(-1, LOOP_SET_STATUS64, "); print_loop_info64(info64, true, NULL, "\\0", NULL); ioctl(-1, LOOP_SET_STATUS64, info64); printf(") = -1 EBADF (%m)\n"); fill_memory(info64, sizeof(*info64)); info64->lo_flags = LO_FLAGS_READ_ONLY; info64->lo_encrypt_type = LO_CRYPT_NONE; memset(info64->lo_file_name, 'C', sizeof(info64->lo_file_name)); memset(info64->lo_crypt_name, 'D', sizeof(info64->lo_crypt_name)); memset(info64->lo_encrypt_key, 'E', sizeof(info64->lo_encrypt_key)); ioctl(-1, LOOP_SET_STATUS64, (void *) info64 + ALIGNOF(info64)); printf("ioctl(-1, LOOP_SET_STATUS64, %p) = -1 EBADF (%m)\n", (void *) info64 + ALIGNOF(info64)); printf("ioctl(-1, LOOP_SET_STATUS64, "); print_loop_info64(info64, false, "LO_CRYPT_NONE", NULL, "LO_FLAGS_READ_ONLY"); ioctl(-1, LOOP_SET_STATUS64, info64); printf(") = -1 EBADF (%m)\n"); /* LOOP_GET_STATUS64 */ ioctl(-1, LOOP_GET_STATUS64, NULL); printf("ioctl(-1, LOOP_GET_STATUS64, NULL) = -1 EBADF (%m)\n"); ioctl(-1, LOOP_GET_STATUS64, (unsigned long) info64 | kernel_mask); printf("ioctl(-1, LOOP_GET_STATUS64, %p) = -1 EBADF (%m)\n", info64); /* LOOP_CHANGE_FD */ ioctl(-1, LOOP_CHANGE_FD, magic); printf("ioctl(-1, LOOP_CHANGE_FD, %d) = -1 EBADF (%m)\n", (unsigned int) magic); /* LOOP_SET_CAPACITY */ ioctl(-1, LOOP_SET_CAPACITY); printf("ioctl(-1, LOOP_SET_CAPACITY) = -1 EBADF (%m)\n"); /* LOOP_SET_DIRECT_IO */ ioctl(-1, LOOP_SET_DIRECT_IO, magic); printf("ioctl(-1, LOOP_SET_DIRECT_IO, %lu) = -1 EBADF (%m)\n", (unsigned long) magic); /* LOOP_SET_BLOCK_SIZE */ ioctl(-1, LOOP_SET_BLOCK_SIZE, magic); printf("ioctl(-1, LOOP_SET_BLOCK_SIZE, %lu) = -1 EBADF (%m)\n", (unsigned long) magic); /* LOOP_CTL_ADD */ ioctl(-1, LOOP_CTL_ADD, magic); printf("ioctl(-1, LOOP_CTL_ADD, %d) = -1 EBADF (%m)\n", (unsigned int) magic); /* LOOP_CTL_REMOVE */ ioctl(-1, LOOP_CTL_REMOVE, magic); printf("ioctl(-1, LOOP_CTL_REMOVE, %d) = -1 EBADF (%m)\n", (unsigned int) magic); /* LOOP_CTL_GET_FREE */ ioctl(-1, LOOP_CTL_GET_FREE); printf("ioctl(-1, LOOP_CTL_GET_FREE) = -1 EBADF (%m)\n"); puts("+++ exited with 0 +++"); return 0; }
int main(const int argc, char *const argv[]) { unsigned int looppos = 0, loopcount = 1, samplerate = 32000; int size; double min_length = 0.0; bool gaussian_lowpass = false; int c; while ((c = getopt(argc, argv, "l:n:s:m:g")) != -1) { switch(c) { case 'l': looppos = atoi(optarg); break; case 'n': loopcount = atoi(optarg); break; case 's': samplerate = atoi(optarg); break; case 'm': min_length = atof(optarg); break; case 'g': gaussian_lowpass = true; break; default: printf("Invalid command line syntax !\n"); print_instructions(); } } if(argc - optind != 2) print_instructions(); char *inbrr_path = argv[optind]; char *outwav_path = argv[optind+1]; // Try to open input BRR file FILE *inbrr = fopen(inbrr_path, "rb"); if(!inbrr) { fprintf(stderr, "No such file : %s\n", inbrr_path); exit(1); } // Get the size of the input BRR file fseek(inbrr, 0L, SEEK_END); size = ftell(inbrr); fseek(inbrr, 0L, SEEK_SET); // Size should be an integer multiple of 9 if(size%9 != 0) { fprintf(stderr, "Error : Size of BRR file %s isn't a multiple of 9 bytes.\n", inbrr_path); exit(1); } int blockamount = size/9; printf("Number of BRR blocks to decode : %d.\n", blockamount); if(looppos >= blockamount) //Make sure the loop position is in range { fprintf(stderr, "Error : Loop position is out of range\n"); exit(1); } //Implement the "minimum length" function int min_len_samples = (int)ceil(min_length*samplerate/16.0); loopcount = MAX((signed)loopcount, (min_len_samples-(signed)looppos)/(blockamount-(signed)looppos)); pcm_t olds0[loopcount]; pcm_t olds1[loopcount]; //Tables to remember value of p1, p2 when looping //Create sample buffer unsigned int out_blocks = loopcount*(blockamount-looppos)+looppos; pcm_t *samples = safe_malloc(out_blocks * 32); fseek(inbrr, 0, SEEK_SET); //Start to read at the beginning of the file pcm_t *buf_ptr = samples; for(int i=0; i<looppos; ++i) //Read the start of the sample before loop point { fread(BRR, 1, 9, inbrr); decodeBRR(buf_ptr); //Append 16 BRR samples to existing array buf_ptr += 16; } for(int j=0; j<loopcount; ++j) { fseek(inbrr, looppos*9, SEEK_SET); for(int i=looppos; i<blockamount; ++i) { fread(BRR, 1, 9, inbrr); decodeBRR(buf_ptr); //Append 16 BRR samples to existing array if(i == looppos) { //Save the p1 and p2 values on each loop point encounter olds0[j] = buf_ptr[0]; olds1[j] = buf_ptr[1]; } buf_ptr += 16; } } if(loopcount > 1) print_note_info(blockamount - looppos, samplerate); print_loop_info(loopcount, olds0, olds1); fclose(inbrr); // Try to open output WAV file FILE *outwav = fopen(outwav_path, "wb"); if(!outwav) { fprintf(stderr, "Can't open file %s for writing.\n", outwav_path); exit(1); } // Lowpass filter data to simulate real SNES hardware if(gaussian_lowpass) apply_gauss_filter(samples, out_blocks * 16); generate_wave_file(outwav, samplerate, samples, out_blocks); fclose(outwav); free(samples); printf("Done !\n"); return 0; // Exit without error }