int LoadNSF(MDFNFILE *fp) { NSF_HEADER NSFHeader; fp->rewind(); fp->fread(&NSFHeader, 1, 0x80); // NULL-terminate strings just in case. NSFHeader.GameName[31] = NSFHeader.Artist[31] = NSFHeader.Copyright[31] = 0; NSFInfo->GameName = (UTF8*)MDFN_RemoveControlChars(strdup((char *)NSFHeader.GameName)); NSFInfo->Artist = (UTF8 *)MDFN_RemoveControlChars(strdup((char *)NSFHeader.Artist)); NSFInfo->Copyright = (UTF8 *)MDFN_RemoveControlChars(strdup((char *)NSFHeader.Copyright)); MDFN_trim((char*)NSFInfo->GameName); MDFN_trim((char*)NSFInfo->Artist); MDFN_trim((char*)NSFInfo->Copyright); NSFInfo->LoadAddr = NSFHeader.LoadAddressLow | (NSFHeader.LoadAddressHigh << 8); NSFInfo->InitAddr = NSFHeader.InitAddressLow | (NSFHeader.InitAddressHigh << 8); NSFInfo->PlayAddr = NSFHeader.PlayAddressLow | (NSFHeader.PlayAddressHigh << 8); NSFInfo->NSFSize = fp->Size() - 0x80; NSFInfo->NSFMaxBank = ((NSFInfo->NSFSize+(NSFInfo->LoadAddr&0xfff)+4095)/4096); NSFInfo->NSFMaxBank = round_up_pow2(NSFInfo->NSFMaxBank); if(!(NSFInfo->NSFDATA=(uint8 *)MDFN_malloc(NSFInfo->NSFMaxBank*4096, _("NSF data")))) return 0; fp->fseek(0x80, SEEK_SET); memset(NSFInfo->NSFDATA, 0x00, NSFInfo->NSFMaxBank*4096); fp->fread(NSFInfo->NSFDATA+(NSFInfo->LoadAddr&0xfff), 1, NSFInfo->NSFSize); NSFInfo->NSFMaxBank--; NSFInfo->VideoSystem = NSFHeader.VideoSystem; NSFInfo->SoundChip = NSFHeader.SoundChip; NSFInfo->TotalSongs = NSFHeader.TotalSongs; if(NSFHeader.StartingSong == 0) NSFHeader.StartingSong = 1; NSFInfo->StartingSong = NSFHeader.StartingSong - 1; memcpy(NSFInfo->BankSwitch, NSFHeader.BankSwitch, 8); return(1); }
static bool LoadCPalette(const char *syspalname, uint8 **ptr, uint32 num_entries) { std::string colormap_fn = MDFN_MakeFName(MDFNMKF_PALETTE, 0, syspalname).c_str(); MDFN_printf(_("Loading custom palette from \"%s\"...\n"), colormap_fn.c_str()); MDFN_indent(1); *ptr = NULL; try { FileStream fp(colormap_fn.c_str(), FileStream::MODE_READ); if(!(*ptr = (uint8 *)MDFN_malloc(num_entries * 3, _("custom color map")))) { MDFN_indent(-1); return(false); } fp.read(*ptr, num_entries * 3); } catch(MDFN_Error &e) { if(*ptr) { MDFN_free(*ptr); *ptr = NULL; } MDFN_printf(_("Error: %s\n"), e.what()); MDFN_indent(-1); return(e.GetErrno() == ENOENT); // Return fatal error if it's an error other than the file not being found. } catch(std::exception &e) { if(*ptr) { MDFN_free(*ptr); *ptr = NULL; } MDFN_printf(_("Error: %s\n"), e.what()); MDFN_indent(-1); return(false); } MDFN_indent(-1); return(true); }
// This function should ALWAYS close the system file "descriptor"(gzip library, zip library, or FILE *) it's given, // even if it errors out. bool MDFNFILE::MakeMemWrapAndClose(void *fp) { location = 0; ::fseek((FILE *)fp, 0, SEEK_END); f_size = ::ftell((FILE *)fp); ::fseek((FILE *)fp, 0, SEEK_SET); if (!(f_data = (uint8*)MDFN_malloc(f_size, _("file read buffer")))) goto fail; ::fread(f_data, 1, f_size, (FILE *)fp); return TRUE; fail: fclose((FILE*)fp); return FALSE; }
void MDFNSS_GetStateInfo(const char *filename, StateStatusStruct *status) { gzFile fp; uint32 StateShowPBWidth; uint32 StateShowPBHeight; uint8 *previewbuffer = NULL; fp = gzopen(filename, "rb"); if(fp) { uint8 header[32]; gzread(fp, header, 32); uint32 width = MDFN_de32lsb(header + 24); uint32 height = MDFN_de32lsb(header + 28); if(width > 1024) width = 1024; if(height > 1024) height = 1024; if(!(previewbuffer = (uint8 *)MDFN_malloc(3 * width * height, _("Save state preview buffer")))) { StateShowPBWidth = 0; StateShowPBHeight = 0; } else { gzread(fp, previewbuffer, 3 * width * height); StateShowPBWidth = width; StateShowPBHeight = height; } gzclose(fp); } else { StateShowPBWidth = MDFNGameInfo->nominal_width; StateShowPBHeight = MDFNGameInfo->nominal_height; } status->gfx = previewbuffer; status->w = StateShowPBWidth; status->h = StateShowPBHeight; }
int Mapper112_Init(CartInfo *info) { SetWriteHandler(0x8000,0xffff,Mapper112_write); SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x6000, 0x7FFF, CartBW); info->Power = Power; info->Close = Close; info->StateAction = StateAction; if(!(WRAM = (uint8 *)MDFN_malloc(8192,"WRAM"))) return(0); SetupCartPRGMapping(0x10, WRAM, 8192, 1); if(info->battery) { info->SaveGame[0] = WRAM; info->SaveGameLen[0] = 8192; } return(1); }
static int Load(const char *name, MDFNFILE *fp) { if(!(ngpc_rom.data = (uint8 *)MDFN_malloc(GET_FSIZE_PTR(fp), _("Cart ROM")))) return(0); ngpc_rom.length = GET_FSIZE_PTR(fp); memcpy(ngpc_rom.data, GET_FDATA_PTR(fp), GET_FSIZE_PTR(fp)); md5_context md5; md5.starts(); md5.update(ngpc_rom.data, ngpc_rom.length); md5.finish(MDFNGameInfo->MD5); rom_loaded(); MDFN_printf(_("ROM: %dKiB\n"), (ngpc_rom.length + 1023) / 1024); MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str()); MDFNMP_Init(1024, 1024 * 1024 * 16 / 1024); NGPGfx = new NGPGFX_CLASS(); MDFNGameInfo->fps = (uint32)((uint64)6144000 * 65536 * 256 / 515 / 198); // 3072000 * 2 * 10000 / 515 / 198 MDFNGameInfo->GameSetMD5Valid = FALSE; MDFNNGPCSOUND_Init(); MDFNMP_AddRAM(16384, 0x4000, CPUExRAM); SetFRM(); // Set up fast read memory mapping bios_install(); //main_timeaccum = 0; z80_runtime = 0; reset(); return(1); }
bool MDFNFILE::ApplyIPS(FILE *ips) { uint8 header[5]; uint32 count = 0; //MDFN_printf(_("Applying IPS file \"%s\"...\n"), path); MDFN_indent(1); if(::fread(header, 1, 5, ips) != 5) { ErrnoHolder ene(errno); MDFN_PrintError(_("Error reading IPS file header: %s"), ene.StrError()); MDFN_indent(-1); return(0); } if(memcmp(header, "PATCH", 5)) { MDFN_PrintError(_("IPS file header is invalid.")); MDFN_indent(-1); return(0); } #ifdef HAVE_MMAP // If the file is mmap()'d, move it to malloc()'d RAM if(is_mmap) { void *tmp_ptr = MDFN_malloc(f_size, _("file read buffer")); if(!tmp_ptr) { //Close(); //fclose(ipsfile); return(0); } memcpy(tmp_ptr, f_data, f_size); munmap(f_data, f_size); is_mmap = FALSE; f_data = (uint8 *)tmp_ptr; } #endif while(::fread(header, 1, 3, ips) == 3) { uint32 offset = (header[0] << 16) | (header[1] << 8) | header[2]; uint8 patch_size_raw[2]; uint32 patch_size; bool rle = false; if(!memcmp(header, "EOF", 3)) { MDFN_printf(_("IPS EOF: Did %d patches\n\n"), count); MDFN_indent(-1); return(1); } if(::fread(patch_size_raw, 1, 2, ips) != 2) { ErrnoHolder ene(errno); MDFN_PrintError(_("Error reading IPS patch length: %s"), ene.StrError()); return(0); } patch_size = MDFN_de16msb(patch_size_raw); if(!patch_size) /* RLE */ { if(::fread(patch_size_raw, 1, 2, ips) != 2) { ErrnoHolder ene(errno); MDFN_PrintError(_("Error reading IPS RLE patch length: %s"), ene.StrError()); return(0); } patch_size = MDFN_de16msb(patch_size_raw); // Is this right? if(!patch_size) patch_size = 65536; rle = true; //MDFN_printf(" Offset: %8d Size: %5d RLE\n",offset, patch_size); } if((offset + patch_size) > f_size) { uint8 *tmp; //printf("%d\n", offset + patch_size, f_size); if((offset + patch_size) > MaxROMImageSize) { MDFN_PrintError(_("ROM image will be too large after IPS patch; maximum size allowed is %llu bytes."), (unsigned long long)MaxROMImageSize); return(0); } if(!(tmp = (uint8 *)MDFN_realloc(f_data, offset + patch_size, _("file read buffer")))) return(0); // Zero newly-allocated memory memset(tmp + f_size, 0, (offset + patch_size) - f_size); f_size = offset + patch_size; f_data = tmp; } if(rle) { const int b = ::fgetc(ips); uint8 *start = f_data + offset; if(EOF == b) { ErrnoHolder ene(errno); MDFN_PrintError(_("Error reading IPS RLE patch byte: %s"), ene.StrError()); return(0); } while(patch_size--) { *start=b; start++; } } else /* Normal patch */ { //MDFN_printf(" Offset: %8d Size: %5d\n", offset, patch_size); if(::fread(f_data + offset, 1, patch_size, ips) != patch_size) { ErrnoHolder ene(errno); MDFN_PrintError(_("Error reading IPS patch: %s"), ene.StrError()); return(0); } } count++; } ErrnoHolder ene(errno); //MDFN_printf(_("Warning: IPS ended without an EOF chunk.\n")); //MDFN_printf(_("IPS EOF: Did %d patches\n\n"), count); MDFN_indent(-1); MDFN_PrintError(_("Error reading IPS patch header: %s"), ene.StrError()); return(0); //return(1); }
// This function should ALWAYS close the system file "descriptor"(gzip library, zip library, or FILE *) it's given, // even if it errors out. bool MDFNFILE::MakeMemWrap(void *tz, int type) { bool ret = FALSE; #ifdef HAVE_MMAP is_mmap = FALSE; #endif location = 0; if(type == MDFN_FILETYPE_PLAIN) { ::fseek((FILE *)tz, 0, SEEK_END); f_size = ::ftell((FILE *)tz); ::fseek((FILE *)tz, 0, SEEK_SET); if(size > MaxROMImageSize) { MDFN_PrintError(_("ROM image is too large; maximum size allowed is %llu bytes."), (unsigned long long)MaxROMImageSize); goto doret; } #ifdef HAVE_MMAP if((void *)-1 != (f_data = (uint8 *)mmap(NULL, size, PROT_READ, MAP_SHARED, fileno((FILE *)tz), 0))) { //puts("mmap'ed"); is_mmap = TRUE; #ifdef HAVE_MADVISE if(0 == madvise(f_data, size, MADV_SEQUENTIAL | MADV_WILLNEED)) { //puts("madvised"); } #endif } else { #endif if(!(f_data = (uint8*)MDFN_malloc(size, _("file read buffer")))) { goto doret; } if((int64)::fread(f_data, 1, size, (FILE *)tz) != size) { free(f_data); goto doret; } #ifdef HAVE_MMAP } #endif } else if(type == MDFN_FILETYPE_GZIP) { uint32_t cur_size = 0; uint32_t cur_alloced = 65536; int howmany; if(!(f_data = (uint8*)MDFN_malloc(cur_alloced, _("file read buffer")))) { goto doret; } while((howmany = gzread(tz, f_data + cur_size, cur_alloced - cur_size)) > 0) { cur_size += howmany; cur_alloced <<= 1; if(!(f_data = (uint8 *)MDFN_realloc(f_data, cur_alloced, _("file read buffer")))) { goto doret; } } if(!(f_data = (uint8 *)MDFN_realloc(f_data, cur_size, _("file read buffer")))) { goto doret; } f_size = cur_size; } else if(type == MDFN_FILETYPE_ZIP) { unz_file_info ufo; unzGetCurrentFileInfo(tz, &ufo, 0, 0, 0, 0, 0, 0); f_size = ufo.uncompressed_size; if(size > MaxROMImageSize) { MDFN_PrintError(_("ROM image is too large; maximum size allowed is %llu bytes."), (unsigned long long)MaxROMImageSize); goto doret; } if(!(f_data=(uint8 *)MDFN_malloc(ufo.uncompressed_size, _("file read buffer")))) { goto doret; } unzReadCurrentFile(tz, f_data, ufo.uncompressed_size); } ret = TRUE; doret: if(type == MDFN_FILETYPE_PLAIN) { fclose((FILE *)tz); } else if(type == MDFN_FILETYPE_GZIP) { gzclose(tz); } else if(type == MDFN_FILETYPE_ZIP) { unzCloseCurrentFile(tz); unzClose(tz); } return(ret); }
void HuC_Load(const uint8 *data, uint32 len, uint32 crc32) { try { uint32 sf2_threshold = 2048 * 1024; uint32 sf2_required_size = 2048 * 1024 + 512 * 1024; uint32 m_len = (len + 8191)&~8191; bool sf2_mapper = FALSE; if(m_len >= sf2_threshold) { sf2_mapper = TRUE; if(m_len != sf2_required_size) m_len = sf2_required_size; } IsPopulous = 0; PCE_IsCD = 0; md5_context md5; md5.starts(); md5.update(data, len); md5.finish(MDFNGameInfo->MD5); MDFN_printf(_("ROM: %dKiB\n"), (len + 1023) / 1024); MDFN_printf(_("ROM CRC32: 0x%04x\n"), crc32); MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str()); HuCROM = (uint8 *)MDFN_malloc(m_len, _("HuCard ROM")); memset(HuCROM, 0xFF, m_len); memcpy(HuCROM, data, (m_len < len) ? m_len : len); memset(ROMSpace, 0xFF, 0x88 * 8192 + 8192); if(m_len == 0x60000) { memcpy(ROMSpace + 0x00 * 8192, HuCROM, 0x20 * 8192); memcpy(ROMSpace + 0x20 * 8192, HuCROM, 0x20 * 8192); memcpy(ROMSpace + 0x40 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192); memcpy(ROMSpace + 0x50 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192); memcpy(ROMSpace + 0x60 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192); memcpy(ROMSpace + 0x70 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192); } else if(m_len == 0x80000) { memcpy(ROMSpace + 0x00 * 8192, HuCROM, 0x40 * 8192); memcpy(ROMSpace + 0x40 * 8192, HuCROM + 0x20 * 8192, 0x20 * 8192); memcpy(ROMSpace + 0x60 * 8192, HuCROM + 0x20 * 8192, 0x20 * 8192); } else { memcpy(ROMSpace + 0x00 * 8192, HuCROM, (m_len < 1024 * 1024) ? m_len : 1024 * 1024); } for(int x = 0x00; x < 0x80; x++) { HuCPUFastMap[x] = ROMSpace; PCERead[x] = HuCRead; } if(!memcmp(HuCROM + 0x1F26, "POPULOUS", strlen("POPULOUS"))) { uint8 *PopRAM = ROMSpace + 0x40 * 8192; gzFile fp; memset(PopRAM, 0xFF, 32768); if((fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb"))) { gzread(fp, PopRAM, 32768); gzclose(fp); } IsPopulous = 1; MDFN_printf("Populous\n"); for(int x = 0x40; x < 0x44; x++) { HuCPUFastMap[x] = &PopRAM[(x & 3) * 8192] - x * 8192; PCERead[x] = HuCRead; PCEWrite[x] = HuCRAMWrite; } MDFNMP_AddRAM(32768, 0x40 * 8192, PopRAM); } else { gzFile fp; memset(SaveRAM, 0x00, 2048); memcpy(SaveRAM, BRAM_Init_String, 8); // So users don't have to manually intialize the file cabinet // in the CD BIOS screen. if((fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb"))) { gzread(fp, SaveRAM, 2048); gzclose(fp); } PCEWrite[0xF7] = SaveRAMWrite; PCERead[0xF7] = SaveRAMRead; MDFNMP_AddRAM(2048, 0xF7 * 8192, SaveRAM); } // 0x1A558 //if(len >= 0x20000 && !memcmp(HuCROM + 0x1A558, "STREET FIGHTER#", strlen("STREET FIGHTER#"))) if(sf2_mapper) { for(int x = 0x40; x < 0x80; x++) { // FIXME: PCE_FAST HuCPUFastMap[x] = NULL; // Make sure our reads go through our read function, and not a table lookup PCERead[x] = HuCSF2Read; } PCEWrite[0] = HuCSF2Write; MDFN_printf("Street Fighter 2 Mapper\n"); HuCSF2Latch = 0; } } catch(...) { Cleanup(); throw; } }
int PCE_HESLoad(const uint8 *buf, uint32 size) { uint32 LoadAddr, LoadSize; uint32 CurPos; uint16 InitAddr; uint8 StartingSong; int TotalSongs; InitAddr = MDFN_de16lsb(&buf[0x6]); CurPos = 0x10; if(!(rom = (uint8 *)MDFN_malloc(0x88 * 8192, _("HES ROM")))) { return(0); } if(!(rom_backup = (uint8 *)MDFN_malloc(0x88 * 8192, _("HES ROM")))) { return(0); } memset(rom, 0, 0x88 * 8192); memset(rom_backup, 0, 0x88 * 8192); while(CurPos < (size - 0x10)) { LoadSize = MDFN_de32lsb(&buf[CurPos + 0x4]); LoadAddr = MDFN_de32lsb(&buf[CurPos + 0x8]); //printf("Size: %08x(%d), Addr: %08x, La: %02x\n", LoadSize, LoadSize, LoadAddr, LoadAddr / 8192); CurPos += 0x10; if(((uint64)LoadSize + CurPos) > size) { uint32 NewLoadSize = size - CurPos; MDFN_printf(_("Warning: HES is trying to load more data than is present in the file(%u attempted, %u left)!\n"), LoadSize, NewLoadSize); LoadSize = NewLoadSize; } // 0x88 * 8192 = 0x110000 if(((uint64)LoadAddr + LoadSize) > 0x110000) { MDFN_printf(_("Warning: HES is trying to load data past boundary.\n")); if(LoadAddr >= 0x110000) break; LoadSize = 0x110000 - LoadAddr; } memcpy(rom + LoadAddr, &buf[CurPos], LoadSize); CurPos += LoadSize; } for(int x = 0; x < 8; x++) mpr_start[x] = buf[0x8 + x]; memcpy(rom_backup, rom, 0x88 * 8192); CurrentSong = StartingSong = buf[5]; TotalSongs = 256; memset(IBP_Bank, 0, 0x2000); uint8 *IBP_WR = IBP_Bank + 0x1C00; for(int i = 0; i < 8; i++) { *IBP_WR++ = 0xA9; // LDA (immediate) *IBP_WR++ = mpr_start[i]; *IBP_WR++ = 0x53; // TAM *IBP_WR++ = 1 << i; } *IBP_WR++ = 0xAD; // LDA(absolute) *IBP_WR++ = 0x00; // *IBP_WR++ = 0x1D; // *IBP_WR++ = 0x20; // JSR *IBP_WR++ = InitAddr; // JSR target LSB *IBP_WR++ = InitAddr >> 8; // JSR target MSB *IBP_WR++ = 0x58; // CLI *IBP_WR++ = 0xFC; // (Mednafen Special) *IBP_WR++ = 0x80; // BRA *IBP_WR++ = 0xFD; // -3 Player_Init(TotalSongs, NULL, NULL, NULL, NULL); //UTF8 **snames); for(int x = 0; x < 0x80; x++) { HuCPUFastMap[x] = rom; PCERead[x] = HESROMRead; PCEWrite[x] = HESROMWrite; } HuCPUFastMap[0xFF] = IBP_Bank - (0xFF * 8192); // FIXME: If a HES rip tries to execute a SCSI command, the CD emulation code will probably crash. Obviously, a HES rip shouldn't do this, // but Mednafen shouldn't crash either. ;) PCE_IsCD = 1; PCE_InitCD(); ROMWriteWarningGiven = FALSE; return(1); }
bool NSFLoad(const char *name, MDFNFILE *fp, NESGameType *gt) { char magic[5]; int x; if(!(NSFInfo = (NSFINFO *)MDFN_malloc(sizeof(NSFINFO), _("NSF header")))) { return(0); } memset(NSFInfo, 0, sizeof(NSFINFO)); fp->rewind(); fp->fread(magic, 1, 5); if(!memcmp(magic, "NESM\x1a", 5)) { if(!LoadNSF(fp)) { FreeNSF(); return(0); } } else if(!memcmp(magic, "NSFE", 4)) { if(!LoadNSFE(NSFInfo, fp->data, fp->Size(), 0)) { FreeNSF(); return(0); } } else { FreeNSF(); return(FALSE); } if(NSFInfo->LoadAddr < 0x6000) { MDFNI_printf(_("Load address is invalid!")); FreeNSF(); return(0); } if(NSFInfo->TotalSongs < 1) { MDFNI_printf(_("Total number of songs is less than 1!")); FreeNSF(); return(0); } BSon = 0; for(x=0;x<8;x++) BSon |= NSFInfo->BankSwitch[x]; MDFNGameInfo->GameType = GMT_PLAYER; if(NSFInfo->GameName) MDFNGameInfo->name = (UTF8*)strdup((char*)NSFInfo->GameName); for(x=0;;x++) { if(NSFROM[x]==0x20) { NSFROM[x+1]=NSFInfo->InitAddr&0xFF; NSFROM[x+2]=NSFInfo->InitAddr>>8; NSFROM[x+8]=NSFInfo->PlayAddr&0xFF; NSFROM[x+9]=NSFInfo->PlayAddr>>8; break; } }
int MDFN_SavePNGSnapshot(const char *fname, uint32 *fb, const MDFN_Rect *rect, uint32 pitch) { int x, y; FILE *pp=NULL; uint8 *compmem = NULL; uLongf compmemsize = (uLongf)( (rect->h * (rect->w + 1) * 3 * 1.001 + 1) + 12 ); if(!(compmem=(uint8 *)MDFN_malloc(compmemsize, _("PNG compression buffer")))) return 0; if(!(pp=fopen(fname, "wb"))) { return 0; } { static uint8 header[8]={137,80,78,71,13,10,26,10}; if(fwrite(header,8,1,pp)!=1) goto PNGerr; } { uint8 chunko[13]; chunko[0] = rect->w >> 24; // Width chunko[1] = rect->w >> 16; chunko[2] = rect->w >> 8; chunko[3] = rect->w; chunko[4] = rect->h >> 24; // Height chunko[5] = rect->h >> 16; chunko[6] = rect->h >> 8; chunko[7] = rect->h; chunko[8]=8; // 8 bits per sample(24 bits per pixel) chunko[9]=2; // Color type; RGB triplet chunko[10]=0; // compression: deflate chunko[11]=0; // Basic adapative filter set(though none are used). chunko[12]=0; // No interlace. if(!WritePNGChunk(pp,13,"IHDR",chunko)) goto PNGerr; } { uint8 *tmp_buffer; uint8 *tmp_inc; tmp_inc = tmp_buffer = (uint8 *)malloc((rect->w * 3 + 1) * rect->h); for(y=0;y<rect->h;y++) { *tmp_inc = 0; tmp_inc++; for(x=0;x<rect->w;x++) { int r,g,b; DECOMP_COLOR(*(uint32 *)((uint8 *)fb + (y + rect->y) * pitch + (x + rect->x) * 4), r, g, b); tmp_inc[0] = r; tmp_inc[1] = g; tmp_inc[2] = b; tmp_inc += 3; } } if(compress(compmem, &compmemsize, tmp_buffer, rect->h * (rect->w * 3 + 1))!=Z_OK) { if(tmp_buffer) free(tmp_buffer); goto PNGerr; } if(tmp_buffer) free(tmp_buffer); if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem)) goto PNGerr; } if(!WritePNGChunk(pp,0,"IEND",0)) goto PNGerr; free(compmem); fclose(pp); return 1; PNGerr: if(compmem) free(compmem); if(pp) fclose(pp); return(0); }