int overflow(int c=EOF) { if (c == EOF) return c ; return gzputc(file, c) ; }
//---------------------------------------------------------------------------------------------- // Pause optimiser //---------------------------------------------------------------------------------------------- BOOL OptimiseVGMPauses(char *filename) { gzFile *in,*out; struct TVGMHeader VGMHeader; char *outfilename,b0,b1,b2; long int OldLoopOffset; int i,PauseLength=0; if (!FileExists(filename)) return FALSE; // Open input file in=gzopen(filename,"rb"); // Read its VGM header if(!ReadVGMHeader(in,&VGMHeader,FALSE)) { gzclose(in); return FALSE; } OldLoopOffset=VGMHeader.LoopOffset+LOOPDELTA; // Make the output filename... outfilename=MakeTempFilename(filename); // ...open it... out=gzopen(outfilename,"wb0"); // ...skip to the data section... gzseek(in,VGM_DATA_OFFSET,SEEK_SET); gzseek(out,VGM_DATA_OFFSET,SEEK_SET); // ...and parse the input file // Go through the file; if it's a pause, add it to the total; if it's data, write the current total and zero it do { // Update loop point // Write any remaining pauyse being buffered first, though if (gztell(in)==OldLoopOffset) { WritePause(out,PauseLength); PauseLength=0; VGMHeader.LoopOffset=gztell(out)-LOOPDELTA; } b0=gzgetc(in); switch (b0) { case VGM_GGST: // GG stereo case VGM_PSG: // PSG write WritePause(out,PauseLength); PauseLength=0; b1=gzgetc(in); gzputc(out,b0); gzputc(out,b1); break; case VGM_YM2413: // YM2413 case VGM_YM2612_0: // YM2612 port 0 case VGM_YM2612_1: // YM2612 port 1 case VGM_YM2151: // YM2151 case 0x55: // Reserved up to 0x5f case 0x56: // All have 2 bytes of data case 0x57: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: WritePause(out,PauseLength); PauseLength=0; b1=gzgetc(in); b2=gzgetc(in); gzputc(out,b0); gzputc(out,b1); gzputc(out,b2); break; case VGM_PAUSE_WORD: // Wait n samples b1=gzgetc(in); b2=gzgetc(in); PauseLength+=MAKEWORD(b1,b2); break; case VGM_PAUSE_60TH: // Wait 1/60 s PauseLength+=LEN60TH; break; case VGM_PAUSE_50TH: // Wait 1/50 s PauseLength+=LEN50TH; break; // case VGM_PAUSE_BYTE: // Wait n samples // b1=gzgetc(in); // PauseLength+=b1; // break; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: // Wait 1-16 samples PauseLength+=(b0 & 0xf)+1; break; case VGM_END: // End of sound data WritePause(out,PauseLength); PauseLength=0; b0=EOF; // break out of loop break; default: break; } // end switch } while (b0!=EOF); // At end: // 1. Write EOF mrker gzputc(out,VGM_END); // 2. Copy GD3 tag if (VGMHeader.GD3Offset) { struct TGD3Header GD3Header; int NewGD3Offset=gztell(out)-GD3DELTA; gzseek(in,VGMHeader.GD3Offset+GD3DELTA,SEEK_SET); gzread(in,&GD3Header,sizeof(GD3Header)); gzwrite(out,&GD3Header,sizeof(GD3Header)); for (i=0; i<GD3Header.Length; ++i) gzputc(out,gzgetc(in)); VGMHeader.GD3Offset=NewGD3Offset; } // 3. Fill in VGM header VGMHeader.EoFOffset=gztell(out)-EOFDELTA; // LoopOffset updated while optimising gzclose(out); WriteVGMHeader(outfilename,VGMHeader); // Clean up gzclose(in); ReplaceFile(filename,outfilename); free(outfilename); return TRUE; }
//---------------------------------------------------------------------------------------------- // PSG offset (small freq value, volume on) remover // Returns number of offsets removed //---------------------------------------------------------------------------------------------- int RemoveOffset(char *filename) { gzFile *in,*out; char *outfilename; struct TVGMHeader VGMHeader; signed int b0,b1,b2; BOOL SilencedChannels[3]={FALSE,FALSE,FALSE}; unsigned short int PSGRegisters[8] = {0,0xf,0,0xf,0,0xf,0,0xf}; int PSGLatchedRegister=0; long int NewLoopOffset=0; int NumOffsetsRemoved=0; int NoiseCh2=0; if (!FileExists(filename)) return 0; in=gzopen(filename,"rb"); // Read header if(!ReadVGMHeader(in,&VGMHeader,FALSE)) { gzclose(in); return FALSE; } gzseek(in,VGM_DATA_OFFSET,SEEK_SET); outfilename=MakeTempFilename(filename); out=gzopen(outfilename,"wb0"); // No compression, since I'll recompress it later // copy header... update it later gzwrite(out,&VGMHeader,sizeof(VGMHeader)); gzseek(out,VGM_DATA_OFFSET,SEEK_SET); // Process file do { if ((VGMHeader.LoopOffset) && (gztell(in)==VGMHeader.LoopOffset+LOOPDELTA)) NewLoopOffset=gztell(out)-LOOPDELTA; b0=gzgetc(in); switch (b0) { case VGM_GGST: // GG stereo (1 byte data) // Just pass it through b1=gzgetc(in); gzputc(out,VGM_GGST); gzputc(out,b1); break; case VGM_PSG: // PSG write (1 byte data) b1=gzgetc(in); if (b1&0x80) { // Latch/data byte %1 cc t dddd PSGLatchedRegister=((b1>>4)&0x07); PSGRegisters[PSGLatchedRegister]= (PSGRegisters[PSGLatchedRegister] & 0x3f0) // zero low 4 bits | (b1&0xf); // and replace with data } else { // Data byte if (!(PSGLatchedRegister%2)&&(PSGLatchedRegister<5)) // Tone register PSGRegisters[PSGLatchedRegister]= (PSGRegisters[PSGLatchedRegister] & 0x00f) // zero high 6 bits | ((b1&0x3f)<<4); // and replace with data else // Other register PSGRegisters[PSGLatchedRegister]=b1&0x0f; // Replace with data } // Analyse: switch (PSGLatchedRegister) { case 0: case 2: case 4: // Tone registers if ((PSGRegisters[PSGLatchedRegister]<PSGCutoff) && // If freq is too low !((PSGLatchedRegister==4)&&NoiseCh2) // and it's not tone2 controlling noise ) { // then silence that channel if (!SilencedChannels[PSGLatchedRegister/2]) { // If channel hasn't already been silenced ++NumOffsetsRemoved; gzputc(out,VGM_PSG); gzputc(out,(char)( 0x9f| // %10011111 (PSGLatchedRegister&0x6)<<4) // %0cc00000 ); // Remember I've done it SilencedChannels[PSGLatchedRegister/2]=TRUE; // Output zero frequency gzputc(out,VGM_PSG); gzputc(out,(char)(0x80|(PSGLatchedRegister<<4))); gzputc(out,VGM_PSG); gzputc(out,0); } } else { // Channel shouldn't be silent if (SilencedChannels[PSGLatchedRegister/2]) { // If I've previously silenced this channel // then restore the volume gzputc(out,VGM_PSG); gzputc(out,(char)( 0x90| // %10010000 (PSGLatchedRegister&0x6)<<4)| // %0cc00000 PSGRegisters[PSGLatchedRegister+1] // %0000vvvv ); SilencedChannels[PSGLatchedRegister/2]=FALSE; } // Write the frequency bytes gzputc(out,VGM_PSG); gzputc(out,(char)(0x80|(PSGLatchedRegister<<4)|PSGRegisters[PSGLatchedRegister]&0xf)); gzputc(out,VGM_PSG); gzputc(out,(char)(PSGRegisters[PSGLatchedRegister]>>4)); } break; case 6: // Noise // Detect if it's ch2 noise NoiseCh2=((PSGRegisters[6]&0x3)==0x3); // Pass through gzputc(out,VGM_PSG); gzputc(out,b1); break; default: // Volume if ((PSGLatchedRegister/2<3) && // Tone channel SilencedChannels[PSGLatchedRegister/2]) // Silenced break; // Don't write // Pass through gzputc(out,VGM_PSG); gzputc(out,b1); break; } // end switch break; case VGM_YM2413: // YM2413 case VGM_YM2612_0: // YM2612 port 0 case VGM_YM2612_1: // YM2612 port 1 case VGM_YM2151: // YM2151 case 0x55: // Reserved up to 0x5f case 0x56: // All have 2 bytes of data case 0x57: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: b1=gzgetc(in); b2=gzgetc(in); gzputc(out,b0); gzputc(out,b1); gzputc(out,b2); break; case VGM_PAUSE_WORD: // Wait n samples b1=gzgetc(in); b2=gzgetc(in); gzputc(out,VGM_PAUSE_WORD); gzputc(out,b1); gzputc(out,b2); break; case VGM_PAUSE_60TH: // Wait 1/60 s gzputc(out,VGM_PAUSE_60TH); break; case VGM_PAUSE_50TH: // Wait 1/50 s gzputc(out,VGM_PAUSE_50TH); break; // case VGM_PAUSE_BYTE: // Wait n samples // b1=gzgetc(in); // gzputc(out,VGM_PAUSE_BYTE); // gzputc(out,b1); // break; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: // Wait 1-16 samples gzputc(out,b0); break; case VGM_END: // End of sound data gzputc(out,VGM_END); break; default: break; }
// Donuts are a tasty treat and delicious with powdered sugar. void MDFNMOV_AddJoy(void *donutdata, uint32 donutlen) { gzFile fp; if(!current) return; /* Not playback nor recording. */ if(current < 0) /* Playback */ { int t; fp = slots[-1 - current]; while((t = gzgetc(fp)) >= 0 && t) { if(t == MDFNNPCMD_LOADSTATE) { uint32 len; StateMem sm; len = gzgetc(fp); len |= gzgetc(fp) << 8; len |= gzgetc(fp) << 16; len |= gzgetc(fp) << 24; if(len >= 5 * 1024 * 1024) // A sanity limit of 5MiB { StopPlayback(); return; } memset(&sm, 0, sizeof(StateMem)); sm.len = len; sm.data = (uint8 *)malloc(len); if(gzread(fp, sm.data, len) != len) { StopPlayback(); return; } if(!MDFNSS_LoadSM(&sm, 0, 0)) { StopPlayback(); return; } } else MDFN_DoSimpleCommand(t); } if(t < 0) { StopPlayback(); return; } if(gzread(fp, donutdata, donutlen) != donutlen) { StopPlayback(); return; } } else /* Recording */ { if(MDFN_StateEvilIsRunning()) { smem_putc(&RewindBuffer, 0); smem_write(&RewindBuffer, donutdata, donutlen); } else { fp = slots[current - 1]; gzputc(fp, 0); gzwrite(fp, donutdata, donutlen); } } }
TInt CTestlibz::libzgzio() { __UHEAP_MARK; #ifdef NO_GZCOMPRESS INFO_PRINT1(_L("NO_GZCOMPRESS -- gz* functions cannot compress")); return KErrNone; #else const char Buffer[] = "Symbian Libz!"; Byte uncompr[15]; char fname[] = "C:\\Libz\\Test1\\bye.gz"; int err = 0; int len; gzFile file; z_off_t pos; err = iRfile.Create(iRfs, KGZFILE, EFileShareAny); if( err != KErrNone && err != KErrAlreadyExists ) { INFO_PRINTF1(_L("File create successfully\n")); return KErrGeneral; } len = (int)strlen(Buffer)+1; //-------------gzopen()------------------ INFO_PRINTF1(_L("gzopen()\n")); file = gzopen(fname, "wb"); if (file == NULL) { INFO_PRINTF1(_L("gzopen error")); return KErrGeneral; } //-------------gzputc() ------------ INFO_PRINTF1(_L("gputc()\n")); gzputc(file, 'S'); if (gzputs(file, "ymbian") != 6) { INFO_PRINTF2(_L("gzputs err: %s\n"), gzerror(file, &err)); return KErrGeneral; } //-------------gzprintf() ------------ INFO_PRINTF1(_L("gzprintf()\n")); if (gzprintf(file, " %s!", "Libz") != 6) { INFO_PRINTF2(_L("gzprintf err: %s\n"), gzerror(file, &err)); return KErrGeneral; } //-------------gzseek() ------------ INFO_PRINTF1(_L("gzseek()\n")); if(gzseek(file, 1L, SEEK_CUR) != 14){ /* add one zero byte */ INFO_PRINTF2(_L("gzseek err: %s\n"), gzerror(file, &err)); return KErrGeneral; } //-------------gzclose() ------------ INFO_PRINTF1(_L("gzclose()\n")); if(gzclose(file) == Z_ERRNO){ INFO_PRINTF2(_L("gzclose err: %s\n"), gzerror(file, &err)); return KErrGeneral; } //-------------gzopen()------------------ INFO_PRINTF1(_L("gzopen()\n")); file = gzopen(fname, "rb"); if (file == NULL) { INFO_PRINTF1(_L("gzopen error\n")); return KErrGeneral; } strcpy((char*)uncompr, "garbage"); //-------------gzread()------------------ INFO_PRINTF1(_L("gzread()\n")); if (gzread(file, uncompr, sizeof(uncompr)) != len) { INFO_PRINTF2(_L("gzread err: %s\n"), gzerror(file, &err)); return KErrGeneral; } if (strcmp((char*)uncompr, Buffer)) { INFO_PRINTF2(_L("bad gzread: %s\n"), (char*)uncompr); return KErrGeneral; } //-------------gzseek() & gztell()----------------- INFO_PRINTF1(_L("gzseek & gztell()\n")); pos = gzseek(file, -7L, SEEK_CUR); if (gztell(file) != pos || pos != 7) { INFO_PRINTF3(_L("gzseek error, pos=%ld, gztell=%ld\n"), (long)pos, (long)gztell(file)); return KErrGeneral; } //-------------gzgetc()------------------ INFO_PRINTF1(_L("gzgetc()\n")); if (gzgetc(file) != ' ') { INFO_PRINTF1(_L("gzgetc error")); return KErrGeneral; } //-------------gzungetc()------------------ INFO_PRINTF1(_L("gzungetc\n")); if (gzungetc(' ', file) != ' ') { INFO_PRINTF1(_L("gzungetc error\n")); return KErrGeneral; } //-------------gzgets()------------------ INFO_PRINTF1(_L("gzgets()\n")); gzgets(file, (char*)uncompr, sizeof(uncompr)); if (strlen((char*)uncompr) != 6) { /* " Libz!" */ INFO_PRINTF2(_L("gzgets err after gzseek: %s\n"), gzerror(file, &err)); return KErrGeneral; } if (strcmp((char*)uncompr, Buffer + 7)) { INFO_PRINTF1(_L("bad gzgets after gzseek\n")); return KErrGeneral; } //-------------gzclose() ------------ if(gzclose(file) == Z_ERRNO) { INFO_PRINTF2(_L("gzclose err: %s\n"), gzerror(file, &err)); return KErrGeneral; } #endif __UHEAP_MARKEND; return KErrNone; }
/* =========================================================================== * Test read/write of .gz files */ void test_gzio( const char *fname, Byte *uncompr, uLong uncomprLen) { #ifdef NO_GZCOMPRESS fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); #else int err; int len = (int)strlen(hello)+1; gzFile file; z_off_t pos; file = gzopen(fname, "wb"); if (file == NULL) { fprintf(stderr, "gzopen error\n"); exit(1); } gzputc(file, 'h'); if (gzputs(file, "ello") != 4) { fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); exit(1); } if (gzprintf(file, ", %s!", "hello") != 8) { fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); exit(1); } gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ gzclose(file); file = gzopen(fname, "rb"); if (file == NULL) { fprintf(stderr, "gzopen error\n"); exit(1); } strcpy((char*)uncompr, "garbage"); if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); exit(1); } if (strcmp((char*)uncompr, hello)) { fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); exit(1); } else { printf("gzread(): %s\n", (char*)uncompr); } pos = gzseek(file, -8L, SEEK_CUR); if (pos != 6 || gztell(file) != pos) { fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", (long)pos, (long)gztell(file)); exit(1); } if (gzgetc(file) != ' ') { fprintf(stderr, "gzgetc error\n"); exit(1); } if (gzungetc(' ', file) != ' ') { fprintf(stderr, "gzungetc error\n"); exit(1); } gzgets(file, (char*)uncompr, (int)uncomprLen); if (strlen((char*)uncompr) != 7) { /* " hello!" */ fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); exit(1); } if (strcmp((char*)uncompr, hello + 6)) { fprintf(stderr, "bad gzgets after gzseek\n"); exit(1); } else { printf("gzgets() after gzseek: %s\n", (char*)uncompr); } gzclose(file); #endif }
void gzput(int i) { gzputc(f, i); };
void GzipT::write(char Char) { auto Error = gzputc(mFile, Char); if (Error == 0) throw std::runtime_error{"Error writing gzip char" + mPath}; }