diff --git a/src/devices/printer/printer.h b/src/devices/printer/printer.h index e05a653..7126adf 100644 --- a/src/devices/printer/printer.h +++ b/src/devices/printer/printer.h @@ -8,7 +8,7 @@ * * Definitions for the printers module. * - * Version: @(#)printer.h 1.0.1 2018/08/31 + * Version: @(#)printer.h 1.0.2 2018/09/02 * * Authors: Michael Drüing, * Fred N. van Kempen, @@ -40,6 +40,8 @@ # define PRINTER_H +#define FONT_FILE_DOTMATRIX L"dotmatrix.ttf" + #define FONT_FILE_ROMAN L"roman.ttf" #define FONT_FILE_SANSSERIF L"sansserif.ttf" #define FONT_FILE_COURIER L"courier.ttf" diff --git a/src/devices/printer/prt_text.c b/src/devices/printer/prt_text.c index 91cac1d..3bae6c5 100644 --- a/src/devices/printer/prt_text.c +++ b/src/devices/printer/prt_text.c @@ -15,7 +15,7 @@ * printer mechanics. This would lead to a page being 66 lines * of 80 characters each. * - * Version: @(#)prt_text.c 1.0.1 2018/08/31 + * Version: @(#)prt_text.c 1.0.2 2018/09/02 * * Author: Fred N. van Kempen, * @@ -63,6 +63,25 @@ #include "printer.h" +#define FULL_PAGE 1 /* set if no top/bot margins */ + + +/* Default page values (for now.) */ +#define PAGE_WIDTH 8.5 /* standard U.S. Letter */ +#define PAGE_HEIGHT 11 +#define PAGE_LMARGIN 0.25 /* 0.25" left and right */ +#define PAGE_RMARGIN 0.25 +#if FULL_PAGE +# define PAGE_TMARGIN 0 +# define PAGE_BMARGIN 0 +#else +# define PAGE_TMARGIN 0.25 +# define PAGE_BMARGIN 0.25 +#endif +#define PAGE_CPI 10.0 /* standard 10 cpi */ +#define PAGE_LPI 6.0 /* standard 6 lpi */ + + typedef struct { int8_t dirty; /* has the page been printed on? */ char pad; @@ -133,6 +152,7 @@ dump_page(prnt_t *dev) pclog("PRNT: unable to create print page '%ls'\n", path); return; } + fseek(fp, 0, SEEK_END); /* If this is not a new file, add a formfeed first. */ if (ftell(fp) != 0) @@ -174,14 +194,14 @@ static void reset_printer(prnt_t *dev) { /* TODO: these three should be configurable */ - dev->page_width = 8.5; - dev->page_height = 11; - dev->left_margin = 0.25; - dev->right_margin = 0.25; - dev->top_margin = 0.25; - dev->bot_margin = 0.25; - dev->cpi = 10.0; - dev->lpi = 6.0; + dev->page_width = PAGE_WIDTH; + dev->page_height = PAGE_HEIGHT; + dev->left_margin = PAGE_LMARGIN; + dev->right_margin = PAGE_RMARGIN; + dev->top_margin = PAGE_TMARGIN; + dev->bot_margin = PAGE_BMARGIN; + dev->cpi = PAGE_CPI; + dev->lpi = PAGE_LPI; /* Default page layout. */ dev->max_chars = (int) ((dev->page_width - dev->left_margin - dev->right_margin) * dev->cpi); @@ -197,7 +217,7 @@ reset_printer(prnt_t *dev) dev->page->dirty = 0; /* Create a file for this page. */ - plat_tempfile(dev->filename, PRINTER_FILE, L".txt"); + plat_tempfile(dev->filename, NULL, L".txt"); } @@ -339,8 +359,6 @@ write_ctrl(uint8_t val, void *priv) /* reset printer */ dev->select = 0; - pclog("PRNT: Printer reset\n"); - reset_printer(dev); } @@ -394,8 +412,10 @@ prnt_init(const lpt_device_t *info) dev->page->chars = (char *)malloc(dev->page->w * dev->page->h); memset(dev->page->chars, 0x00, dev->page->w * dev->page->h); +#if 0 pclog("PRNT: created a virtual %ix%i page.\n", dev->page->w, dev->page->h); +#endif return(dev); } @@ -408,8 +428,6 @@ prnt_close(void *priv) if (dev == NULL) return; - pclog("PRNT: Closing LPT printer '%s'\n", dev->name); - /* print last page if it contains data */ if (dev->page->dirty) dump_page(dev); @@ -420,8 +438,6 @@ prnt_close(void *priv) free(dev->page); } - pclog("PRNT: LPT printer '%s' closed.\n", dev->name); - free(dev); } diff --git a/src/emu.h b/src/emu.h index a48d5fc..120c8b9 100644 --- a/src/emu.h +++ b/src/emu.h @@ -8,7 +8,7 @@ * * Main include file for the application. * - * Version: @(#)emu.h 1.0.30 2018/08/31 + * Version: @(#)emu.h 1.0.31 2018/09/01 * * Author: Fred N. van Kempen, * @@ -65,7 +65,6 @@ #define PRINTER_PATH L"printer" /* Pre-defined file names and extensions. */ -#define PRINTER_FILE L"print" #define LANG_FILE L"VARCem-" #define BIOS_FILE L"bios.txt" #define CONFIG_FILE L"config.varc" diff --git a/src/png.c b/src/png.c new file mode 100644 index 0000000..f0a38b7 --- /dev/null +++ b/src/png.c @@ -0,0 +1,410 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Provide centralized access to the PNG image handler. + * + * Version: @(#)png.c 1.0.1 2018/09/01 + * + * Author: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#define PNG_DEBUG 0 +#include +#include "./png.h" +#include "emu.h" +#include "plat.h" + + +#define PATH_PNG_DLL "libpng16.dll" +#define USE_CUSTOM_IO 1 + + +static void *png_handle = NULL; /* handle to DLL */ +#if USE_LIBPNG == 1 +# define PNGFUNC(x) png_ ## x +# else +# define PNGFUNC(x) PNG_ ## x + + +/* Pointers to the real functions. */ +static png_structp (*PNG_create_write_struct)(png_const_charp user_png_ver, + png_voidp error_ptr, + png_error_ptr error_fn, + png_error_ptr warn_fn); +static void (*PNG_destroy_write_struct)(png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr); +static png_infop (*PNG_create_info_struct)(png_const_structrp png_ptr); +#if USE_CUSTOM_IO +static void (*PNG_set_write_fn)(png_structrp png_ptr, + png_voidp io_ptr, + png_rw_ptr write_data_fn, + png_flush_ptr output_flush_fn); +static png_voidp (*PNG_get_io_ptr)(png_const_structrp png_ptr); +#else +static void (*PNG_init_io)(png_structrp png_ptr, png_FILE_p fp); +#endif +static void (*PNG_set_IHDR)(png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, + png_uint_32 height, int bit_depth, + int color_type, int interlace_method, + int compression_method, + int filter_method); +static png_size_t (*PNG_get_rowbytes)(png_const_structrp png_ptr, + png_const_inforp info_ptr); +static void (*PNG_write_info)(png_structrp png_ptr, + png_const_inforp info_ptr); +static void (*PNG_write_image)(png_structrp png_ptr, + png_bytepp image); +static void (*PNG_write_row)(png_structrp png_ptr, + png_bytep row); +static void (*PNG_write_rows)(png_structrp png_ptr, + png_bytepp rows, int num); +static void (*PNG_write_end)(png_structrp png_ptr, + png_inforp info_ptr); + + +static const dllimp_t png_imports[] = { + { "png_create_write_struct", &PNG_create_write_struct }, + { "png_destroy_write_struct", &PNG_destroy_write_struct }, + { "png_create_info_struct", &PNG_create_info_struct }, +#if USE_CUSTOM_IO + { "png_set_write_fn", &PNG_set_write_fn }, + { "png_get_io_ptr", &PNG_get_io_ptr }, +#else + { "png_init_io", &PNG_init_io }, +#endif + { "png_set_IHDR", &PNG_set_IHDR }, + { "png_get_rowbytes", &PNG_get_rowbytes }, + { "png_write_info", &PNG_write_info }, + { "png_write_row", &PNG_write_row }, + { "png_write_rows", &PNG_write_rows }, + { "png_write_image", &PNG_write_image }, + { "png_write_end", &PNG_write_end }, + { NULL, NULL } +}; +#endif + + +static void +error_handler(png_structp arg, const char *str) +{ + pclog("PNG: stream 0x%08lx error '%s'\n", arg, str); +} + + +static void +warning_handler(png_structp arg, const char *str) +{ + pclog("PNG: stream 0x%08lx warning '%s'\n", arg, str); +} + + +#if USE_CUSTOM_IO +/* Use custom I/O Write function to avoid debug-dll issues. */ +static void +write_handler(png_struct *png_ptr, png_byte *bufp, png_size_t len) +{ + FILE *fp = (FILE *)PNGFUNC(get_io_ptr)(png_ptr); + + if (fwrite(bufp, 1, len, fp) != len) + pclog("PNG: error writing file!\n"); +} + + +/* Use custom I/O Flush function to avoid debug-dll issues. */ +static void +flush_handler(png_struct *png_ptr) +{ + FILE *fp = (FILE *)PNGFUNC(get_io_ptr)(png_ptr); + + fflush(fp); +} +#endif + + +/* Prepare the PNG library for use, load DLL if needed. */ +int +png_load(void) +{ + /* If already loaded, good! */ + if (png_handle != NULL) return(1); + +#if USE_LIBPNG == 2 + /* Try loading the DLL. */ + png_handle = dynld_module(PATH_PNG_DLL, png_imports); + if (png_handle == NULL) { + pclog("PNG: unable to load '%s'; format disabled!\n", PATH_PNG_DLL); + return(0); + } +#else + png_handle = (void *)1; /* just to indicate always therse */ +#endif + + return(1); +} + + +/* PNG library no longer needed, unload DLL if needed. */ +void +png_unload(void) +{ +#if USE_LIBPNG == 2 + /* Unload the DLL if possible. */ + if (png_handle != NULL) + dynld_close(png_handle); +#else + png_handle = NULL; +#endif +} + + +/* Write the given image as an 8-bit GrayScale PNG image file. */ +int +png_write_gray(const wchar_t *fn, int inv, uint8_t *pix, int16_t w, int16_t h) +{ + png_structp png = NULL; + png_infop info = NULL; + png_bytep row; + int16_t x, y; + FILE *fp; + + /* Load the DLL if needed, give up if that fails. */ + if (! png_load()) return(0); + + /* Create the image file. */ + fp = plat_fopen(fn, L"wb"); + if (fp == NULL) { + /* Yes, this looks weird. */ + if (fp == NULL) + pclog("[PNG] file %ls could not be opened for writing!\n", fn); + else +error: + pclog("[PNG] fatal error, bailing out, error = %i\n", errno); + if (png != NULL) + PNGFUNC(destroy_write_struct)(&png, &info); + if (fp != NULL) + (void)fclose(fp); + return(0); + } + + /* Initialize PNG stuff. */ + png = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, NULL, + error_handler, warning_handler); + if (png == NULL) { + pclog("[PNG] create_write_struct failed!\n"); + goto error; + } + + info = PNGFUNC(create_info_struct)(png); + if (info == NULL) { + pclog("[PNG] create_info_struct failed!\n"); + goto error; + } + +#if USE_LIBPNG == 1 + /* Set up error handling. */ + if (setjmp(png_jmpbuf(png))) { + /* If we get here, we had a problem writing the file */ + goto error; + } +#endif + +#if USE_CUSTOM_IO + /* + * We use our own I/O routines, because it seems that some of + * the PNG DLL's out there are compiled in Debug mode, which + * causes the 'FILE' definition to be different. This in turn + * results in pretty bad crashes when trying to write.. + * + * Using custom I/O routines, we avoid this issue. + */ + PNGFUNC(set_write_fn)(png, (void *)fp, write_handler, flush_handler); +#else + PNGFUNC(init_io)(png, fp); +#endif + + PNGFUNC(set_IHDR)(png, info, w, h, 8, PNG_COLOR_TYPE_GRAY, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + PNGFUNC(write_info)(png, info); + + /* Create a buffer for one scanline of pixels. */ + row = (png_bytep)malloc(PNGFUNC(get_rowbytes)(png, info)); + + /* Process all scanlines in the image. */ + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + /* Copy the pixel data. */ + if (inv) + row[x] = 255 - pix[(y * w) + x]; + else + row[x] = pix[(y * w) + x]; + } + + /* Write image to the file. */ + PNGFUNC(write_rows)(png, &row, 1); + } + + /* No longer need the row buffer. */ + free(row); + + PNGFUNC(write_end)(png, NULL); + + PNGFUNC(destroy_write_struct)(&png, &info); + + /* Clean up. */ + (void)fclose(fp); + + return(1); +} + + +/* Write the given BITMAP-format image as an 8-bit RGBA PNG image file. */ +int +png_write_rgb(const wchar_t *fn, uint8_t *pix, int16_t w, int16_t h) +{ + png_structp png = NULL; + png_infop info = NULL; + png_bytepp rows; + uint8_t *r, *b; + FILE *fp; + int y, x; + + /* Load the DLL if needed, give up if that fails. */ + if (! png_load()) return(0); + + /* Create the image file. */ + fp = plat_fopen(fn, L"wb"); + if (fp == NULL) { + pclog("[PNG] File %ls could not be opened for writing!\n", fn); +error: + if (png != NULL) + PNGFUNC(destroy_write_struct)(&png, &info); + if (fp != NULL) + (void)fclose(fp); + return(0); + } + + /* Initialize PNG stuff. */ + png = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, NULL, + error_handler, warning_handler); + if (png == NULL) { + pclog("[PNG] create_write_struct failed!\n"); + goto error; + } + + info = PNGFUNC(create_info_struct)(png); + if (info == NULL) { + pclog("[PNG] create_info_struct failed!\n"); + goto error; + } + +#if USE_CUSTOM_IO + /* + * We use our own I/O routines, because it seems that some of + * the PNG DLL's out there are compiled in Debug mode, which + * causes the 'FILE' definition to be different. This in turn + * results in pretty bad crashes when trying to write.. + * + * Using custom I/O routines, we avoid this issue. + */ + PNGFUNC(set_write_fn)(png, (void *)fp, write_handler, flush_handler); +#else + PNGFUNC(init_io)(png, fp); +#endif + + PNGFUNC(set_IHDR)(png, info, w, h, 8, PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + PNGFUNC(write_info)(png, info); + + /* Create a buffer for scanlines of pixels. */ + rows = (png_bytepp)malloc(sizeof(png_bytep) * h); + for (y = 0; y < h; y++) { + /* Create a buffer for this scanline. */ + rows[y] = (png_bytep)malloc(PNGFUNC(get_rowbytes)(png, info)); + } + + /* + * Process all scanlines in the image. + * + * Since the bitmap is in 'bottom-up' mode, we have to + * convert all pixels to RGB mode, but also 'flip' the + * image to the normal top-down mode. + */ + for (y = 0; y < h; y++) { + for (x = 0; x < x; x++) { + /* Get pointer to pixel in bitmap data. */ + b = &pix[((y * w) + x) * 4]; + + /* Get pointer to png row data. */ + r = &rows[(h - 1) - y][x * 3]; + + /* Copy the pixel data. */ + r[0] = b[2]; + r[1] = b[1]; + r[2] = b[0]; + } + } + + /* Write image to the file. */ + PNGFUNC(write_image)(png, rows); + + /* No longer need the row buffers. */ + for (y = 0; y < h; y++) + free(rows[y]); + free(rows); + + PNGFUNC(write_end)(png, NULL); + + PNGFUNC(destroy_write_struct)(&png, &info); + + /* Clean up. */ + (void)fclose(fp); + + return(1); +} diff --git a/src/png.h b/src/png.h new file mode 100644 index 0000000..20cd5c8 --- /dev/null +++ b/src/png.h @@ -0,0 +1,69 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the centralized PNG image handler. + * + * Version: @(#)png.h 1.0.1 2018/09/01 + * + * Author: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EMU_PNG_H +# define EMU_PNG_H + + +#ifdef __cplusplus +extern "C" { +#endif + +extern int png_load(void); +extern void png_unload(void); + +extern int png_write_gray(const wchar_t *path, int invert, + uint8_t *pix, int16_t w, int16_t h); + +extern int png_write_rgb(const wchar_t *fn, + uint8_t *pix, int16_t w, int16_t h); + +#ifdef __cplusplus +} +#endif + + +#endif /*EMU_PNG_H*/ diff --git a/src/win/mingw/Makefile.MinGW b/src/win/mingw/Makefile.MinGW index 42e2100..f9d6a92 100644 --- a/src/win/mingw/Makefile.MinGW +++ b/src/win/mingw/Makefile.MinGW @@ -8,7 +8,7 @@ # # Makefile for Windows systems using the MinGW32 environment. # -# Version: @(#)Makefile.mingw 1.0.56 2018/08/31 +# Version: @(#)Makefile.mingw 1.0.57 2018/09/01 # # Author: Fred N. van Kempen, # @@ -571,7 +571,7 @@ CXXFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ # Create the (final) list of objects to build. # ######################################################################### -MAINOBJ := pc.o config.o misc.o random.o timer.o io.o mem.o \ +MAINOBJ := pc.o config.o misc.o random.o timer.o io.o mem.o png.o \ rom.o rom_load.o device.o nvr.o $(VNCOBJ) $(RDPOBJ) UIOBJ += ui_main.o ui_new_image.o ui_stbar.o ui_vidapi.o diff --git a/src/win/msvc/Makefile.VC b/src/win/msvc/Makefile.VC index ed68087..e320e70 100644 --- a/src/win/msvc/Makefile.VC +++ b/src/win/msvc/Makefile.VC @@ -8,7 +8,7 @@ # # Makefile for Windows using Visual Studio 2015. # -# Version: @(#)Makefile.VC 1.0.42 2018/08/31 +# Version: @(#)Makefile.VC 1.0.43 2018/09/01 # # Author: Fred N. van Kempen, # @@ -541,7 +541,7 @@ CXXFLAGS := $(WX_FLAGS) $(OPTS) $(CXXOPTS) $(COPTS) $(DOPTS) $(AOPTIM) $(AFLAGS) RESDLL := VARCem-$(LANG) MAINOBJ := pc.obj config.obj misc.obj random.obj timer.obj io.obj \ - mem.obj rom.obj rom_load.obj device.obj nvr.obj \ + mem.obj rom.obj rom_load.obj device.obj nvr.obj png.obj \ $(VNCOBJ) $(RDPOBJ) UIOBJ += ui_main.obj ui_new_image.obj ui_stbar.obj ui_vidapi.obj diff --git a/src/win/win.c b/src/win/win.c index 3c90778..bef01ff 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -8,7 +8,7 @@ * * Platform main support module for Windows. * - * Version: @(#)win.c 1.0.17 2018/07/28 + * Version: @(#)win.c 1.0.18 2018/09/02 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -374,12 +374,12 @@ plat_tempfile(wchar_t *bufp, const wchar_t *prefix, const wchar_t *suffix) char temp[1024]; if (prefix != NULL) - sprintf(temp, "%ls", prefix); + sprintf(temp, "%ls-", prefix); else - strcpy(temp, EMU_NAME); + strcpy(temp, ""); GetSystemTime(&SystemTime); - sprintf(&temp[strlen(temp)], "-%d%02d%02d-%02d-%02d-%02d-%03d%ls", + sprintf(&temp[strlen(temp)], "%d%02d%02d-%02d-%02d-%02d-%03d%ls", SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, SystemTime.wMilliseconds, suffix); diff --git a/src/win/win_ddraw.cpp b/src/win/win_ddraw.cpp index 3e58b39..f087268 100644 --- a/src/win/win_ddraw.cpp +++ b/src/win/win_ddraw.cpp @@ -8,12 +8,7 @@ * * Rendering module for Microsoft DirectDraw 9. * - * If configured with USE_LIBPNG, we try to load the external - * PNG library and use that if found. Otherwise, we fall back - * the original mode, which uses the Windows/DDraw built-in BMP - * format. - * - * Version: @(#)win_ddraw.cpp 1.0.16 2018/06/18 + * Version: @(#)win_ddraw.cpp 1.0.17 2018/09/02 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,14 +41,13 @@ #include #include #include -#ifdef USE_LIBPNG -# define PNG_DEBUG 0 -# include -#endif #include "../emu.h" #include "../device.h" #include "../ui/ui.h" #include "../plat.h" +#ifdef USE_LIBPNG +# include "../png.h" +#endif #ifdef _MSC_VER # pragma warning(disable: 4200) #endif @@ -61,11 +55,6 @@ #include "win.h" -#ifdef USE_LIBPNG -# define PATH_PNG_DLL "libpng16.dll" -#endif - - static LPDIRECTDRAW4 lpdd4 = NULL; static LPDIRECTDRAWSURFACE4 lpdds_pri = NULL, lpdds_back = NULL, @@ -74,55 +63,6 @@ static LPDIRECTDRAWCLIPPER lpdd_clipper = NULL; static HWND ddraw_hwnd; static int ddraw_w, ddraw_h, xs, ys, ys2; -#ifdef USE_LIBPNG -static void *png_handle = NULL; /* handle to DLL */ -# if USE_LIBPNG == 1 -# define PNGFUNC(x) png_ ## x -# else -# define PNGFUNC(x) PNG_ ## x - - -/* Pointers to the real functions. */ -extern "C" { -png_structp (*PNG_create_write_struct)(png_const_charp user_png_ver, - png_voidp error_ptr, - png_error_ptr error_fn, - png_error_ptr warn_fn); -void (*PNG_destroy_write_struct)(png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr); -png_infop (*PNG_create_info_struct)(png_const_structrp png_ptr); -void (*PNG_init_io)(png_structrp png_ptr, png_FILE_p fp); -void (*PNG_set_IHDR)(png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_32 width, - png_uint_32 height, int bit_depth, - int color_type, int interlace_method, - int compression_method, - int filter_method); -png_size_t (*PNG_get_rowbytes)(png_const_structrp png_ptr, - png_const_inforp info_ptr); -void (*PNG_write_info)(png_structrp png_ptr, - png_const_inforp info_ptr); -void (*PNG_write_image)(png_structrp png_ptr, - png_bytepp image); -void (*PNG_write_end)(png_structrp png_ptr, - png_inforp info_ptr); -}; - - -static const dllimp_t png_imports[] = { - { "png_create_write_struct", &PNG_create_write_struct }, - { "png_destroy_write_struct", &PNG_destroy_write_struct }, - { "png_create_info_struct", &PNG_create_info_struct }, - { "png_init_io", &PNG_init_io }, - { "png_set_IHDR", &PNG_set_IHDR }, - { "png_get_rowbytes", &PNG_get_rowbytes }, - { "png_write_info", &PNG_write_info }, - { "png_write_image", &PNG_write_image }, - { "png_write_end", &PNG_write_end }, - { NULL, NULL } -}; -# endif -#endif static const char * @@ -473,14 +413,6 @@ ddraw_close(void) lpdd4->Release(); lpdd4 = NULL; } - -#if defined(USE_LIBPNG) && USE_LIBPNG == 2 - /* Unload the DLL if possible. */ - if (png_handle != NULL) { - dynld_close(png_handle); - png_handle = NULL; - } -#endif } @@ -627,131 +559,10 @@ ddraw_init(int fs) else video_setblit(ddraw_blit); -#ifdef USE_LIBPNG -# if USE_LIBPNG == 2 - /* Try loading the DLL. */ - png_handle = dynld_module(PATH_PNG_DLL, png_imports); - if (png_handle == NULL) - pclog("DDraw: unable to load '%s', using BMP for screenshots.\n", - PATH_PNG_DLL); -# else - png_handle = (void *)1; /* just to indicate always therse */ -# endif -#endif - return(1); } -#ifdef USE_LIBPNG -static void -error_handler(png_structp arg, const char *str) -{ - pclog("PNG: stream 0x%08lx error '%s'\n", arg, str); -} - - -static void -warning_handler(png_structp arg, const char *str) -{ - pclog("PNG: stream 0x%08lx warning '%s'\n", arg, str); -} - - -static int -SavePNG(const wchar_t *fn, BITMAPINFO *bmi, uint8_t *pixels) -{ - png_structp png = NULL; - png_infop info = NULL; - png_bytepp rows; - uint8_t *r, *b; - FILE *fp; - int h, w; - - /* Create the image file. */ - fp = plat_fopen(fn, L"wb"); - if (fp == NULL) { - pclog("[SavePNG] File %ls could not be opened for writing!\n", fn); -error: - if (png != NULL) - PNGFUNC(destroy_write_struct)(&png, &info); - if (fp != NULL) - (void)fclose(fp); - return(0); - } - - /* Initialize PNG stuff. */ - png = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, NULL, - error_handler, warning_handler); - if (png == NULL) { - pclog("[SavePNG] create_write_struct failed!\n"); - goto error; - } - - info = PNGFUNC(create_info_struct)(png); - if (info == NULL) { - pclog("[SavePNG] create_info_struct failed!\n"); - goto error; - } - - PNGFUNC(init_io)(png, fp); - - PNGFUNC(set_IHDR)(png, info, - bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 8, - PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - PNGFUNC(write_info)(png, info); - - /* Create a buffer for scanlines of pixels. */ - rows = (png_bytepp)malloc(sizeof(png_bytep) * bmi->bmiHeader.biHeight); - for (h = 0; h < bmi->bmiHeader.biHeight; h++) { - /* Create a buffer for this scanline. */ - rows[h] = (png_bytep)malloc(PNGFUNC(get_rowbytes)(png, info)); - } - - /* - * Process all scanlines in the image. - * - * Since the bitmap is un bottom-up mode, we have to convert - * all pixels to RGB mode, but also 'flip' the image to the - * normal top-down mode. - */ - for (h = 0; h < bmi->bmiHeader.biHeight; h++) { - for (w = 0; w < bmi->bmiHeader.biWidth; w++) { - /* Get pointer to pixel in bitmap data. */ - b = &pixels[((h * bmi->bmiHeader.biWidth) + w) * 4]; - - /* Get pointer to png row data. */ - r = &rows[(bmi->bmiHeader.biHeight - 1) - h][w * 3]; - - /* Copy the pixel data. */ - r[0] = b[2]; - r[1] = b[1]; - r[2] = b[0]; - } - } - - /* Write image to the file. */ - PNGFUNC(write_image)(png, rows); - - /* No longer need the row buffers. */ - for (h = 0; h < bmi->bmiHeader.biHeight; h++) - free(rows[h]); - free(rows); - - PNGFUNC(write_end)(png, NULL); - - PNGFUNC(destroy_write_struct)(&png, &info); - - /* Clean up. */ - (void)fclose(fp); - - return(1); -} -#endif - - static int SaveBMP(const wchar_t *fn, BITMAPINFO *bmi, uint8_t *pixels) { @@ -909,10 +720,10 @@ ddraw_screenshot(const wchar_t *fn) #ifdef USE_LIBPNG /* Save the screenshot, using PNG if available. */ - if (png_handle != NULL) { - /* Use the PNG library. */ - i = SavePNG(path, &bmi, pixels); - } else { + i = png_write_rgb(path, pixels, + (int16_t)bmi.bmiHeader.biWidth, + (int16_t)abs(bmi.bmiHeader.biHeight)); + if (i == 0) { #endif /* Use BMP, so fix the file name. */ path[wcslen(path)-3] = L'b';