diff --git a/src/common/PNGLibrary.cxx b/src/common/PNGLibrary.cxx index 67988b79c..5da26df03 100644 --- a/src/common/PNGLibrary.cxx +++ b/src/common/PNGLibrary.cxx @@ -17,6 +17,10 @@ // $Id$ //============================================================================ +#include +#include + +#include "bspf.hxx" #include "PNGLibrary.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -31,8 +35,176 @@ PNGLibrary::~PNGLibrary() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* - PNGLibrary::readImage(uInt32& width, uInt32& height, StringList& text) +bool PNGLibrary::readImage(const FrameBuffer& fb, FBSurface& surface) { - return 0; + #define readImageERROR(s) { err_message = s; goto error; } + + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_bytep* row_pointers = NULL; + png_uint_32 iwidth, iheight, ipitch; + uInt8* buffer = NULL; + int bit_depth, color_type, interlace_type; + string err_message; + + ifstream* in = new ifstream(myFilename.c_str(), ios_base::binary); + if(!in || !in->is_open()) + readImageERROR("No image found") + + // Create the PNG loading context structure + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + png_user_error, png_user_warn); + if(png_ptr == NULL) + readImageERROR("Couldn't allocate memory for PNG file") + + // Allocate/initialize the memory for image information. REQUIRED. + info_ptr = png_create_info_struct(png_ptr); + if(info_ptr == NULL) + readImageERROR("Couldn't create image information for PNG file") + + // Set up the input control + png_set_read_fn(png_ptr, in, png_read_data); + + // Read PNG header info + png_read_info(png_ptr, info_ptr); + png_get_IHDR(png_ptr, info_ptr, &iwidth, &iheight, &bit_depth, + &color_type, &interlace_type, NULL, NULL); + + // Tell libpng to strip 16 bit/color files down to 8 bits/color + png_set_strip_16(png_ptr); + + // Extract multiple pixels with bit depths of 1, 2, and 4 from a single + // byte into separate bytes (useful for paletted and grayscale images). + png_set_packing(png_ptr); + + // Greyscale mode not supported + if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + readImageERROR("Greyscale PNG images not supported") + + // Create space for the entire image (3 bytes per pixel in RGB format) + ipitch = iwidth * 3; + buffer = new uInt8[ipitch * iheight]; + if(buffer == NULL) + readImageERROR("Not enough memory to read PNG file") + + // The PNG read function expects an array of rows, not a single 1-D array + row_pointers = new png_bytep[iheight]; + for(uInt32 irow = 0, offset = 0; irow < iheight; ++irow, offset += ipitch) + row_pointers[irow] = (png_bytep) (uInt8*)buffer + offset; + + // Read the entire image in one go + png_read_image(png_ptr, row_pointers); + delete[] row_pointers; + + // We're finished reading + png_read_end(png_ptr, info_ptr); + + // Scale image to surface dimensions + scaleImagetoSurface(iwidth, iheight, buffer, fb, surface); + + // Cleanup + if(png_ptr) + png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : (png_infopp)0, (png_infopp)0); + if(in) + in->close(); + delete[] buffer; + + return true; + +error: + if(png_ptr) + png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : (png_infopp)0, (png_infopp)0); + if(in) + in->close(); + delete[] buffer; + + throw err_message.c_str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PNGLibrary::scaleImagetoSurface(uInt32 iwidth, uInt32 iheight, uInt8* buffer, + const FrameBuffer& fb, FBSurface& surface) +{ + // Figure out the original zoom level of the snapshot + // All snapshots generated by Stella are at most some multiple of 320 + // pixels wide + // The only complication is when the aspect ratio is changed, the width + // can range from 256 (80%) to 320 (100%) + // The following calculation will work up to approx. 16x zoom level, + // but since Stella only generates snapshots at up to 10x, we should + // be fine for a while ... + uInt32 izoom = uInt32(ceil(iwidth/320.0)), + szoom = surface.getWidth()/320.0; + + // Set the surface size + uInt32 sw = iwidth / izoom * szoom, + sh = iheight / izoom * szoom; + sw = BSPF_min(sw, surface.getWidth()); + sh = BSPF_min(sh, surface.getHeight()); + surface.setWidth(sw); + surface.setHeight(sh); + + // Decompress the image, and scale it correctly + uInt32 ipitch = iwidth * 3; // bytes per line of the actual PNG image + uInt32* line = new uInt32[ipitch]; + + uInt32 buf_offset = ipitch * izoom; + uInt32 i_offset = 3 * izoom; + + // We can only scan at most the height of the surface + iheight = BSPF_min(iheight, surface.getHeight()); + + // Grab each non-duplicate row of data from the image + for(uInt32 irow = 0, srow = 0; irow < iheight; irow += izoom, buffer += buf_offset) + { + // Scale the image data into the temporary line buffer + uInt8* i_ptr = buffer; + uInt32* l_ptr = line; + for(uInt32 icol = 0; icol < iwidth; icol += izoom, i_ptr += i_offset) + { + uInt32 pixel = fb.mapRGB(*i_ptr, *(i_ptr+1), *(i_ptr+2)); + uInt32 xstride = szoom; + while(xstride--) + *l_ptr++ = pixel; + } + + // Then fill the surface with those bytes + uInt32 ystride = szoom; + while(ystride--) + surface.drawPixels(line, 0, srow++, sw); + } + delete[] line; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PNGLibrary::png_read_data(png_structp ctx, png_bytep area, png_size_t size) +{ + ifstream* stream = (ifstream *) png_get_io_ptr(ctx); + stream->read((char *)area, size); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PNGLibrary::png_write_data(png_structp ctx, png_bytep area, png_size_t size) +{ + ofstream* stream = (ofstream *) png_get_io_ptr(ctx); + stream->write((const char *)area, size); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PNGLibrary::png_io_flush(png_structp ctx) +{ + ofstream* stream = (ofstream *) png_get_io_ptr(ctx); + stream->flush(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PNGLibrary::png_user_warn(png_structp ctx, png_const_charp str) +{ + cout << "PNGLibrary warning: " << str << endl; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PNGLibrary::png_user_error(png_structp ctx, png_const_charp str) +{ + cout << "PNGLibrary error: " << str << endl; } diff --git a/src/common/PNGLibrary.hxx b/src/common/PNGLibrary.hxx index 9ce0d7aff..fdb737067 100644 --- a/src/common/PNGLibrary.hxx +++ b/src/common/PNGLibrary.hxx @@ -23,6 +23,7 @@ #include #include "bspf.hxx" +#include "FrameBuffer.hxx" #include "StringList.hxx" /** @@ -40,17 +41,36 @@ class PNGLibrary ~PNGLibrary(); /** - Read a PNG image from the previously specified file. + Read a PNG image from the previously specified file into a + FBSurface structure, scaling the image to the surface bounds. - @param width The width of the image that was read - @param height The height of the image that was read - @param text Any tEXt chunks that were present in the input file + @param fb The main framebuffer of the application + @param surface The FBSurface into which to place the PNG data - @return On success, a buffer containing image data, otherwise - an exception is thrown. Note that the caller IS NOT - responsible for deleting the buffer array. + @return On success, the FBSurface containing image data and a + result of true, otherwise an exception is thrown. */ - const uInt8* readImage(uInt32& width, uInt32& height, StringList& text); + bool readImage(const FrameBuffer& fb, FBSurface& surface); + + private: + /** + Scale the PNG data from 'buffer' into the FBSurface. For now, scaling + is done on integer boundaries only (ie, 1x, 2x, etc up or down). + + @param iwidth Width of the PNG data (3 bytes per pixel) + @param iheight Number of row of PNG data + @param buffer The PNG data + @param fb The main framebuffer of the application + @param surface The FBSurface into which to place the PNG data + */ + static void scaleImagetoSurface(uInt32 iwidth, uInt32 iheight, uInt8* buffer, + const FrameBuffer& fb, FBSurface& surface); + + static void png_read_data(png_structp ctx, png_bytep area, png_size_t size); + static void png_write_data(png_structp ctx, png_bytep area, png_size_t size); + static void png_io_flush(png_structp ctx); + static void png_user_warn(png_structp ctx, png_const_charp str); + static void png_user_error(png_structp ctx, png_const_charp str); private: string myFilename; diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx index 099e025c8..6df6e1637 100644 --- a/src/gui/RomInfoWidget.cxx +++ b/src/gui/RomInfoWidget.cxx @@ -17,12 +17,9 @@ // $Id$ //============================================================================ -#include -#include -#include - #include "FrameBuffer.hxx" #include "OSystem.hxx" +#include "PNGLibrary.hxx" #include "Settings.hxx" #include "Widget.hxx" @@ -96,82 +93,37 @@ void RomInfoWidget::parseProperties() mySurface = instance().frameBuffer().surface(mySurfaceID); if(mySurface == NULL) { - // For some reason, we need to allocate a buffer slightly higher than - // the maximum that Stella can generate mySurfaceID = instance().frameBuffer().allocateSurface( - 320*myZoomLevel, 257*myZoomLevel, false); + 320*myZoomLevel, 256*myZoomLevel, false); mySurface = instance().frameBuffer().surface(mySurfaceID); } + else + { + mySurface->setWidth(320*myZoomLevel); + mySurface->setHeight(256*myZoomLevel); + } // Initialize to empty properties entry mySurfaceErrorMsg = ""; mySurfaceIsValid = false; myRomInfo.clear(); - // The input stream for the PNG file - ifstream in; - - // Contents of each PNG chunk - string type = ""; - uInt8* data = NULL; - int size = 0; - - // 'tEXt' chucks from the PNG image - StringList textChucks; - // Get a valid filename representing a snapshot file for this rom const string& filename = instance().snapshotDir() + BSPF_PATH_SEPARATOR + myProperties.get(Cartridge_Name) + ".png"; - // Open the PNG and check for a valid signature - in.open(filename.c_str(), ios_base::binary); - if(in) + // Read the PNG file + try { - try - { - uInt8 header[8]; - in.read((char*)header, 8); - if(!isValidPNGHeader(header)) - throw "Invalid PNG image"; - - // Read all chunks until we reach the end - int width = 0, height = 0; - while(type != "IEND" && !in.eof()) - { - readPNGChunk(in, type, &data, size); - - if(type == "IHDR") - { - if(!parseIHDR(width, height, data, size)) - throw "Invalid PNG image (IHDR)"; - } - else if(type == "IDAT") - { - if(!parseIDATChunk(mySurface, width, height, data, size)) - throw "Invalid PNG image (IDAT)"; - } - else if(type == "tEXt") - textChucks.push_back(parseTextChunk(data, size)); - - delete[] data; data = NULL; - } - - in.close(); - mySurfaceIsValid = true; - } - catch(const char* msg) - { - mySurfaceIsValid = false; - myRomInfo.clear(); - if(data) delete[] data; - data = NULL; - in.close(); - - mySurfaceErrorMsg = msg; - } + PNGLibrary png(filename); + mySurfaceIsValid = + png.readImage(instance().frameBuffer(), *mySurface); + } + catch(const char* msg) + { + mySurfaceIsValid = false; + mySurfaceErrorMsg = msg; } - else - mySurfaceErrorMsg = "No image found"; // Now add some info for the message box below the image myRomInfo.push_back("Name: " + myProperties.get(Cartridge_Name)); @@ -181,7 +133,6 @@ void RomInfoWidget::parseProperties() myRomInfo.push_back("Note: " + myProperties.get(Cartridge_Note)); myRomInfo.push_back("Controllers: " + myProperties.get(Controller_Left) + " (left), " + myProperties.get(Controller_Right) + " (right)"); - // TODO - add the PNG tEXt chunks } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -218,127 +169,6 @@ void RomInfoWidget::drawWidget(bool hilite) } } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool RomInfoWidget::isValidPNGHeader(uInt8* header) -{ - // Unique signature indicating a PNG image file - uInt8 signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; - - return memcmp(header, signature, 8) == 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void RomInfoWidget::readPNGChunk(ifstream& in, string& type, - uInt8** data, int& size) -{ - uInt8 temp[9]; - temp[8] = '\0'; - - // Get the size and type from the 8-byte header - in.read((char*)temp, 8); - size = temp[0] << 24 | temp[1] << 16 | temp[2] << 8 | temp[3]; - type = string((const char*)temp+4); - - // Now read the payload - if(size > 0) - { - *data = new uInt8[size]; - in.read((char*) *data, size); - } - - // Read (and discard) the 4-byte CRC - in.read((char*)temp, 4); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool RomInfoWidget::parseIHDR(int& width, int& height, uInt8* data, int size) -{ - // We only support the PNG functionality defined in Snapshot.cxx - // Specifically, 24 bpp RGB data; any other formats are ignored - - if(size != 13) - return false; - - width = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; - height = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; - - uInt8 trailer[5] = { 8, 2, 0, 0, 0 }; // 24-bit RGB - return memcmp(trailer, data + 8, 5) == 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool RomInfoWidget::parseIDATChunk(FBSurface* surface, int width, int height, - uInt8* data, int size) -{ - // Figure out the original zoom level of the snapshot - // All snapshots generated by Stella are at most some multiple of 320 - // pixels wide - // The only complication is when the aspect ratio is changed, the width - // can range from 256 (80%) to 320 (100%) - // The following calculation will work up to approx. 16x zoom level, - // but since Stella only generates snapshots at up to 10x, we should - // be fine for a while ... - uInt32 izoom = uInt32(ceil(width/320.0)); - - // Set the surface size - uInt32 sw = width / izoom * myZoomLevel, - sh = height / izoom * myZoomLevel; - sw = BSPF_min(sw, myZoomLevel * 320u); - sh = BSPF_min(sh, myZoomLevel * 256u); - mySurface->setWidth(sw); - mySurface->setHeight(sh); - - // Decompress the image, and scale it correctly - uInt32 ipitch = width * 3 + 1; // bytes per line of the actual PNG image - uLongf bufsize = ipitch * height; - uInt8* buffer = new uInt8[bufsize]; - uInt32* line = new uInt32[ipitch]; - - if(uncompress(buffer, &bufsize, data, size) == Z_OK) - { - uInt8* buf_ptr = buffer + 1; // skip past first column (PNG filter type) - uInt32 buf_offset = ipitch * izoom; - uInt32 i_offset = 3 * izoom; - uInt32 srow = 0; - - // We can only scan at most izoom*256 lines - height = BSPF_min(uInt32(height), izoom*256u); - - // Grab each non-duplicate row of data from the image - for(int irow = 0; irow < height; irow += izoom, buf_ptr += buf_offset) - { - // Scale the image data into the temporary line buffer - uInt8* i_ptr = buf_ptr; - uInt32* l_ptr = line; - for(int icol = 0; icol < width; icol += izoom, i_ptr += i_offset) - { - uInt32 pixel = - instance().frameBuffer().mapRGB(*i_ptr, *(i_ptr+1), *(i_ptr+2)); - uInt32 xstride = myZoomLevel; - while(xstride--) - *l_ptr++ = pixel; - } - - // Then fill the surface with those bytes - uInt32 ystride = myZoomLevel; - while(ystride--) - surface->drawPixels(line, 0, srow++, sw); - } - delete[] buffer; - delete[] line; - return true; - } - delete[] buffer; - delete[] line; - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string RomInfoWidget::parseTextChunk(uInt8* data, int size) -{ - return ""; -} - /* cerr << "surface:" << endl << " w = " << sw << endl diff --git a/src/gui/RomInfoWidget.hxx b/src/gui/RomInfoWidget.hxx index 72c7c4ef0..cc4330af0 100644 --- a/src/gui/RomInfoWidget.hxx +++ b/src/gui/RomInfoWidget.hxx @@ -45,12 +45,6 @@ class RomInfoWidget : public Widget private: void parseProperties(); - bool isValidPNGHeader(uInt8* header); - void readPNGChunk(ifstream& in, string& type, uInt8** data, int& size); - bool parseIHDR(int& width, int& height, uInt8* data, int size); - bool parseIDATChunk(FBSurface* surface, int width, int height, - uInt8* data, int size); - string parseTextChunk(uInt8* data, int size); private: // Surface id and pointer holding the scaled PNG image diff --git a/src/macosx/stella.xcodeproj/project.pbxproj b/src/macosx/stella.xcodeproj/project.pbxproj index 0a9862bac..ee8397898 100644 --- a/src/macosx/stella.xcodeproj/project.pbxproj +++ b/src/macosx/stella.xcodeproj/project.pbxproj @@ -250,6 +250,26 @@ DC173F770E2CAC1E00320F94 /* ContextMenu.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC173F750E2CAC1E00320F94 /* ContextMenu.hxx */; }; DC1FC18A0DB3B2C7009B3DF7 /* SerialPortMACOSX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC1FC1880DB3B2C7009B3DF7 /* SerialPortMACOSX.cxx */; }; DC1FC18B0DB3B2C7009B3DF7 /* SerialPortMACOSX.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC1FC1890DB3B2C7009B3DF7 /* SerialPortMACOSX.hxx */; }; + DC3FE47C11C7D35600C91C72 /* png.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE46A11C7D35600C91C72 /* png.c */; }; + DC3FE47D11C7D35600C91C72 /* png.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3FE46B11C7D35600C91C72 /* png.h */; }; + DC3FE47E11C7D35600C91C72 /* pngconf.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3FE46C11C7D35600C91C72 /* pngconf.h */; }; + DC3FE47F11C7D35600C91C72 /* pngerror.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE46D11C7D35600C91C72 /* pngerror.c */; }; + DC3FE48011C7D35600C91C72 /* pngget.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE46E11C7D35600C91C72 /* pngget.c */; }; + DC3FE48111C7D35600C91C72 /* pngmem.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE46F11C7D35600C91C72 /* pngmem.c */; }; + DC3FE48211C7D35600C91C72 /* pngpread.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47011C7D35600C91C72 /* pngpread.c */; }; + DC3FE48311C7D35600C91C72 /* pngpriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3FE47111C7D35600C91C72 /* pngpriv.h */; }; + DC3FE48411C7D35600C91C72 /* pngread.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47211C7D35600C91C72 /* pngread.c */; }; + DC3FE48511C7D35600C91C72 /* pngrio.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47311C7D35600C91C72 /* pngrio.c */; }; + DC3FE48611C7D35600C91C72 /* pngrtran.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47411C7D35600C91C72 /* pngrtran.c */; }; + DC3FE48711C7D35600C91C72 /* pngrutil.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47511C7D35600C91C72 /* pngrutil.c */; }; + DC3FE48811C7D35600C91C72 /* pngset.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47611C7D35600C91C72 /* pngset.c */; }; + DC3FE48911C7D35600C91C72 /* pngtrans.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47711C7D35600C91C72 /* pngtrans.c */; }; + DC3FE48A11C7D35600C91C72 /* pngwio.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47811C7D35600C91C72 /* pngwio.c */; }; + DC3FE48B11C7D35600C91C72 /* pngwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47911C7D35600C91C72 /* pngwrite.c */; }; + DC3FE48C11C7D35600C91C72 /* pngwtran.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47A11C7D35600C91C72 /* pngwtran.c */; }; + DC3FE48D11C7D35600C91C72 /* pngwutil.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE47B11C7D35600C91C72 /* pngwutil.c */; }; + DC3FE49F11C7D3FE00C91C72 /* PNGLibrary.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3FE49D11C7D3FE00C91C72 /* PNGLibrary.cxx */; }; + DC3FE4A011C7D3FE00C91C72 /* PNGLibrary.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3FE49E11C7D3FE00C91C72 /* PNGLibrary.hxx */; }; DC4613670D92C03600D8DAB9 /* RomAuditDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC4613650D92C03600D8DAB9 /* RomAuditDialog.cxx */; }; DC4613680D92C03600D8DAB9 /* RomAuditDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC4613660D92C03600D8DAB9 /* RomAuditDialog.hxx */; }; DC47455509C34BFA00EDDA3A /* BankRomCheat.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC47454A09C34BFA00EDDA3A /* BankRomCheat.cxx */; }; @@ -630,6 +650,26 @@ DC173F750E2CAC1E00320F94 /* ContextMenu.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; name = ContextMenu.hxx; path = ../gui/ContextMenu.hxx; sourceTree = SOURCE_ROOT; }; DC1FC1880DB3B2C7009B3DF7 /* SerialPortMACOSX.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SerialPortMACOSX.cxx; sourceTree = ""; }; DC1FC1890DB3B2C7009B3DF7 /* SerialPortMACOSX.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = SerialPortMACOSX.hxx; sourceTree = ""; }; + DC3FE46A11C7D35600C91C72 /* png.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = png.c; path = ../libpng/png.c; sourceTree = SOURCE_ROOT; }; + DC3FE46B11C7D35600C91C72 /* png.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = png.h; path = ../libpng/png.h; sourceTree = SOURCE_ROOT; }; + DC3FE46C11C7D35600C91C72 /* pngconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pngconf.h; path = ../libpng/pngconf.h; sourceTree = SOURCE_ROOT; }; + DC3FE46D11C7D35600C91C72 /* pngerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngerror.c; path = ../libpng/pngerror.c; sourceTree = SOURCE_ROOT; }; + DC3FE46E11C7D35600C91C72 /* pngget.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngget.c; path = ../libpng/pngget.c; sourceTree = SOURCE_ROOT; }; + DC3FE46F11C7D35600C91C72 /* pngmem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngmem.c; path = ../libpng/pngmem.c; sourceTree = SOURCE_ROOT; }; + DC3FE47011C7D35600C91C72 /* pngpread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngpread.c; path = ../libpng/pngpread.c; sourceTree = SOURCE_ROOT; }; + DC3FE47111C7D35600C91C72 /* pngpriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pngpriv.h; path = ../libpng/pngpriv.h; sourceTree = SOURCE_ROOT; }; + DC3FE47211C7D35600C91C72 /* pngread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngread.c; path = ../libpng/pngread.c; sourceTree = SOURCE_ROOT; }; + DC3FE47311C7D35600C91C72 /* pngrio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngrio.c; path = ../libpng/pngrio.c; sourceTree = SOURCE_ROOT; }; + DC3FE47411C7D35600C91C72 /* pngrtran.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngrtran.c; path = ../libpng/pngrtran.c; sourceTree = SOURCE_ROOT; }; + DC3FE47511C7D35600C91C72 /* pngrutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngrutil.c; path = ../libpng/pngrutil.c; sourceTree = SOURCE_ROOT; }; + DC3FE47611C7D35600C91C72 /* pngset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngset.c; path = ../libpng/pngset.c; sourceTree = SOURCE_ROOT; }; + DC3FE47711C7D35600C91C72 /* pngtrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngtrans.c; path = ../libpng/pngtrans.c; sourceTree = SOURCE_ROOT; }; + DC3FE47811C7D35600C91C72 /* pngwio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngwio.c; path = ../libpng/pngwio.c; sourceTree = SOURCE_ROOT; }; + DC3FE47911C7D35600C91C72 /* pngwrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngwrite.c; path = ../libpng/pngwrite.c; sourceTree = SOURCE_ROOT; }; + DC3FE47A11C7D35600C91C72 /* pngwtran.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngwtran.c; path = ../libpng/pngwtran.c; sourceTree = SOURCE_ROOT; }; + DC3FE47B11C7D35600C91C72 /* pngwutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngwutil.c; path = ../libpng/pngwutil.c; sourceTree = SOURCE_ROOT; }; + DC3FE49D11C7D3FE00C91C72 /* PNGLibrary.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PNGLibrary.cxx; path = ../common/PNGLibrary.cxx; sourceTree = SOURCE_ROOT; }; + DC3FE49E11C7D3FE00C91C72 /* PNGLibrary.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = PNGLibrary.hxx; path = ../common/PNGLibrary.hxx; sourceTree = SOURCE_ROOT; }; DC419D81108E10A3006E8687 /* Info-Stella.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Stella.plist"; sourceTree = ""; }; DC4613650D92C03600D8DAB9 /* RomAuditDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = RomAuditDialog.cxx; path = ../gui/RomAuditDialog.cxx; sourceTree = SOURCE_ROOT; }; DC4613660D92C03600D8DAB9 /* RomAuditDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; name = RomAuditDialog.hxx; path = ../gui/RomAuditDialog.hxx; sourceTree = SOURCE_ROOT; }; @@ -799,6 +839,7 @@ 2D605130089879BA00C6DE89 /* debugger */, 2D6050CC0898776500C6DE89 /* emucore */, 2D6050FA0898786C00C6DE89 /* gui */, + DC3FE46711C7D32500C91C72 /* libpng */, 2D6050C60898771C00C6DE89 /* macosx */, 2D6050C90898774B00C6DE89 /* unix */, 2D60513708987A5400C6DE89 /* yacc */, @@ -881,6 +922,8 @@ 2D733D62062893E7006265D9 /* FrameBufferSoft.hxx */, DCB9DA5E0FCD527000B192F6 /* GLShaderProgs.hxx */, 2DDBEA0A0845700300812C11 /* mainSDL.cxx */, + DC3FE49D11C7D3FE00C91C72 /* PNGLibrary.cxx */, + DC3FE49E11C7D3FE00C91C72 /* PNGLibrary.hxx */, DCD56D3A0B247DB40092F9F8 /* RectList.cxx */, DCD56D3B0B247DB40092F9F8 /* RectList.hxx */, DCF467B20F93993B00B25D7A /* SharedPtr.hxx */, @@ -1183,6 +1226,31 @@ name = yacc; sourceTree = ""; }; + DC3FE46711C7D32500C91C72 /* libpng */ = { + isa = PBXGroup; + children = ( + DC3FE46A11C7D35600C91C72 /* png.c */, + DC3FE46B11C7D35600C91C72 /* png.h */, + DC3FE46C11C7D35600C91C72 /* pngconf.h */, + DC3FE46D11C7D35600C91C72 /* pngerror.c */, + DC3FE46E11C7D35600C91C72 /* pngget.c */, + DC3FE46F11C7D35600C91C72 /* pngmem.c */, + DC3FE47011C7D35600C91C72 /* pngpread.c */, + DC3FE47111C7D35600C91C72 /* pngpriv.h */, + DC3FE47211C7D35600C91C72 /* pngread.c */, + DC3FE47311C7D35600C91C72 /* pngrio.c */, + DC3FE47411C7D35600C91C72 /* pngrtran.c */, + DC3FE47511C7D35600C91C72 /* pngrutil.c */, + DC3FE47611C7D35600C91C72 /* pngset.c */, + DC3FE47711C7D35600C91C72 /* pngtrans.c */, + DC3FE47811C7D35600C91C72 /* pngwio.c */, + DC3FE47911C7D35600C91C72 /* pngwrite.c */, + DC3FE47A11C7D35600C91C72 /* pngwtran.c */, + DC3FE47B11C7D35600C91C72 /* pngwutil.c */, + ); + name = libpng; + sourceTree = ""; + }; DCCC0C9109C3541E0088BFF1 /* cheat */ = { isa = PBXGroup; children = ( @@ -1376,6 +1444,10 @@ DCE9CC2D1103812700C86671 /* DiStella.hxx in Headers */, DC84E11D1135988E00CA7C9D /* Genesis.hxx in Headers */, DC64EB211152F9C000DC9140 /* CartDPCPlus.hxx in Headers */, + DC3FE47D11C7D35600C91C72 /* png.h in Headers */, + DC3FE47E11C7D35600C91C72 /* pngconf.h in Headers */, + DC3FE48311C7D35600C91C72 /* pngpriv.h in Headers */, + DC3FE4A011C7D3FE00C91C72 /* PNGLibrary.hxx in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1610,6 +1682,22 @@ DCE9CC2C1103812700C86671 /* DiStella.cxx in Sources */, DC84E11C1135988E00CA7C9D /* Genesis.cxx in Sources */, DC64EB201152F9C000DC9140 /* CartDPCPlus.cxx in Sources */, + DC3FE47C11C7D35600C91C72 /* png.c in Sources */, + DC3FE47F11C7D35600C91C72 /* pngerror.c in Sources */, + DC3FE48011C7D35600C91C72 /* pngget.c in Sources */, + DC3FE48111C7D35600C91C72 /* pngmem.c in Sources */, + DC3FE48211C7D35600C91C72 /* pngpread.c in Sources */, + DC3FE48411C7D35600C91C72 /* pngread.c in Sources */, + DC3FE48511C7D35600C91C72 /* pngrio.c in Sources */, + DC3FE48611C7D35600C91C72 /* pngrtran.c in Sources */, + DC3FE48711C7D35600C91C72 /* pngrutil.c in Sources */, + DC3FE48811C7D35600C91C72 /* pngset.c in Sources */, + DC3FE48911C7D35600C91C72 /* pngtrans.c in Sources */, + DC3FE48A11C7D35600C91C72 /* pngwio.c in Sources */, + DC3FE48B11C7D35600C91C72 /* pngwrite.c in Sources */, + DC3FE48C11C7D35600C91C72 /* pngwtran.c in Sources */, + DC3FE48D11C7D35600C91C72 /* pngwutil.c in Sources */, + DC3FE49F11C7D3FE00C91C72 /* PNGLibrary.cxx in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };