From 14e7818fdf8db241ff91c384308bfc4613b89c09 Mon Sep 17 00:00:00 2001 From: stephena Date: Thu, 9 Nov 2006 03:06:42 +0000 Subject: [PATCH] Completely removed the PNG library dependency from Stella. I'm amazed at how easy it was to just write the PNG directly; it takes roughly the same amount of code as when interfacing with the PNG library! One less dependency is always a good thing, since some systems might not have it installed by default. For now, the Linux side of things is complete (configure script, etc). Still TODO is check the Win32 project file, and rework the OSX stuff (OSX had the full libpng sources embedded in src/macosx). I suspect this will fix the bugs recently reported when compiling Stella on Intel-based Macs. Added a freedesktop.org compliant stella.desktop menu entry, which is now installed as part of 'make install'. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1143 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/Makefile | 9 +- stella/configure | 57 +--------- stella/src/common/Snapshot.cxx | 191 +++++++++++++++++++-------------- stella/src/common/Snapshot.hxx | 22 +--- stella/src/unix/stella.desktop | 9 ++ stella/src/unix/stella.spec | 16 --- stella/src/win32/Stella.vcproj | 6 +- 7 files changed, 134 insertions(+), 176 deletions(-) create mode 100644 stella/src/unix/stella.desktop diff --git a/stella/Makefile b/stella/Makefile index 4339f877c..3eabea009 100644 --- a/stella/Makefile +++ b/stella/Makefile @@ -13,7 +13,7 @@ ## See the file "license" for information on usage and redistribution of ## this file, and for a DISCLAIMER OF ALL WARRANTIES. ## -## $Id: Makefile,v 1.28 2006-09-08 14:35:20 stephena Exp $ +## $Id: Makefile,v 1.29 2006-11-09 03:06:42 stephena Exp $ ## ## Based on code from ScummVM - Scumm Interpreter ## Copyright (C) 2002-2004 The ScummVM project @@ -174,6 +174,8 @@ install: all $(INSTALL) -c -m 644 "$(srcdir)/Announce.txt" "$(srcdir)/Changes.txt" "$(srcdir)/Copyright.txt" "$(srcdir)/License.txt" "$(srcdir)/README-SDL.txt" "$(srcdir)/Readme.txt" "$(srcdir)/Todo.txt" "$(srcdir)/docs/index.html" "$(srcdir)/docs/debugger.html" "$(DESTDIR)$(DOCDIR)/" $(INSTALL) -d "$(DESTDIR)$(DOCDIR)/graphics" $(INSTALL) -c -m 644 "$(srcdir)/docs/graphics/chucky_cheese.png" "$(srcdir)/docs/graphics/circuit.png" "$(srcdir)/docs/graphics/console.png" "$(srcdir)/docs/graphics/eventmapping.png" "$(srcdir)/docs/graphics/eventmapping_remap.png" "$(srcdir)/docs/graphics/jr_pacman.png" "$(srcdir)/docs/graphics/launcher_options_rom.png" "$(srcdir)/docs/graphics/launcher_options_snap.png" "$(srcdir)/docs/graphics/launcher.png" "$(srcdir)/docs/graphics/options_about.png" "$(srcdir)/docs/graphics/options_audio.png" "$(srcdir)/docs/graphics/options_gameinfo.png" "$(srcdir)/docs/graphics/options_help.png" "$(srcdir)/docs/graphics/options_video.png" "$(srcdir)/docs/graphics/pacman.png" "$(srcdir)/docs/graphics/rom_browser.png" "$(srcdir)/docs/graphics/secret_quest.png" "$(srcdir)/docs/graphics/space_invaders.png" "$(DESTDIR)$(DOCDIR)/graphics" + $(INSTALL) -d "$(DESTDIR)$(DATADIR)/applications" + $(INSTALL) -c -m 644 "$(srcdir)/src/unix/stella.desktop" "$(DESTDIR)$(DATADIR)/applications" $(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons" $(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons/mini" $(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons/large" @@ -187,7 +189,10 @@ install-strip: install uninstall: rm -f "$(DESTDIR)$(BINDIR)/stella$(EXEEXT)" rm -rf "$(DESTDIR)$(DOCDIR)/" + rm -f "$(DESTDIR)$(DATADIR)/applications/stella.desktop" rm -f "$(DESTDIR)$(DATADIR)/icons/stella.xpm" + rm -f "$(DESTDIR)$(DATADIR)/icons/mini/stella.xpm" + rm -f "$(DESTDIR)$(DATADIR)/icons/large/stella.xpm" # Special rule for Win32 icon stuff (there's probably a better way to do this ...) src/win32/stella_icon.o: src/win32/stella.ico src/win32/stella.rc @@ -201,7 +206,7 @@ win32dist: stella$(EXEEXT) cp Announce.txt Changes.txt Copyright.txt License.txt README-SDL.txt Readme.txt Todo.txt $(DISTNAME)/docs cp -r docs/*.html $(DISTNAME)/docs cp -r docs/graphics/*.png $(DISTNAME)/docs/graphics - cp /mingw/bin/SDL.dll /mingw/bin/libpng-3.dll $(DISTNAME) + cp /mingw/bin/SDL.dll $(DISTNAME) # u2d $(DISTNAME)/*.txt # zip $(DISTNAME)-win32.zip $(DISTNAME) diff --git a/stella/configure b/stella/configure index 1249cab92..36dd0f59f 100755 --- a/stella/configure +++ b/stella/configure @@ -16,7 +16,6 @@ CXXFLAGS="$CXXFLAGS $CPPFLAGS" # default lib behaviour yes/no/auto _opengl=auto _zlib=auto -_png=auto # default option behaviour yes/no _build_gl=yes @@ -281,9 +280,6 @@ Optional Libraries: --with-zlib-prefix=DIR Prefix where zlib is installed (optional) --disable-zlib disable zlib (compression) support [autodetect] - --with-png-prefix=DIR Prefix where png is installed (optional) - --disable-png disable png support [autodetect] - --with-sdl-prefix=DIR Prefix where the sdl-config script is installed (optional) --with-nasm-prefix=DIR Prefix where nasm executable is installed (optional) @@ -324,8 +320,6 @@ for ac_option in $@; do --disable-scalers) _build_scalers=no ;; --enable-zlib) _zlib=yes ;; --disable-zlib) _zlib=no ;; - --enable-png) _png=yes ;; - --disable-png) _png=no ;; --enable-nasm) _nasm=yes ;; --disable-nasm) _nasm=no ;; --enable-shared) _build_static=no ;; @@ -338,11 +332,6 @@ for ac_option in $@; do ZLIB_CFLAGS="-I$_prefix/include" ZLIB_LIBS="-L$_prefix/lib" ;; - --with-png-prefix=*) - _prefix=`echo $ac_option | cut -d '=' -f 2` - PNG_CFLAGS="-I$_prefix/include" - PNG_LIBS="-L$_prefix/lib" - ;; --with-sdl-prefix=*) arg=`echo $ac_option | cut -d '=' -f 2` _sdlpath="$arg:$arg/bin" @@ -394,7 +383,6 @@ ppc-amigaos) psp) _host_os=psp _host_cpu=mips - _png=yes # force psp sdl path _sdlpath=$(psp-config --pspdev-path)/psp/bin:$_sdlpath PATH=$(psp-config --pspdev-path)/psp/bin:$(psp-config --pspdev-path)/bin:$PATH @@ -402,7 +390,6 @@ psp) gp2x) _host_os=gp2x _host_cpu=arm - _png=yes ;; *) guessed_host=`$_srcdir/config.guess` @@ -652,21 +639,6 @@ EOF fi echo "$_zlib" -# -# Check for PNG -# -echocheck "png" -if test "$_png" = auto ; then - _png=no - cat > $TMPC << EOF -#include -#include -int main(void) { return 0; } -EOF - cc_check $LDFLAGS $CXXFLAGS && _png=yes -fi -echo "$_png" - # # Check for GL # @@ -741,14 +713,8 @@ else fi if test "$_build_snapshot" = "yes" ; then - if test "$_png" = "yes" ; then - echo_n " Snapshot support enabled" - echo - else - echo_n " Snapshot support disabled (missing PNG library)" - echo - _build_snapshot=no - fi + echo_n " Snapshot support enabled" + echo else echo_n " Snapshot support disabled" echo @@ -864,7 +830,7 @@ case $_host_os in CXXFLAGS="-G0 -O2 -fno-rtti" # 2 times -lc to avoid link problems. psp-gcc seems to to forget the first -lc wiile stdc++ linking LIBS="-L `psp-config --pspsdk-path`/lib -L`psp-config --pspsdk-path`/../lib " - LIBS="$LIBS -lSDLmain -lSDL -lGL -lm -lpspdebug -lpspgu -lpspctrl -lpspge -lpspdisplay -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lc -lpspuser -lpspkernel -lpsppower -lpng -lz -lm -lg -lstdc++ -lc -lpsputility" + LIBS="$LIBS -lSDLmain -lSDL -lGL -lm -lpspdebug -lpspgu -lpspctrl -lpspge -lpspdisplay -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lc -lpspuser -lpspkernel -lpsppower -lz -lm -lg -lstdc++ -lc -lpsputility" # psp compiler CC="psp-gcc" LD="psp-gcc" @@ -927,7 +893,6 @@ fi if test "$_build_snapshot" = yes ; then DEFINES="$DEFINES -DSNAPSHOT_SUPPORT" - LIBS="$LIBS -lpng" fi if test "$_build_joystick" = yes ; then @@ -957,22 +922,6 @@ if test "$_build_profile" = no ; then fi -# 20051003 bkw: fix static Linux build. -# No guarantee this will work for anyone other than me, and no -# guarantee it's needed by anyone but me (and Steve)... -if test "$_host_os" = unix ; then - if test "$_build_static" = yes ; then - LIBS="`echo \"$LIBS\" | sed 's/-lz -lpng/-lpng -lz/'`" - fi -fi - -# Works for GP2X which needs a static build. -if test "$_host_os" = gp2x ; then - if test "$_build_static" = yes ; then - LIBS="`echo \"$LIBS\" | sed 's/-lz -lpng/-lpng -lz/'`" - fi -fi - echo "Creating config.mak" cat > config.mak << EOF # -------- Generated by configure ----------- diff --git a/stella/src/common/Snapshot.cxx b/stella/src/common/Snapshot.cxx index 618c46de3..c6f44863a 100644 --- a/stella/src/common/Snapshot.cxx +++ b/stella/src/common/Snapshot.cxx @@ -13,13 +13,12 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Snapshot.cxx,v 1.10 2006-05-24 17:37:32 stephena Exp $ +// $Id: Snapshot.cxx,v 1.11 2006-11-09 03:06:42 stephena Exp $ //============================================================================ #ifdef SNAPSHOT_SUPPORT -#include -#include +#include #include #include "bspf.hxx" @@ -34,97 +33,123 @@ Snapshot::Snapshot(FrameBuffer& framebuffer) myFrameBuffer.hideMessage(); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Snapshot::~Snapshot() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Snapshot::png_write_data(png_structp ctx, png_bytep area, png_size_t size) -{ - ofstream* out = (ofstream *) png_get_io_ptr(ctx); - out->write((const char *)area, size); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Snapshot::png_io_flush(png_structp ctx) -{ - ofstream* out = (ofstream *) png_get_io_ptr(ctx); - out->flush(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Snapshot::png_user_warn(png_structp ctx, png_const_charp str) -{ - cerr << "Snapshot: libpng warning: " << str << endl; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Snapshot::png_user_error(png_structp ctx, png_const_charp str) -{ - cerr << "Snapshot: libpng error: " << str << endl; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string Snapshot::savePNG(string filename) { - png_structp png_ptr = 0; - png_infop info_ptr = 0; + uInt8* buffer = (uInt8*) NULL; + uInt8* compmem = (uInt8*) NULL; + ofstream out; - // Get actual image dimensions. which are not always the same - // as the framebuffer dimensions - uInt32 width = myFrameBuffer.imageWidth(); - uInt32 height = myFrameBuffer.imageHeight(); + try + { + // Get actual image dimensions. which are not always the same + // as the framebuffer dimensions + int width = myFrameBuffer.imageWidth(); + int height = myFrameBuffer.imageHeight(); - ofstream* out = new ofstream(filename.c_str(), ios_base::binary); - if(!out) + out.open(filename.c_str(), ios_base::binary); + if(!out) + throw "Couldn't open snapshot file"; + + // PNG file header + uInt8 header[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; + out.write((const char*)header, 8); + + // PNG IHDR + uInt8 ihdr[13]; + ihdr[0] = width >> 24; // width + ihdr[1] = width >> 16; + ihdr[2] = width >> 8; + ihdr[3] = width & 0xFF; + ihdr[4] = height >> 24; // height + ihdr[5] = height >> 16; + ihdr[6] = height >> 8; + ihdr[7] = height & 0xFF; + ihdr[8] = 8; // 8 bits per sample (24 bits per pixel) + ihdr[9] = 2; // PNG_COLOR_TYPE_RGB + ihdr[10] = 0; // PNG_COMPRESSION_TYPE_DEFAULT + ihdr[11] = 0; // PNG_FILTER_TYPE_DEFAULT + ihdr[12] = 0; // PNG_INTERLACE_NONE + writePNGChunk(out, "IHDR", ihdr, 13); + + // Fill the buffer with scanline data + int rowbytes = width * 3; + buffer = new uInt8[(rowbytes + 1) * height]; + uInt8* buf_ptr = buffer; + for(int row = 0; row < height; row++) + { + *buf_ptr++ = 0; // first byte of row is filter type + myFrameBuffer.scanline(row, buf_ptr); // get another scanline + buf_ptr += rowbytes; // add pitch + } + + // Compress the data with zlib + uLongf compmemsize = (uLongf)((height * (width + 1) * 3 * 1.001 + 1) + 12); + compmem = new uInt8[compmemsize]; + if(compmem == NULL || + (compress(compmem, &compmemsize, buffer, height * (width * 3 + 1)) != Z_OK)) + throw "Error: Couldn't compress PNG"; + + // Write the compressed framebuffer data + writePNGChunk(out, "IDAT", compmem, compmemsize); + + // Finish up + writePNGChunk(out, "IEND", 0, 0); + + // Clean up + if(buffer) delete[] buffer; + if(compmem) delete[] compmem; + out.close(); + + return "Snapshot saved"; + } + catch(const char *msg) + { + if(buffer) delete[] buffer; + if(compmem) delete[] compmem; + out.close(); + return msg; + } + catch(...) + { + if(buffer) delete[] buffer; + if(compmem) delete[] compmem; + out.close(); return "Couldn't create snapshot file"; + } +} - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_user_error, png_user_warn); - if(png_ptr == NULL) - return "Snapshot: Out of memory"; +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Snapshot::writePNGChunk(ofstream& out, char* type, uInt8* data, int size) +{ + // Stuff the length/type into the buffer + uInt8 temp[8]; + temp[0] = size >> 24; + temp[1] = size >> 16; + temp[2] = size >> 8; + temp[3] = size; + temp[4] = type[0]; + temp[5] = type[1]; + temp[6] = type[2]; + temp[7] = type[3]; - // Allocate/initialize the image information data. REQUIRED. - info_ptr = png_create_info_struct(png_ptr); - if(info_ptr == NULL) + // Write the header + out.write((const char*)temp, 8); + + // Append the actual data + uInt32 crc = crc32(0, temp + 4, 4); + if(size > 0) { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - out->close(); - - return "Snapshot: Error on create image info"; + out.write((const char*)data, size); + crc = crc32(crc, data, size); } - png_set_write_fn(png_ptr, out, png_write_data, png_io_flush); - - png_set_IHDR(png_ptr, info_ptr, width, height, 8, - PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - // Write the file header information. REQUIRED - png_write_info(png_ptr, info_ptr); - - // Pack pixels into bytes - png_set_packing(png_ptr); - - // Create space for one full scanline (3 bytes per pixel in RGB format) - uInt8* data = new uInt8[width * 3]; - - // Write a new scanline to the PNG file - for(uInt32 row = 0; row < height; row++) - { - myFrameBuffer.scanline(row, data); - png_write_row(png_ptr, (png_bytep) data); - } - - // Cleanup - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - delete[] data; - - out->close(); - delete out; - - return "Snapshot saved"; + // Write the CRC + temp[0] = crc >> 24; + temp[1] = crc >> 16; + temp[2] = crc >> 8; + temp[3] = crc; + out.write((const char*)temp, 4); } #endif // SNAPSHOT_SUPPORT diff --git a/stella/src/common/Snapshot.hxx b/stella/src/common/Snapshot.hxx index de4295b6f..4409012a3 100644 --- a/stella/src/common/Snapshot.hxx +++ b/stella/src/common/Snapshot.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Snapshot.hxx,v 1.5 2005-06-28 23:18:15 stephena Exp $ +// $Id: Snapshot.hxx,v 1.6 2006-11-09 03:06:42 stephena Exp $ //============================================================================ #ifndef SNAPSHOT_HXX @@ -23,7 +23,7 @@ class FrameBuffer; -#include +#include #include "bspf.hxx" class Snapshot @@ -37,27 +37,15 @@ class Snapshot Snapshot(FrameBuffer& framebuffer); /** - The destructor. - */ - ~Snapshot(); - - /** - This routine saves the current frame buffer to a PNG file. + Save the current frame buffer to a PNG file. @param filename The filename of the PNG file - - @string The resulting string to print to the framebuffer + @return The resulting string to print to the framebuffer */ string savePNG(string filename); private: - 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); + static void writePNGChunk(ofstream& out, char* type, uInt8* data, int size); private: // The Framebuffer for the system diff --git a/stella/src/unix/stella.desktop b/stella/src/unix/stella.desktop new file mode 100644 index 000000000..562b369ef --- /dev/null +++ b/stella/src/unix/stella.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Stella +Comment=A multi-platform Atari 2600 emulator +Exec=stella +Icon=stella.xpm +Terminal=false +Type=Application +Categories=Application;Emulator;Game; diff --git a/stella/src/unix/stella.spec b/stella/src/unix/stella.spec index af8795fbf..41d3f7b31 100644 --- a/stella/src/unix/stella.spec +++ b/stella/src/unix/stella.spec @@ -31,9 +31,6 @@ BuildRoot: %_tmppath/%name-%version-%release-root BuildRequires: SDL-devel BuildRequires: MesaGLU-devel BuildRequires: zlib-devel -%if %enable_snapshot -BuildRequires: libpng-devel -%endif %description The Atari 2600 Video Computer System (VCS), introduced in 1977, was the most @@ -106,19 +103,6 @@ longtitle="A multi-platform Atari 2600 emulator" \ section="More Applications/Emulators" \ xdg="true" EOF -# Todo - make this part of the main package -install -d -m0755 %{buildroot}%{_datadir}/applications -cat > %{buildroot}%{_datadir}/applications/%{name}.desktop << EOF -[Desktop Entry] -Encoding=UTF-8 -Name=Stella -Comment=A multi-platform Atari 2600 emulator -Exec=%{_bindir}/%{name} -Icon=stella.xpm -Terminal=false -Type=Application -Categories=Application;Emulator; -EOF %clean rm -rf $RPM_BUILD_ROOT diff --git a/stella/src/win32/Stella.vcproj b/stella/src/win32/Stella.vcproj index 38de7a2c8..b4916e41b 100755 --- a/stella/src/win32/Stella.vcproj +++ b/stella/src/win32/Stella.vcproj @@ -35,9 +35,8 @@ Name="VCLinkerTool" AdditionalOptions="SDL.lib SDLmain.lib -libpng.lib " - AdditionalDependencies="sdl.lib sdlmain.lib libpng.lib zdll.lib" + AdditionalDependencies="sdl.lib sdlmain.lib zdll.lib" OutputFile="$(OutDir)/Stella.exe" LinkIncremental="2" GenerateDebugInformation="TRUE" @@ -86,9 +85,8 @@ libpng.lib Name="VCLinkerTool" AdditionalOptions="SDL.lib SDLmain.lib -libpng.lib " - AdditionalDependencies="sdl.lib sdlmain.lib libpng.lib zdll.lib" + AdditionalDependencies="sdl.lib sdlmain.lib zdll.lib" OutputFile="$(OutDir)/Stella.exe" GenerateDebugInformation="TRUE" SubSystem="2"