2020-02-15 23:36:20 +01:00
# include " stdafx.h "
# include "Emu/VFS.h"
2015-03-12 20:02:02 +01:00
# include "Emu/IdManager.h"
2016-03-21 20:43:03 +01:00
# include "Emu/Cell/PPUModule.h"
2015-03-12 20:02:02 +01:00
2016-03-21 20:43:03 +01:00
# include "Emu/Cell/lv2/sys_fs.h"
2016-01-19 20:24:41 +01:00
# include "png.h"
2014-08-23 22:40:04 +02:00
# include "cellPngDec.h"
2013-09-08 10:45:10 +02:00
2016-07-01 06:07:16 +02:00
# if PNG_LIBPNG_VER_MAJOR >= 1 && (PNG_LIBPNG_VER_MINOR < 5 \
| | ( PNG_LIBPNG_VER_MINOR = = 5 & & PNG_LIBPNG_VER_RELEASE < 7 ) )
# define PNG_ERROR_ACTION_NONE 1
# define PNG_RGB_TO_GRAY_DEFAULT (-1)
# endif
# if PNG_LIBPNG_VER_MAJOR >= 1 && PNG_LIBPNG_VER_MINOR >= 5
typedef png_bytep iCCP_profile_type ;
# else
typedef png_charp iCCP_profile_type ;
# endif
2018-08-25 14:39:00 +02:00
LOG_CHANNEL ( cellPngDec ) ;
2013-09-08 10:45:10 +02:00
2016-01-19 20:24:41 +01:00
// cellPngDec aliases to improve readability
using PPHandle = vm : : pptr < PngHandle > ;
using PHandle = vm : : ptr < PngHandle > ;
using PThreadInParam = vm : : cptr < CellPngDecThreadInParam > ;
using PThreadOutParam = vm : : ptr < CellPngDecThreadOutParam > ;
using PExtThreadInParam = vm : : cptr < CellPngDecExtThreadInParam > ;
2015-08-05 17:30:32 +02:00
using PExtThreadOutParam = vm : : ptr < CellPngDecExtThreadOutParam > ;
2016-01-19 20:24:41 +01:00
using PPStream = vm : : pptr < PngStream > ;
using PStream = vm : : ptr < PngStream > ;
using PSrc = vm : : cptr < CellPngDecSrc > ;
using POpenInfo = vm : : ptr < CellPngDecOpnInfo > ;
using POpenParam = vm : : cptr < CellPngDecOpnParam > ;
using PInfo = vm : : ptr < CellPngDecInfo > ;
using PExtInfo = vm : : ptr < CellPngDecExtInfo > ;
using PInParam = vm : : cptr < CellPngDecInParam > ;
using POutParam = vm : : ptr < CellPngDecOutParam > ;
using PExtInParam = vm : : cptr < CellPngDecExtInParam > ;
using PExtOutParam = vm : : ptr < CellPngDecExtOutParam > ;
using PDataControlParam = vm : : cptr < CellPngDecDataCtrlParam > ;
using PDataOutInfo = vm : : ptr < CellPngDecDataOutInfo > ;
using PCbControlDisp = vm : : cptr < CellPngDecCbCtrlDisp > ;
using PCbControlStream = vm : : cptr < CellPngDecCbCtrlStrm > ;
using PDispParam = vm : : ptr < CellPngDecDispParam > ;
// Custom read function for libpng, so we could decode images from a buffer
void pngDecReadBuffer ( png_structp png_ptr , png_bytep out , png_size_t length )
{
// Get the IO pointer
png_voidp io_ptr = png_get_io_ptr ( png_ptr ) ;
// Check if obtaining of the IO pointer failed
if ( ! io_ptr )
2014-09-08 16:56:47 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . error ( " Failed to obtain the io_ptr failed. " ) ;
return ;
2014-09-08 16:56:47 +02:00
}
2016-01-19 20:24:41 +01:00
// Cast the IO pointer to our custom structure
2019-12-02 22:31:34 +01:00
PngBuffer & buffer = * static_cast < PngBuffer * > ( io_ptr ) ;
2014-05-30 19:44:38 +02:00
2016-01-19 20:24:41 +01:00
// Read froma file or a buffer
if ( buffer . file )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
// Get the file
2017-01-26 02:12:50 +01:00
auto file = idm : : get < lv2_fs_object , lv2_file > ( buffer . fd ) ;
2016-01-19 20:24:41 +01:00
// Read the data
2016-03-21 20:43:03 +01:00
file - > file . read ( out , length ) ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
else
{
// Get the current data pointer, including the current cursor position
void * data = static_cast < u8 * > ( buffer . data . get_ptr ( ) ) + buffer . cursor ;
2014-09-09 14:13:38 +02:00
2016-01-19 20:24:41 +01:00
// Copy the length of the current data pointer to the output
memcpy ( out , data , length ) ;
// Increment the cursor for the next time
buffer . cursor + = length ;
}
2013-09-08 10:45:10 +02:00
}
2017-02-19 12:59:49 +01:00
void pngDecRowCallback ( png_structp png_ptr , png_bytep new_row , png_uint_32 row_num , int pass )
{
2019-12-02 22:31:34 +01:00
PngStream * stream = static_cast < PngStream * > ( png_get_progressive_ptr ( png_ptr ) ) ;
2018-08-25 14:39:00 +02:00
if ( ! stream )
2017-02-19 12:59:49 +01:00
{
cellPngDec . error ( " Failed to obtain streamPtr in rowCallback. " ) ;
return ;
}
// we have to check this everytime as this func can be called multiple times per row, and/or only once per row
if ( stream - > nextRow + stream - > outputCounts = = row_num )
stream - > nextRow = row_num ;
if ( stream - > ppuContext & & ( stream - > nextRow = = row_num | | pass > 0 ) )
{
2018-08-25 14:39:00 +02:00
if ( pass > 0 )
2017-02-19 12:59:49 +01:00
{
2018-08-25 14:39:00 +02:00
stream - > cbDispInfo - > scanPassCount = pass ;
2017-02-19 12:59:49 +01:00
stream - > cbDispInfo - > nextOutputStartY = row_num ;
}
else {
stream - > cbDispInfo - > scanPassCount = 0 ;
stream - > cbDispInfo - > nextOutputStartY = 0 ;
}
stream - > cbDispInfo - > outputImage = stream - > cbDispParam - > nextOutputImage ;
stream - > cbCtrlDisp . cbCtrlDispFunc ( * stream - > ppuContext , stream - > cbDispInfo , stream - > cbDispParam , stream - > cbCtrlDisp . cbCtrlDispArg ) ;
stream - > cbDispInfo - > outputStartY = row_num ;
}
u8 * data ;
2018-08-25 14:39:00 +02:00
if ( pass > 0 )
2017-02-19 12:59:49 +01:00
data = static_cast < u8 * > ( stream - > cbDispParam - > nextOutputImage . get_ptr ( ) ) ;
else
data = static_cast < u8 * > ( stream - > cbDispParam - > nextOutputImage . get_ptr ( ) ) + ( ( row_num - stream - > cbDispInfo - > outputStartY ) * stream - > cbDispInfo - > outputFrameWidthByte ) ;
png_progressive_combine_row ( png_ptr , data , new_row ) ;
}
2018-08-25 14:39:00 +02:00
void pngDecInfoCallback ( png_structp png_ptr , png_infop info )
2017-02-19 12:59:49 +01:00
{
2019-12-02 22:31:34 +01:00
PngStream * stream = static_cast < PngStream * > ( png_get_progressive_ptr ( png_ptr ) ) ;
2018-08-25 14:39:00 +02:00
if ( ! stream )
2017-02-19 12:59:49 +01:00
{
cellPngDec . error ( " Failed to obtain streamPtr in rowCallback. " ) ;
return ;
}
const size_t remaining = png_process_data_pause ( png_ptr , false ) ;
stream - > buffer - > cursor + = ( stream - > buffer - > length - remaining ) ;
}
void pngDecEndCallback ( png_structp png_ptr , png_infop info )
{
2019-12-02 22:31:34 +01:00
PngStream * stream = static_cast < PngStream * > ( png_get_progressive_ptr ( png_ptr ) ) ;
2018-08-25 14:39:00 +02:00
if ( ! stream )
2017-02-19 12:59:49 +01:00
{
cellPngDec . error ( " Failed to obtain streamPtr in endCallback. " ) ;
return ;
}
stream - > endOfFile = true ;
}
2016-01-19 20:24:41 +01:00
// Custom error handler for libpng
void pngDecError ( png_structp png_ptr , png_const_charp error_message )
{
2019-10-09 01:14:52 +02:00
cellPngDec . error ( " %s " , error_message ) ;
2017-02-19 12:59:49 +01:00
// we can't return here or libpng blows up
2020-03-09 17:18:39 +01:00
report_fatal_error ( " Fatal Error in libpng " ) ;
2016-01-19 20:24:41 +01:00
}
// Custom warning handler for libpng
void pngDecWarning ( png_structp png_ptr , png_const_charp error_message )
{
2019-10-09 01:14:52 +02:00
cellPngDec . warning ( " %s " , error_message ) ;
2016-01-19 20:24:41 +01:00
}
// Get the chunk information of the PNG file. IDAT is marked as existing, only after decoding or reading the header.
// Bits (if set indicates existence of the chunk):
// 0 - gAMA
// 1 - sBIT
// 2 - cHRM
// 3 - PLTE
// 4 - tRNS
// 5 - bKGD
// 6 - hIST
// 7 - pHYs
// 8 - oFFs
// 9 - tIME
// 10 - pCAL
// 11 - sRGB
// 12 - iCCP
// 13 - sPLT
// 14 - sCAL
// 15 - IDAT
// 16:30 - reserved
2017-02-19 12:59:49 +01:00
be_t < u32 > pngDecGetChunkInformation ( PngStream * stream , bool IDAT = false )
2016-01-19 20:24:41 +01:00
{
// The end result of the chunk information (bigger-endian)
be_t < u32 > chunk_information = 0 ;
// Needed pointers for getting the chunk information
f64 gamma ;
f64 red_x ;
f64 red_y ;
f64 green_x ;
f64 green_y ;
f64 blue_x ;
f64 blue_y ;
f64 white_x ;
f64 white_y ;
f64 width ;
f64 height ;
s32 intent ;
s32 num_trans ;
s32 num_palette ;
s32 unit_type ;
s32 type ;
s32 nparams ;
s32 compression_type ;
s32 unit ;
u16 * hist ;
2016-07-01 06:07:16 +02:00
png_uint_32 proflen ;
iCCP_profile_type profile ;
2016-01-19 20:24:41 +01:00
png_bytep trans_alpha ;
png_charp units ;
png_charp name ;
png_charp purpose ;
png_charpp params ;
png_int_32 X0 ;
png_int_32 X1 ;
png_int_32 offset_x ;
png_int_32 offset_y ;
png_uint_32 res_x ;
png_uint_32 res_y ;
png_colorp palette ;
png_color_8p sig_bit ;
png_color_16p background ;
png_color_16p trans_color ;
png_sPLT_tp entries ;
png_timep mod_time ;
// Get chunk information and set the appropriate bits
if ( png_get_gAMA ( stream - > png_ptr , stream - > info_ptr , & gamma ) )
2014-09-08 16:56:47 +02:00
{
2016-01-19 20:24:41 +01:00
chunk_information | = 1 < < 0 ; // gAMA
2014-09-08 16:56:47 +02:00
}
2014-09-09 14:13:38 +02:00
2016-01-19 20:24:41 +01:00
if ( png_get_sBIT ( stream - > png_ptr , stream - > info_ptr , & sig_bit ) )
{
chunk_information | = 1 < < 1 ; // sBIT
}
2013-09-08 10:45:10 +02:00
2016-01-19 20:24:41 +01:00
if ( png_get_cHRM ( stream - > png_ptr , stream - > info_ptr , & white_x , & white_y , & red_x , & red_y , & green_x , & green_y , & blue_x , & blue_y ) )
{
chunk_information | = 1 < < 2 ; // cHRM
}
2014-09-08 16:56:47 +02:00
2016-01-19 20:24:41 +01:00
if ( png_get_PLTE ( stream - > png_ptr , stream - > info_ptr , & palette , & num_palette ) )
2014-09-08 16:56:47 +02:00
{
2016-01-19 20:24:41 +01:00
chunk_information | = 1 < < 3 ; // PLTE
2014-09-08 16:56:47 +02:00
}
2013-09-08 10:45:10 +02:00
2016-01-19 20:24:41 +01:00
if ( png_get_tRNS ( stream - > png_ptr , stream - > info_ptr , & trans_alpha , & num_trans , & trans_color ) )
2013-11-28 13:27:04 +01:00
{
2016-01-19 20:24:41 +01:00
chunk_information | = 1 < < 4 ; // tRNS
}
2013-12-24 04:58:32 +01:00
2016-01-19 20:24:41 +01:00
if ( png_get_bKGD ( stream - > png_ptr , stream - > info_ptr , & background ) )
2015-03-12 20:02:02 +01:00
{
2016-01-19 20:24:41 +01:00
chunk_information | = 1 < < 5 ; // bKGD
}
2015-05-27 05:11:59 +02:00
2016-01-19 20:24:41 +01:00
if ( png_get_hIST ( stream - > png_ptr , stream - > info_ptr , & hist ) )
{
chunk_information | = 1 < < 6 ; // hIST
}
if ( png_get_pHYs ( stream - > png_ptr , stream - > info_ptr , & res_x , & res_y , & unit_type ) )
{
chunk_information | = 1 < < 7 ; // pHYs
2013-11-28 13:27:04 +01:00
}
2016-01-19 20:24:41 +01:00
if ( png_get_oFFs ( stream - > png_ptr , stream - > info_ptr , & offset_x , & offset_y , & unit_type ) )
{
chunk_information | = 1 < < 8 ; // oFFs
2015-03-12 20:02:02 +01:00
}
2013-09-13 19:29:54 +02:00
2016-01-19 20:24:41 +01:00
if ( png_get_tIME ( stream - > png_ptr , stream - > info_ptr , & mod_time ) )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
chunk_information | = 1 < < 9 ; // tIME
2014-09-08 02:54:17 +02:00
}
2014-06-29 05:21:57 +02:00
2016-01-19 20:24:41 +01:00
if ( png_get_pCAL ( stream - > png_ptr , stream - > info_ptr , & purpose , & X0 , & X1 , & type , & nparams , & units , & params ) )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
chunk_information | = 1 < < 10 ; // pCAL
2014-09-08 02:54:17 +02:00
}
2014-06-29 05:21:57 +02:00
2016-01-19 20:24:41 +01:00
if ( png_get_sRGB ( stream - > png_ptr , stream - > info_ptr , & intent ) )
{
chunk_information | = 1 < < 11 ; // sRGB
}
2014-09-09 14:13:38 +02:00
2019-12-02 22:31:34 +01:00
if ( png_get_iCCP ( stream - > png_ptr , stream - > info_ptr , & name , & compression_type , & profile , & proflen ) )
2016-01-19 20:24:41 +01:00
{
chunk_information | = 1 < < 12 ; // iCCP
}
2014-09-09 14:13:38 +02:00
2016-01-19 20:24:41 +01:00
if ( png_get_sPLT ( stream - > png_ptr , stream - > info_ptr , & entries ) )
{
chunk_information | = 1 < < 13 ; // sPLT
}
if ( png_get_sCAL ( stream - > png_ptr , stream - > info_ptr , & unit , & width , & height ) )
{
chunk_information | = 1 < < 14 ; // sCAL
}
if ( IDAT )
{
chunk_information | = 1 < < 15 ; // IDAT
}
return chunk_information ;
2014-06-28 03:19:44 +02:00
}
2016-07-27 23:43:22 +02:00
s32 pngDecCreate ( ppu_thread & ppu , PPHandle png_handle , PThreadInParam thread_in_param , PThreadOutParam thread_out_param , PExtThreadInParam extra_thread_in_param = vm : : null , PExtThreadOutParam extra_thread_out_param = vm : : null )
2013-09-08 10:45:10 +02:00
{
2016-01-19 20:24:41 +01:00
// Check if partial image decoding is used
if ( extra_thread_out_param )
{
2016-08-08 18:01:06 +02:00
fmt : : throw_exception ( " Partial image decoding is not supported. " HERE ) ;
2016-01-19 20:24:41 +01:00
}
// Allocate memory for the decoder handle
auto handle = vm : : ptr < PngHandle > : : make ( thread_in_param - > cbCtrlMallocFunc ( ppu , sizeof ( PngHandle ) , thread_in_param - > cbCtrlMallocArg ) . addr ( ) ) ;
2015-03-12 20:02:02 +01:00
2016-01-19 20:24:41 +01:00
// Check if the memory allocation for the handle failed
if ( ! handle )
2014-09-08 16:56:47 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . error ( " PNG decoder creation failed. " ) ;
2014-09-09 14:13:38 +02:00
return CELL_PNGDEC_ERROR_FATAL ;
2014-09-08 16:56:47 +02:00
}
2014-09-09 14:13:38 +02:00
2016-01-19 20:24:41 +01:00
// Set the allocation functions in the handle
2017-01-28 13:32:45 +01:00
handle - > malloc_ = thread_in_param - > cbCtrlMallocFunc ;
2016-01-19 20:24:41 +01:00
handle - > malloc_arg = thread_in_param - > cbCtrlMallocArg ;
2017-01-28 13:32:45 +01:00
handle - > free_ = thread_in_param - > cbCtrlFreeFunc ;
2016-01-19 20:24:41 +01:00
handle - > free_arg = thread_in_param - > cbCtrlFreeArg ;
// Set handle pointer
* png_handle = handle ;
// Set the version information
thread_out_param - > pngCodecVersion = PNGDEC_CODEC_VERSION ;
2014-09-09 14:13:38 +02:00
return CELL_OK ;
2013-09-08 10:45:10 +02:00
}
2016-07-27 23:43:22 +02:00
s32 pngDecDestroy ( ppu_thread & ppu , PHandle handle )
2013-09-08 10:45:10 +02:00
{
2016-01-19 20:24:41 +01:00
// Deallocate the decoder handle memory
2017-01-28 13:32:45 +01:00
if ( handle - > free_ ( ppu , handle , handle - > free_arg ) ! = 0 )
2016-01-19 20:24:41 +01:00
{
cellPngDec . error ( " PNG decoder deallocation failed. " ) ;
return CELL_PNGDEC_ERROR_FATAL ;
}
2013-10-06 14:07:42 +02:00
2016-01-19 20:24:41 +01:00
return CELL_OK ;
}
2016-07-27 23:43:22 +02:00
s32 pngDecOpen ( ppu_thread & ppu , PHandle handle , PPStream png_stream , PSrc source , POpenInfo open_info , PCbControlStream control_stream = vm : : null , POpenParam open_param = vm : : null )
2016-01-19 20:24:41 +01:00
{
2017-02-19 12:59:49 +01:00
// partial decoding only supported with buffer type
if ( source - > srcSelect ! = CELL_PNGDEC_BUFFER & & control_stream )
2014-09-08 16:56:47 +02:00
{
2017-02-19 12:59:49 +01:00
cellPngDec . error ( " Attempted partial image decode with file. " ) ;
return CELL_PNGDEC_ERROR_STREAM_FORMAT ;
2014-09-08 16:56:47 +02:00
}
2013-09-08 10:45:10 +02:00
2016-01-19 20:24:41 +01:00
// Allocate memory for the stream structure
2017-01-28 13:32:45 +01:00
auto stream = vm : : ptr < PngStream > : : make ( handle - > malloc_ ( ppu , sizeof ( PngStream ) , handle - > malloc_arg ) . addr ( ) ) ;
2013-10-06 14:07:42 +02:00
2016-01-19 20:24:41 +01:00
// Check if the allocation of memory for the stream structure failed
if ( ! stream )
2013-11-28 13:27:04 +01:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . error ( " PNG stream creation failed. " ) ;
return CELL_PNGDEC_ERROR_FATAL ;
}
// Set memory info
open_info - > initSpaceAllocated = sizeof ( PngStream ) ;
// Set the stream source to the source give by the game
stream - > source = * source ;
// Use virtual memory address as a handle
* png_stream = stream ;
// Allocate memory for the PNG buffer for decoding
2017-01-28 13:32:45 +01:00
auto buffer = vm : : ptr < PngBuffer > : : make ( handle - > malloc_ ( ppu , sizeof ( PngBuffer ) , handle - > malloc_arg ) . addr ( ) ) ;
2016-01-19 20:24:41 +01:00
// Check for if the buffer structure allocation failed
if ( ! buffer )
2015-03-12 20:02:02 +01:00
{
2016-08-08 18:01:06 +02:00
fmt : : throw_exception ( " Memory allocation for the PNG buffer structure failed. " HERE ) ;
2013-11-28 13:27:04 +01:00
}
2016-01-19 20:24:41 +01:00
// We might not be reading from a file stream
buffer - > file = false ;
// Set the buffer pointer in the stream structure, so we can later deallocate it
stream - > buffer = buffer ;
// Open the buffer/file and check the header
u8 header [ 8 ] ;
2016-03-29 17:58:59 +02:00
// Need to test it somewhere
if ( stream - > source . fileOffset ! = 0 )
{
2016-08-08 18:01:06 +02:00
fmt : : throw_exception ( " Non-0 file offset not supported. " HERE ) ;
2016-03-29 17:58:59 +02:00
}
2016-01-19 20:24:41 +01:00
// Depending on the source type, get the first 8 bytes
if ( source - > srcSelect = = CELL_PNGDEC_FILE )
{
// Open a file stream
2016-03-21 20:43:03 +01:00
fs : : file file_stream ( vfs : : get ( stream - > source . fileName . get_ptr ( ) ) ) ;
2018-08-25 14:39:00 +02:00
2016-01-19 20:24:41 +01:00
// Check if opening of the PNG file failed
if ( ! file_stream )
{
cellPngDec . error ( " Opening of PNG failed. (%s) " , stream - > source . fileName . get_ptr ( ) ) ;
return CELL_PNGDEC_ERROR_OPEN_FILE ;
}
// Read the header
2016-03-21 20:43:03 +01:00
if ( file_stream . read ( header , 8 ) ! = 8 )
2016-01-19 20:24:41 +01:00
{
cellPngDec . error ( " PNG header is too small. " ) ;
return CELL_PNGDEC_ERROR_HEADER ;
}
// Get the file descriptor
2017-01-26 02:12:50 +01:00
buffer - > fd = idm : : make < lv2_fs_object , lv2_file > ( stream - > source . fileName . get_ptr ( ) , std : : move ( file_stream ) , 0 , 0 ) ;
2016-01-19 20:24:41 +01:00
// Indicate that we need to read from a file stream
buffer - > file = true ;
}
else
{
// We can simply copy the first 8 bytes
memcpy ( header , stream - > source . streamPtr . get_ptr ( ) , 8 ) ;
2015-03-12 20:02:02 +01:00
}
2013-10-06 14:07:42 +02:00
2016-01-19 20:24:41 +01:00
// Check if the header indicates a valid PNG file
if ( png_sig_cmp ( header , 0 , 8 ) )
2014-09-08 16:56:47 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . error ( " PNG signature is invalid. " ) ;
2014-09-09 14:13:38 +02:00
return CELL_PNGDEC_ERROR_HEADER ;
2014-09-08 16:56:47 +02:00
}
2013-09-08 10:45:10 +02:00
2016-01-19 20:24:41 +01:00
// Create a libpng structure, also pass our custom error/warning functions
stream - > png_ptr = png_create_read_struct ( PNG_LIBPNG_VER_STRING , nullptr , pngDecError , pngDecWarning ) ;
// Check if the creation of the structure failed
if ( ! stream - > png_ptr )
2013-09-25 15:43:55 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . error ( " Creation of png_structp failed. " ) ;
return CELL_PNGDEC_ERROR_FATAL ;
2013-09-25 15:43:55 +02:00
}
2013-10-06 14:07:42 +02:00
2016-01-19 20:24:41 +01:00
// Create a libpng info structure
stream - > info_ptr = png_create_info_struct ( stream - > png_ptr ) ;
// Check if the creation of the structure failed
if ( ! stream - > info_ptr )
{
2016-08-08 18:01:06 +02:00
fmt : : throw_exception ( " Creation of png_infop failed. " HERE ) ;
2016-01-19 20:24:41 +01:00
}
// We must indicate, that we allocated more memory
2019-06-28 14:41:47 +02:00
open_info - > initSpaceAllocated + = u32 { sizeof ( PngBuffer ) } ;
2014-09-09 14:13:38 +02:00
2016-01-19 20:24:41 +01:00
if ( source - > srcSelect = = CELL_PNGDEC_BUFFER )
2014-09-09 14:13:38 +02:00
{
2017-02-19 12:59:49 +01:00
buffer - > length = stream - > source . streamSize ;
2016-01-19 20:24:41 +01:00
buffer - > data = stream - > source . streamPtr ;
buffer - > cursor = 8 ;
2014-09-09 14:13:38 +02:00
}
2016-01-19 20:24:41 +01:00
// Set the custom read function for decoding
2018-08-25 14:39:00 +02:00
if ( control_stream )
2017-02-19 12:59:49 +01:00
{
2020-02-19 16:26:41 +01:00
if ( open_param & & open_param - > selectChunk ! = 0u )
2017-02-19 12:59:49 +01:00
fmt : : throw_exception ( " Partial Decoding with selectChunk not supported yet. " ) ;
2016-01-19 20:24:41 +01:00
2017-02-19 12:59:49 +01:00
stream - > cbCtrlStream . cbCtrlStrmArg = control_stream - > cbCtrlStrmArg ;
stream - > cbCtrlStream . cbCtrlStrmFunc = control_stream - > cbCtrlStrmFunc ;
2016-01-19 20:24:41 +01:00
2019-12-02 22:31:34 +01:00
png_set_progressive_read_fn ( stream - > png_ptr , stream . get_ptr ( ) , pngDecInfoCallback , pngDecRowCallback , pngDecEndCallback ) ;
2016-01-19 20:24:41 +01:00
2017-02-19 12:59:49 +01:00
// push header tag to libpng to keep us in sync
2020-03-09 17:18:39 +01:00
png_process_data ( stream - > png_ptr , stream - > info_ptr , header , 8 ) ;
2017-02-19 12:59:49 +01:00
}
2018-08-25 14:39:00 +02:00
else
2017-02-19 12:59:49 +01:00
{
png_set_read_fn ( stream - > png_ptr , buffer . get_ptr ( ) , pngDecReadBuffer ) ;
// We need to tell libpng, that we already read 8 bytes
png_set_sig_bytes ( stream - > png_ptr , 8 ) ;
}
2016-01-19 20:24:41 +01:00
2014-09-09 14:13:38 +02:00
return CELL_OK ;
2013-09-08 10:45:10 +02:00
}
2016-07-27 23:43:22 +02:00
s32 pngDecClose ( ppu_thread & ppu , PHandle handle , PStream stream )
2013-09-08 10:45:10 +02:00
{
2016-01-19 20:24:41 +01:00
// Remove the file descriptor, if a file descriptor was used for decoding
if ( stream - > buffer - > file )
{
2017-01-26 02:12:50 +01:00
idm : : remove < lv2_fs_object , lv2_file > ( stream - > buffer - > fd ) ;
2016-01-19 20:24:41 +01:00
}
2014-09-08 16:56:47 +02:00
2016-01-19 20:24:41 +01:00
// Deallocate the PNG buffer structure used to decode from memory, if we decoded from memory
if ( stream - > buffer )
{
2017-01-28 13:32:45 +01:00
if ( handle - > free_ ( ppu , stream - > buffer , handle - > free_arg ) ! = 0 )
2016-01-19 20:24:41 +01:00
{
cellPngDec . error ( " PNG buffer decoding structure deallocation failed. " ) ;
return CELL_PNGDEC_ERROR_FATAL ;
}
}
2014-09-08 16:56:47 +02:00
2016-01-19 20:24:41 +01:00
// Free the memory allocated by libpng
png_destroy_read_struct ( & stream - > png_ptr , & stream - > info_ptr , nullptr ) ;
// Deallocate the stream memory
2017-01-28 13:32:45 +01:00
if ( handle - > free_ ( ppu , stream , handle - > free_arg ) ! = 0 )
2014-09-08 16:56:47 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . error ( " PNG stream deallocation failed. " ) ;
return CELL_PNGDEC_ERROR_FATAL ;
}
2014-09-08 16:56:47 +02:00
2016-01-19 20:24:41 +01:00
return CELL_OK ;
}
2014-09-08 16:56:47 +02:00
2017-02-19 12:59:49 +01:00
void pngSetHeader ( PngStream * stream )
2016-01-19 20:24:41 +01:00
{
2017-02-19 12:59:49 +01:00
stream - > info . imageWidth = png_get_image_width ( stream - > png_ptr , stream - > info_ptr ) ;
stream - > info . imageHeight = png_get_image_height ( stream - > png_ptr , stream - > info_ptr ) ;
stream - > info . numComponents = png_get_channels ( stream - > png_ptr , stream - > info_ptr ) ;
stream - > info . colorSpace = getPngDecColourType ( png_get_color_type ( stream - > png_ptr , stream - > info_ptr ) ) ;
stream - > info . bitDepth = png_get_bit_depth ( stream - > png_ptr , stream - > info_ptr ) ;
stream - > info . interlaceMethod = png_get_interlace_type ( stream - > png_ptr , stream - > info_ptr ) ;
stream - > info . chunkInformation = pngDecGetChunkInformation ( stream ) ;
}
2014-09-08 16:56:47 +02:00
2017-02-19 12:59:49 +01:00
s32 pngDecSetParameter ( PStream stream , PInParam in_param , POutParam out_param , PExtInParam extra_in_param = vm : : null , PExtOutParam extra_out_param = vm : : null )
{
if ( in_param - > outputPackFlag = = CELL_PNGDEC_1BYTE_PER_NPIXEL )
2016-01-19 20:24:41 +01:00
{
2017-02-19 12:59:49 +01:00
fmt : : throw_exception ( " Packing not supported! (%d) " HERE , in_param - > outputPackFlag ) ;
2016-01-19 20:24:41 +01:00
}
2017-02-19 12:59:49 +01:00
// flag to keep unknown chunks
png_set_keep_unknown_chunks ( stream - > png_ptr , PNG_HANDLE_CHUNK_IF_SAFE , 0 , 0 ) ;
2016-01-19 20:24:41 +01:00
2017-02-19 12:59:49 +01:00
// Scale 16 bit depth down to 8 bit depth.
2020-02-19 16:26:41 +01:00
if ( stream - > info . bitDepth = = 16u & & in_param - > outputBitDepth = = 8u )
2016-01-19 20:24:41 +01:00
{
2017-02-19 12:59:49 +01:00
// PS3 uses png_set_strip_16, since png_set_scale_16 wasn't available back then.
png_set_strip_16 ( stream - > png_ptr ) ;
2016-01-19 20:24:41 +01:00
}
2017-02-19 12:59:49 +01:00
// This shouldnt ever happen, but not sure what to do if it does, just want it logged for now
2020-02-19 16:26:41 +01:00
if ( stream - > info . bitDepth ! = 16u & & in_param - > outputBitDepth = = 16u )
2017-02-19 12:59:49 +01:00
cellPngDec . error ( " Output depth of 16 with non input depth of 16 specified! " ) ;
2019-12-20 04:51:16 +01:00
if ( in_param - > commandPtr )
2017-02-19 12:59:49 +01:00
cellPngDec . warning ( " Ignoring CommandPtr. " ) ;
2018-08-25 14:39:00 +02:00
if ( stream - > info . colorSpace ! = in_param - > outputColorSpace )
2016-01-19 20:24:41 +01:00
{
2018-08-25 14:39:00 +02:00
// check if we need to set alpha
2017-02-19 12:59:49 +01:00
const bool inputHasAlpha = cellPngColorSpaceHasAlpha ( stream - > info . colorSpace ) ;
const bool outputWantsAlpha = cellPngColorSpaceHasAlpha ( in_param - > outputColorSpace ) ;
2018-08-25 14:39:00 +02:00
if ( outputWantsAlpha & & ! inputHasAlpha )
2017-02-19 12:59:49 +01:00
{
if ( in_param - > outputAlphaSelect = = CELL_PNGDEC_FIX_ALPHA )
png_set_add_alpha ( stream - > png_ptr , in_param - > outputColorAlpha , in_param - > outputColorSpace = = CELL_PNGDEC_ARGB ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER ) ;
2018-08-25 14:39:00 +02:00
else
2017-02-19 12:59:49 +01:00
{
// Check if we can steal the alpha from a trns block
if ( png_get_valid ( stream - > png_ptr , stream - > info_ptr , PNG_INFO_tRNS ) )
png_set_tRNS_to_alpha ( stream - > png_ptr ) ;
// if not, just set default of 0xff
2018-08-25 14:39:00 +02:00
else
2017-02-19 12:59:49 +01:00
png_set_add_alpha ( stream - > png_ptr , 0xff , in_param - > outputColorSpace = = CELL_PNGDEC_ARGB ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER ) ;
}
}
else if ( inputHasAlpha & & ! outputWantsAlpha )
png_set_strip_alpha ( stream - > png_ptr ) ;
else if ( in_param - > outputColorSpace = = CELL_PNGDEC_ARGB & & stream - > info . colorSpace = = CELL_PNGDEC_RGBA )
png_set_swap_alpha ( stream - > png_ptr ) ;
// Handle gray<->rgb colorspace conversions
// rgb output
if ( in_param - > outputColorSpace = = CELL_PNGDEC_ARGB
| | in_param - > outputColorSpace = = CELL_PNGDEC_RGBA
| | in_param - > outputColorSpace = = CELL_PNGDEC_RGB )
{
if ( stream - > info . colorSpace = = CELL_PNGDEC_PALETTE )
png_set_palette_to_rgb ( stream - > png_ptr ) ;
if ( ( stream - > info . colorSpace = = CELL_PNGDEC_GRAYSCALE | | stream - > info . colorSpace = = CELL_PNGDEC_GRAYSCALE_ALPHA )
2018-08-25 14:39:00 +02:00
& & stream - > info . bitDepth < 8 )
2017-02-19 12:59:49 +01:00
png_set_expand_gray_1_2_4_to_8 ( stream - > png_ptr ) ;
}
// grayscale output
2018-08-25 14:39:00 +02:00
else
2017-02-19 12:59:49 +01:00
{
if ( stream - > info . colorSpace = = CELL_PNGDEC_ARGB
| | stream - > info . colorSpace = = CELL_PNGDEC_RGBA
2018-08-25 14:39:00 +02:00
| | stream - > info . colorSpace = = CELL_PNGDEC_RGB )
2017-02-19 12:59:49 +01:00
{
png_set_rgb_to_gray ( stream - > png_ptr , PNG_ERROR_ACTION_NONE , PNG_RGB_TO_GRAY_DEFAULT , PNG_RGB_TO_GRAY_DEFAULT ) ;
}
else {
2018-08-25 14:39:00 +02:00
// not sure what to do here
2017-02-19 12:59:49 +01:00
cellPngDec . error ( " Grayscale / Palette to Grayscale / Palette conversion currently unsupported. " ) ;
}
}
2016-01-19 20:24:41 +01:00
}
2017-02-19 12:59:49 +01:00
stream - > passes = png_set_interlace_handling ( stream - > png_ptr ) ;
// Update the info structure
png_read_update_info ( stream - > png_ptr , stream - > info_ptr ) ;
2016-01-19 20:24:41 +01:00
stream - > out_param . outputWidth = stream - > info . imageWidth ;
stream - > out_param . outputHeight = stream - > info . imageHeight ;
2017-02-19 12:59:49 +01:00
stream - > out_param . outputBitDepth = in_param - > outputBitDepth ;
2016-01-19 20:24:41 +01:00
stream - > out_param . outputColorSpace = in_param - > outputColorSpace ;
stream - > out_param . outputMode = in_param - > outputMode ;
2017-02-19 12:59:49 +01:00
2016-01-19 20:24:41 +01:00
stream - > out_param . outputWidthByte = png_get_rowbytes ( stream - > png_ptr , stream - > info_ptr ) ;
2017-02-19 12:59:49 +01:00
stream - > out_param . outputComponents = png_get_channels ( stream - > png_ptr , stream - > info_ptr ) ;
2016-01-19 20:24:41 +01:00
2017-02-19 12:59:49 +01:00
stream - > packing = in_param - > outputPackFlag ;
2016-01-19 20:24:41 +01:00
2017-02-19 12:59:49 +01:00
// Set the memory usage. We currently don't actually allocate memory for libpng through the callbacks, due to libpng needing a lot more memory compared to PS3 variant.
stream - > out_param . useMemorySpace = 0 ;
2016-01-19 20:24:41 +01:00
2018-08-25 14:39:00 +02:00
if ( extra_in_param )
2016-01-19 20:24:41 +01:00
{
2017-02-19 12:59:49 +01:00
if ( extra_in_param - > bufferMode ! = CELL_PNGDEC_LINE_MODE )
{
cellPngDec . error ( " Invalid Buffermode specified. " ) ;
return CELL_PNGDEC_ERROR_ARG ;
}
2014-09-08 16:56:47 +02:00
2017-02-19 12:59:49 +01:00
if ( stream - > passes > 1 )
{
stream - > outputCounts = 1 ;
}
else
stream - > outputCounts = extra_in_param - > outputCounts ;
2014-09-08 16:56:47 +02:00
2017-02-19 12:59:49 +01:00
if ( extra_out_param )
{
if ( stream - > outputCounts = = 0 )
extra_out_param - > outputHeight = stream - > out_param . outputHeight ;
2018-08-25 14:39:00 +02:00
else
2017-02-19 12:59:49 +01:00
extra_out_param - > outputHeight = std : : min ( stream - > outputCounts , stream - > out_param . outputHeight . value ( ) ) ;
extra_out_param - > outputWidthByte = stream - > out_param . outputWidthByte ;
}
2016-01-19 20:24:41 +01:00
}
2014-08-06 00:19:33 +02:00
2016-01-19 20:24:41 +01:00
* out_param = stream - > out_param ;
2018-08-25 14:39:00 +02:00
2014-09-09 14:13:38 +02:00
return CELL_OK ;
2014-09-08 16:56:47 +02:00
}
2016-07-27 23:43:22 +02:00
s32 pngDecodeData ( ppu_thread & ppu , PHandle handle , PStream stream , vm : : ptr < u8 > data , PDataControlParam data_control_param , PDataOutInfo data_out_info , PCbControlDisp cb_control_disp = vm : : null , PDispParam disp_param = vm : : null )
2014-09-08 16:56:47 +02:00
{
2016-01-19 20:24:41 +01:00
// Indicate, that the PNG decoding is stopped/failed. This is incase, we return an error code in the middle of decoding
data_out_info - > status = CELL_PNGDEC_DEC_STATUS_STOP ;
2013-09-08 10:45:10 +02:00
2019-10-25 12:32:21 +02:00
const u32 bytes_per_line = : : narrow < u32 > ( data_control_param - > outputBytesPerLine ) ;
2013-11-28 13:27:04 +01:00
2017-02-19 12:59:49 +01:00
// Log this for now
if ( bytes_per_line < stream - > out_param . outputWidthByte )
2013-11-28 13:27:04 +01:00
{
2017-02-19 12:59:49 +01:00
fmt : : throw_exception ( " Bytes per line less than expected output! Got: %d, expected: %d " HERE , bytes_per_line , stream - > out_param . outputWidthByte ) ;
2016-01-19 20:24:41 +01:00
}
2017-02-19 12:59:49 +01:00
// partial decoding
if ( cb_control_disp & & stream - > outputCounts > 0 )
2015-03-12 20:02:02 +01:00
{
2017-02-19 12:59:49 +01:00
// get data from cb
auto streamInfo = vm : : ptr < CellPngDecStrmInfo > : : make ( handle - > malloc_ ( ppu , sizeof ( CellPngDecStrmInfo ) , handle - > malloc_arg ) . addr ( ) ) ;
auto streamParam = vm : : ptr < CellPngDecStrmParam > : : make ( handle - > malloc_ ( ppu , sizeof ( CellPngDecStrmParam ) , handle - > malloc_arg ) . addr ( ) ) ;
stream - > cbDispInfo = vm : : ptr < CellPngDecDispInfo > : : make ( handle - > malloc_ ( ppu , sizeof ( CellPngDecDispInfo ) , handle - > malloc_arg ) . addr ( ) ) ;
stream - > cbDispParam = vm : : ptr < CellPngDecDispParam > : : make ( handle - > malloc_ ( ppu , sizeof ( CellPngDecDispParam ) , handle - > malloc_arg ) . addr ( ) ) ;
auto freeMem = [ & ] ( )
2016-01-19 20:24:41 +01:00
{
2017-02-19 12:59:49 +01:00
handle - > free_ ( ppu , streamInfo , handle - > free_arg ) ;
handle - > free_ ( ppu , streamParam , handle - > free_arg ) ;
handle - > free_ ( ppu , stream - > cbDispInfo , handle - > free_arg ) ;
handle - > free_ ( ppu , stream - > cbDispParam , handle - > free_arg ) ;
} ;
// set things that won't change between callbacks
stream - > cbDispInfo - > outputFrameWidthByte = bytes_per_line ;
stream - > cbDispInfo - > outputFrameHeight = stream - > out_param . outputHeight ;
stream - > cbDispInfo - > outputWidthByte = stream - > out_param . outputWidthByte ;
stream - > cbDispInfo - > outputBitDepth = stream - > out_param . outputBitDepth ;
stream - > cbDispInfo - > outputComponents = stream - > out_param . outputComponents ;
stream - > cbDispInfo - > outputHeight = stream - > outputCounts ;
stream - > cbDispInfo - > outputStartXByte = 0 ;
stream - > cbDispInfo - > outputStartY = 0 ;
stream - > cbDispInfo - > scanPassCount = 0 ;
stream - > cbDispInfo - > nextOutputStartY = 0 ;
stream - > ppuContext = & ppu ;
stream - > nextRow = stream - > cbDispInfo - > outputHeight ;
stream - > cbCtrlDisp . cbCtrlDispArg = cb_control_disp - > cbCtrlDispArg ;
stream - > cbCtrlDisp . cbCtrlDispFunc = cb_control_disp - > cbCtrlDispFunc ;
stream - > cbDispParam - > nextOutputImage = disp_param - > nextOutputImage ;
2019-06-28 14:41:47 +02:00
streamInfo - > decodedStrmSize = : : narrow < u32 > ( stream - > buffer - > cursor ) ;
2017-02-19 12:59:49 +01:00
// push the rest of the buffer we have
if ( stream - > buffer - > length > stream - > buffer - > cursor )
{
u8 * data = static_cast < u8 * > ( stream - > buffer - > data . get_ptr ( ) ) + stream - > buffer - > cursor ;
2020-03-09 17:18:39 +01:00
png_process_data ( stream - > png_ptr , stream - > info_ptr , data , stream - > buffer - > length - stream - > buffer - > cursor ) ;
2019-06-28 14:41:47 +02:00
streamInfo - > decodedStrmSize = : : narrow < u32 > ( stream - > buffer - > length ) ;
2016-01-19 20:24:41 +01:00
}
2017-02-19 12:59:49 +01:00
// todo: commandPtr
// then just loop until the end, the callbacks should take care of the rest
while ( stream - > endOfFile ! = true )
2016-01-19 20:24:41 +01:00
{
2017-02-19 12:59:49 +01:00
stream - > cbCtrlStream . cbCtrlStrmFunc ( ppu , streamInfo , streamParam , stream - > cbCtrlStream . cbCtrlStrmArg ) ;
streamInfo - > decodedStrmSize + = streamParam - > strmSize ;
2020-03-09 17:18:39 +01:00
png_process_data ( stream - > png_ptr , stream - > info_ptr , static_cast < u8 * > ( streamParam - > strmPtr . get_ptr ( ) ) , streamParam - > strmSize ) ;
2016-01-19 20:24:41 +01:00
}
2017-02-19 12:59:49 +01:00
freeMem ( ) ;
2016-03-29 17:58:59 +02:00
}
2017-02-19 12:59:49 +01:00
else
2014-09-09 14:13:38 +02:00
{
2017-02-19 12:59:49 +01:00
// Check if the image needs to be flipped
const bool flip = stream - > out_param . outputMode = = CELL_PNGDEC_BOTTOM_TO_TOP ;
2013-09-14 22:47:59 +02:00
2017-02-19 12:59:49 +01:00
// Decode the image
// todo: commandptr
2014-03-07 04:15:56 +01:00
{
2019-05-22 05:47:47 +02:00
for ( u32 j = 0 ; j < stream - > passes ; j + + )
2016-01-19 20:24:41 +01:00
{
2019-05-22 05:47:47 +02:00
for ( u32 i = 0 ; i < stream - > out_param . outputHeight ; + + i )
2017-02-19 12:59:49 +01:00
{
const u32 line = flip ? stream - > out_param . outputHeight - i - 1 : i ;
png_read_row ( stream - > png_ptr , & data [ line * bytes_per_line ] , nullptr ) ;
}
2014-03-07 04:15:56 +01:00
}
2017-02-19 12:59:49 +01:00
png_read_end ( stream - > png_ptr , stream - > info_ptr ) ;
2014-03-07 04:15:56 +01:00
}
2013-09-08 10:45:10 +02:00
}
2013-10-06 14:07:42 +02:00
2016-01-19 20:24:41 +01:00
// Get the number of iTXt, tEXt and zTXt chunks
2017-02-19 12:59:49 +01:00
const s32 text_chunks = png_get_text ( stream - > png_ptr , stream - > info_ptr , nullptr , nullptr ) ;
2014-09-08 02:54:17 +02:00
2016-01-19 20:24:41 +01:00
// Set the chunk information and the previously obtained number of text chunks
2019-12-02 22:31:34 +01:00
data_out_info - > numText = static_cast < u32 > ( text_chunks ) ;
2017-02-19 12:59:49 +01:00
data_out_info - > chunkInformation = pngDecGetChunkInformation ( stream . get_ptr ( ) , true ) ;
png_unknown_chunkp unknowns ;
const int num_unknowns = png_get_unknown_chunks ( stream - > png_ptr , stream - > info_ptr , & unknowns ) ;
data_out_info - > numUnknownChunk = num_unknowns ;
2014-09-08 02:54:17 +02:00
2016-01-19 20:24:41 +01:00
// Indicate that the decoding succeeded
data_out_info - > status = CELL_PNGDEC_DEC_STATUS_FINISH ;
2014-09-08 02:54:17 +02:00
return CELL_OK ;
}
2016-07-27 23:43:22 +02:00
s32 cellPngDecCreate ( ppu_thread & ppu , PPHandle handle , PThreadInParam threadInParam , PThreadOutParam threadOutParam )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . warning ( " cellPngDecCreate(handle=**0x%x, threadInParam=*0x%x, threadOutParam=*0x%x) " , handle , threadInParam , threadOutParam ) ;
return pngDecCreate ( ppu , handle , threadInParam , threadOutParam ) ;
2014-09-08 02:54:17 +02:00
}
2016-07-27 23:43:22 +02:00
s32 cellPngDecExtCreate ( ppu_thread & ppu , PPHandle handle , PThreadInParam threadInParam , PThreadOutParam threadOutParam , PExtThreadInParam extThreadInParam , PExtThreadOutParam extThreadOutParam )
2014-09-08 02:54:17 +02:00
{
2017-02-19 12:59:49 +01:00
cellPngDec . warning ( " cellPngDecExtCreate(mainHandle=**0x%x, threadInParam=*0x%x, threadOutParam=*0x%x, extThreadInParam=*0x%x, extThreadOutParam=*0x%x) " , handle , threadInParam , threadOutParam , extThreadInParam , extThreadOutParam ) ;
2016-01-19 20:24:41 +01:00
return pngDecCreate ( ppu , handle , threadInParam , threadOutParam , extThreadInParam , extThreadOutParam ) ;
2014-09-08 02:54:17 +02:00
}
2016-07-27 23:43:22 +02:00
s32 cellPngDecDestroy ( ppu_thread & ppu , PHandle handle )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . warning ( " cellPngDecDestroy(mainHandle=*0x%x) " , handle ) ;
return pngDecDestroy ( ppu , handle ) ;
2014-09-08 02:54:17 +02:00
}
2016-07-27 23:43:22 +02:00
s32 cellPngDecOpen ( ppu_thread & ppu , PHandle handle , PPStream stream , PSrc src , POpenInfo openInfo )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . warning ( " cellPngDecOpen(handle=*0x%x, stream=**0x%x, src=*0x%x, openInfo=*0x%x) " , handle , stream , src , openInfo ) ;
return pngDecOpen ( ppu , handle , stream , src , openInfo ) ;
2014-09-08 02:54:17 +02:00
}
2016-07-27 23:43:22 +02:00
s32 cellPngDecExtOpen ( ppu_thread & ppu , PHandle handle , PPStream stream , PSrc src , POpenInfo openInfo , PCbControlStream cbCtrlStrm , POpenParam opnParam )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . warning ( " cellPngDecExtOpen(handle=*0x%x, stream=**0x%x, src=*0x%x, openInfo=*0x%x, cbCtrlStrm=*0x%x, opnParam=*0x%x) " , handle , stream , src , openInfo , cbCtrlStrm , opnParam ) ;
return pngDecOpen ( ppu , handle , stream , src , openInfo , cbCtrlStrm , opnParam ) ;
2014-09-08 02:54:17 +02:00
}
2016-07-27 23:43:22 +02:00
s32 cellPngDecClose ( ppu_thread & ppu , PHandle handle , PStream stream )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . warning ( " cellPngDecClose(handle=*0x%x, stream=*0x%x) " , handle , stream ) ;
return pngDecClose ( ppu , handle , stream ) ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecReadHeader ( PHandle handle , PStream stream , PInfo info )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . warning ( " cellPngDecReadHeader(handle=*0x%x, stream=*0x%x, info=*0x%x) " , handle , stream , info ) ;
2017-02-19 12:59:49 +01:00
// Read the header info
png_read_info ( stream - > png_ptr , stream - > info_ptr ) ;
pngSetHeader ( stream . get_ptr ( ) ) ;
// Set the pointer to stream info
* info = stream - > info ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecExtReadHeader ( PHandle handle , PStream stream , PInfo info , PExtInfo extInfo )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . warning ( " cellPngDecExtReadHeader(handle=*0x%x, stream=*0x%x, info=*0x%x, extInfo=*0x%x) " , handle , stream , info , extInfo ) ;
2017-02-19 12:59:49 +01:00
// Set the reserved value to 0, if passed to the function. (Should this be arg error if they dont pass?)
if ( extInfo )
{
extInfo - > reserved = 0 ;
}
// lets push what we have so far
u8 * data = static_cast < u8 * > ( stream - > buffer - > data . get_ptr ( ) ) + stream - > buffer - > cursor ;
2020-03-09 17:18:39 +01:00
png_process_data ( stream - > png_ptr , stream - > info_ptr , data , stream - > buffer - > length ) ;
2017-02-19 12:59:49 +01:00
// lets hope we pushed enough for callback
pngSetHeader ( stream . get_ptr ( ) ) ;
// png doesnt allow empty image, so quick check for 0 verifys if we got the header
// not sure exactly what should happen if we dont have header, ask for more data with callback?
2020-02-19 16:26:41 +01:00
if ( stream - > info . imageWidth = = 0u )
2017-02-19 12:59:49 +01:00
{
fmt : : throw_exception ( " Invalid or not enough data sent to get header " ) ;
return CELL_PNGDEC_ERROR_HEADER ;
}
// Set the pointer to stream info
* info = stream - > info ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecSetParameter ( PHandle handle , PStream stream , PInParam inParam , POutParam outParam )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . warning ( " cellPngDecSetParameter(handle=*0x%x, stream=*0x%x, inParam=*0x%x, outParam=*0x%x) " , handle , stream , inParam , outParam ) ;
return pngDecSetParameter ( stream , inParam , outParam ) ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecExtSetParameter ( PHandle handle , PStream stream , PInParam inParam , POutParam outParam , PExtInParam extInParam , PExtOutParam extOutParam )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . warning ( " cellPngDecExtSetParameter(handle=*0x%x, stream=*0x%x, inParam=*0x%x, outParam=*0x%x, extInParam=*0x%x, extOutParam=*0x%x " , handle , stream , inParam , outParam , extInParam , extOutParam ) ;
return pngDecSetParameter ( stream , inParam , outParam , extInParam , extOutParam ) ;
2014-09-08 02:54:17 +02:00
}
2016-07-27 23:43:22 +02:00
s32 cellPngDecDecodeData ( ppu_thread & ppu , PHandle handle , PStream stream , vm : : ptr < u8 > data , PDataControlParam dataCtrlParam , PDataOutInfo dataOutInfo )
2014-09-08 02:54:17 +02:00
{
2016-01-19 20:24:41 +01:00
cellPngDec . warning ( " cellPngDecDecodeData(handle=*0x%x, stream=*0x%x, data=*0x%x, dataCtrlParam=*0x%x, dataOutInfo=*0x%x) " , handle , stream , data , dataCtrlParam , dataOutInfo ) ;
return pngDecodeData ( ppu , handle , stream , data , dataCtrlParam , dataOutInfo ) ;
}
2014-09-08 16:56:47 +02:00
2016-07-27 23:43:22 +02:00
s32 cellPngDecExtDecodeData ( ppu_thread & ppu , PHandle handle , PStream stream , vm : : ptr < u8 > data , PDataControlParam dataCtrlParam , PDataOutInfo dataOutInfo , PCbControlDisp cbCtrlDisp , PDispParam dispParam )
2016-01-19 20:24:41 +01:00
{
cellPngDec . warning ( " cellPngDecExtDecodeData(handle=*0x%x, stream=*0x%x, data=*0x%x, dataCtrlParam=*0x%x, dataOutInfo=*0x%x, cbCtrlDisp=*0x%x, dispParam=*0x%x) " , handle , stream , data , dataCtrlParam , dataOutInfo , cbCtrlDisp , dispParam ) ;
return pngDecodeData ( ppu , handle , stream , data , dataCtrlParam , dataOutInfo , cbCtrlDisp , dispParam ) ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetUnknownChunks ( PHandle handle , PStream stream , vm : : pptr < CellPngUnknownChunk > unknownChunk , vm : : ptr < u32 > unknownChunkNumber )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetUnknownChunks() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetpCAL ( PHandle handle , PStream stream , vm : : ptr < CellPngPCAL > pcal )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetpCAL() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetcHRM ( PHandle handle , PStream stream , vm : : ptr < CellPngCHRM > chrm )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetcHRM() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetsCAL ( PHandle handle , PStream stream , vm : : ptr < CellPngSCAL > scal )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetsCAL() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetpHYs ( PHandle handle , PStream stream , vm : : ptr < CellPngPHYS > phys )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetpHYs() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetoFFs ( PHandle handle , PStream stream , vm : : ptr < CellPngOFFS > offs )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetoFFs() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetsPLT ( PHandle handle , PStream stream , vm : : ptr < CellPngSPLT > splt )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetsPLT() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetbKGD ( PHandle handle , PStream stream , vm : : ptr < CellPngBKGD > bkgd )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetbKGD() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGettIME ( PHandle handle , PStream stream , vm : : ptr < CellPngTIME > time )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGettIME() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGethIST ( PHandle handle , PStream stream , vm : : ptr < CellPngHIST > hist )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGethIST() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGettRNS ( PHandle handle , PStream stream , vm : : ptr < CellPngTRNS > trns )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGettRNS() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetsBIT ( PHandle handle , PStream stream , vm : : ptr < CellPngSBIT > sbit )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetsBIT() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetiCCP ( PHandle handle , PStream stream , vm : : ptr < CellPngICCP > iccp )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetiCCP() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetsRGB ( PHandle handle , PStream stream , vm : : ptr < CellPngSRGB > srgb )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetsRGB() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetgAMA ( PHandle handle , PStream stream , vm : : ptr < CellPngGAMA > gama )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetgAMA() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetPLTE ( PHandle handle , PStream stream , vm : : ptr < CellPngPLTE > plte )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetPLTE() " ) ;
return CELL_OK ;
2014-09-08 02:54:17 +02:00
}
2016-01-19 20:24:41 +01:00
s32 cellPngDecGetTextChunk ( PHandle handle , PStream stream , vm : : ptr < u32 > textInfoNum , vm : : pptr < CellPngTextInfo > textInfo )
2014-09-08 02:54:17 +02:00
{
2019-09-02 13:41:57 +02:00
cellPngDec . todo ( " cellPngDecGetTextChunk() " ) ;
return CELL_OK ;
2014-06-28 03:19:44 +02:00
}
2016-03-21 20:43:03 +01:00
DECLARE ( ppu_module_manager : : cellPngDec ) ( " cellPngDec " , [ ] ( )
2013-09-08 10:45:10 +02:00
{
2014-09-08 02:54:17 +02:00
REG_FUNC ( cellPngDec , cellPngDecGetUnknownChunks ) ;
REG_FUNC ( cellPngDec , cellPngDecClose ) ;
REG_FUNC ( cellPngDec , cellPngDecGetpCAL ) ;
REG_FUNC ( cellPngDec , cellPngDecGetcHRM ) ;
REG_FUNC ( cellPngDec , cellPngDecGetsCAL ) ;
REG_FUNC ( cellPngDec , cellPngDecGetpHYs ) ;
REG_FUNC ( cellPngDec , cellPngDecGetoFFs ) ;
REG_FUNC ( cellPngDec , cellPngDecGetsPLT ) ;
REG_FUNC ( cellPngDec , cellPngDecGetbKGD ) ;
REG_FUNC ( cellPngDec , cellPngDecGettIME ) ;
REG_FUNC ( cellPngDec , cellPngDecGethIST ) ;
REG_FUNC ( cellPngDec , cellPngDecGettRNS ) ;
REG_FUNC ( cellPngDec , cellPngDecGetsBIT ) ;
REG_FUNC ( cellPngDec , cellPngDecGetiCCP ) ;
REG_FUNC ( cellPngDec , cellPngDecGetsRGB ) ;
REG_FUNC ( cellPngDec , cellPngDecGetgAMA ) ;
REG_FUNC ( cellPngDec , cellPngDecGetPLTE ) ;
REG_FUNC ( cellPngDec , cellPngDecGetTextChunk ) ;
REG_FUNC ( cellPngDec , cellPngDecDestroy ) ;
REG_FUNC ( cellPngDec , cellPngDecCreate ) ;
REG_FUNC ( cellPngDec , cellPngDecExtCreate ) ;
REG_FUNC ( cellPngDec , cellPngDecExtSetParameter ) ;
REG_FUNC ( cellPngDec , cellPngDecSetParameter ) ;
REG_FUNC ( cellPngDec , cellPngDecExtReadHeader ) ;
REG_FUNC ( cellPngDec , cellPngDecReadHeader ) ;
REG_FUNC ( cellPngDec , cellPngDecExtOpen ) ;
REG_FUNC ( cellPngDec , cellPngDecOpen ) ;
REG_FUNC ( cellPngDec , cellPngDecExtDecodeData ) ;
REG_FUNC ( cellPngDec , cellPngDecDecodeData ) ;
2015-02-18 17:22:06 +01:00
} ) ;