diff --git a/Core/HLE/sceJpeg.cpp b/Core/HLE/sceJpeg.cpp index fdb7c500ea..616772c74e 100644 --- a/Core/HLE/sceJpeg.cpp +++ b/Core/HLE/sceJpeg.cpp @@ -21,6 +21,7 @@ #include "Common/ChunkFile.h" #include "Core/HLE/HLE.h" #include "Core/Reporting.h" +#include "sceMpeg.h" //Uncomment if you want to dump JPEGs loaded through sceJpeg to a file //#define JPEG_DEBUG @@ -62,12 +63,6 @@ u32 convertYCbCrToABGR (int y, int cb, int cr) { return 0xFF000000 | (b << 16) | (g << 8) | (r << 0); } -int sceJpegDecompressAllImage() -{ - ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDecompressAllImage()"); - return 0; -} - void __JpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth) { int height = widthHeight & 0xFFF; int width = (widthHeight >> 16) & 0xFFF; @@ -109,19 +104,14 @@ void __JpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth) { int sceJpegMJpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth) { __JpegCsc(imageAddr, yCbCrAddr, widthHeight, bufferWidth); - DEBUG_LOG(ME, "UNIMPL sceJpegMJpegCsc(%i, %i, %i, %i)", imageAddr, yCbCrAddr, widthHeight, bufferWidth); + + DEBUG_LOG(ME, "sceJpegMJpegCsc(%i, %i, %i, %i)", imageAddr, yCbCrAddr, widthHeight, bufferWidth); return 0; } int sceJpegDecodeMJpeg(u32 jpegAddr, int jpegSize, u32 imageAddr, int dhtMode) { - ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDecodeMJpeg(%i, %i, %i, %i)", jpegAddr, jpegSize, imageAddr, dhtMode); - return 0; -} - -int sceJpegDecodeMJpegYCbCrSuccessively(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCrSize, int dhtMode) -{ - ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDecodeMJpegYCbCrSuccessively(%i, %i, %i, %i, %i)", jpegAddr, jpegSize, yCbCrAddr, yCbCrSize, dhtMode); + DEBUG_LOG(ME, "UNIMPL sceJpegDecodeMJpeg(%i, %i, %i, %i)", jpegAddr, jpegSize, imageAddr, dhtMode); return 0; } @@ -133,7 +123,7 @@ int sceJpegDeleteMJpeg() int sceJpegDecodeMJpegSuccessively(u32 jpegAddr, int jpegSize, u32 imageAddr, int dhtMode) { - ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDecodeMJpegSuccessively(%i, %i, %i, %i)", jpegAddr, jpegSize, imageAddr, dhtMode); + DEBUG_LOG(ME, "UNIMPL sceJpegDecodeMJpegSuccessively(%i, %i, %i, %i)", jpegAddr, jpegSize, imageAddr, dhtMode); return 0; } @@ -141,9 +131,11 @@ int sceJpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth, i { if (bufferWidth < 0 || widthHeight < 0){ WARN_LOG(ME, "sceJpegCsc(%i, %i, %i, %i, %i)", imageAddr, yCbCrAddr, widthHeight, bufferWidth, colourInfo); - return 0x80650051; + return ERROR_JPEG_INVALID_VALUE; } + __JpegCsc(imageAddr, yCbCrAddr, widthHeight, bufferWidth); + DEBUG_LOG(ME, "sceJpegCsc(%i, %i, %i, %i, %i)", imageAddr, yCbCrAddr, widthHeight, bufferWidth, colourInfo); return 0; } @@ -154,49 +146,36 @@ int sceJpegFinishMJpeg() return 0; } -int getYCbCrBufferSize(int w, int h) -{ +int getYCbCrBufferSize(int w, int h) { // Return necessary buffer size for conversion: 12 bits per pixel return ((w * h) >> 1) * 3; } -int sceJpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr, int dhtMode) -{ - ERROR_LOG_REPORT(ME, "sceJpegGetOutputInfo(%i, %i, %i, %i)", jpegAddr, jpegSize, colourInfoAddr, dhtMode); +int __JpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr) { + u8 *buf = Memory::GetPointer(jpegAddr); + int width, height, actual_components; + unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &width, &height, &actual_components, 3); - int w = 0, h = 0, actual_components = 0; + if (actual_components != 3) { + // The assumption that the image was RGB was wrong... + // Try again. + int components = actual_components; + jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &width, &height, &actual_components, components); + } - if (!Memory::IsValidAddress(jpegAddr)) - { - ERROR_LOG(ME, "sceJpegGetOutputInfo: Bad JPEG address 0x%08x", jpegAddr); + if (jpegBuf == NULL) { + ERROR_LOG(ME, "sceJpegGetOutputInfo: Bad JPEG data"); return getYCbCrBufferSize(0, 0); } - else // Memory address is good - { - // But data may not be...so check it - u8 *buf = Memory::GetPointer(jpegAddr); - unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &w, &h, &actual_components, 3); - if (actual_components != 3) - { - // The assumption that the image was RGB was wrong... - // Try again. - int components = actual_components; - jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &w, &h, &actual_components, components); - } - if (jpegBuf == NULL) - { - ERROR_LOG(ME, "sceJpegGetOutputInfo: Bad JPEG data"); - return getYCbCrBufferSize(0, 0); - } - } - + // Buffer to store info about the color space in use. // - Bits 24 to 32 (Always empty): 0x00 // - Bits 16 to 24 (Color mode): 0x00 (Unknown), 0x01 (Greyscale) or 0x02 (YCbCr) // - Bits 8 to 16 (Vertical chroma subsampling value): 0x00, 0x01 or 0x02 // - Bits 0 to 8 (Horizontal chroma subsampling value): 0x00, 0x01 or 0x02 - if (Memory::IsValidAddress(colourInfoAddr)) + if (Memory::IsValidAddress(colourInfoAddr)) { Memory::Write_U32(0x00020202, colourInfoAddr); + } #ifdef JPEG_DEBUG char jpeg_fname[256]; @@ -212,11 +191,20 @@ int sceJpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr, int dht fclose(wfp); #endif //JPEG_DEBUG - return getYCbCrBufferSize(w, h); + return getYCbCrBufferSize(width, height); +} +int sceJpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr, int dhtMode) +{ + if (!Memory::IsValidAddress(jpegAddr)) { + ERROR_LOG(ME, "sceJpegGetOutputInfo: Bad JPEG address 0x%08x", jpegAddr); + return getYCbCrBufferSize(0, 0); + } + + DEBUG_LOG(ME, "sceJpegGetOutputInfo(%i, %i, %i, %i)", jpegAddr, jpegSize, colourInfoAddr, dhtMode); + return __JpegGetOutputInfo(jpegAddr, jpegSize, colourInfoAddr); } -int getWidthHeight(int width, int height) -{ +int getWidthHeight(int width, int height) { return (width << 16) | height; } @@ -271,47 +259,66 @@ int __JpegConvertRGBToYCbCr (const void *data, u32 bufferOutputAddr, int width, return (width << 16) | height; } -int sceJpegDecodeMJpegYCbCr(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCrSize, int dhtMode) -{ - WARN_LOG_REPORT(ME, "sceJpegDecodeMJpegYCbCr(%i, %i, %i, %i, %i)", jpegAddr, jpegSize, yCbCrAddr, yCbCrSize, dhtMode); - - if (!Memory::IsValidAddress(jpegAddr)) - { - return getWidthHeight(0, 0); - } - +int __JpegDecodeMJpegYCbCr(u32 jpegAddr, int jpegSize, u32 yCbCrAddr) { u8 *buf = Memory::GetPointer(jpegAddr); int width, height, actual_components; unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &width, &height, &actual_components, 3); - if (actual_components != 3) - { + + if (actual_components != 3) { // The assumption that the image was RGB was wrong... // Try again. int components = actual_components; jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &width, &height, &actual_components, components); } - if (jpegBuf == NULL) + + if (jpegBuf == NULL) { return getWidthHeight(0, 0); - if (actual_components == 3) + } + + if (actual_components == 3) { __JpegConvertRGBToYCbCr(jpegBuf, yCbCrAddr, width, height); + } + // TODO: There's more... return getWidthHeight(width, height); } +int sceJpegDecodeMJpegYCbCr(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCrSize, int dhtMode) +{ + if (!Memory::IsValidAddress(jpegAddr)) { + ERROR_LOG(ME, "sceJpegDecodeMJpegYCbCr: Bad JPEG address 0x%08x", jpegAddr); + return getWidthHeight(0, 0); + } + + DEBUG_LOG(ME, "sceJpegDecodeMJpegYCbCr(%i, %i, %i, %i, %i)", jpegAddr, jpegSize, yCbCrAddr, yCbCrSize, dhtMode); + return __JpegDecodeMJpegYCbCr(jpegAddr, jpegSize, yCbCrAddr); +} + +int sceJpegDecodeMJpegYCbCrSuccessively(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCrSize, int dhtMode) +{ + if (!Memory::IsValidAddress(jpegAddr)) { + ERROR_LOG(ME, "sceJpegDecodeMJpegYCbCrSuccessively: Bad JPEG address 0x%08x", jpegAddr); + return getWidthHeight(0, 0); + } + + DEBUG_LOG(ME, "sceJpegDecodeMJpegYCbCrSuccessively(%i, %i, %i, %i, %i)", jpegAddr, jpegSize, yCbCrAddr, yCbCrSize, dhtMode); + // Do as same way as sceJpegDecodeMJpegYCbCr() but with smaller block size + return __JpegDecodeMJpegYCbCr(jpegAddr, jpegSize, yCbCrAddr); +} + int sceJpeg_9B36444C() { - ERROR_LOG_REPORT(ME, "UNIMPL sceJpeg_9B36444C()"); + DEBUG_LOG(ME, "UNIMPL sceJpeg_9B36444C()"); return 0; } int sceJpegCreateMJpeg(int width, int height) { - DEBUG_LOG(ME, "sceJpegCreateMJpeg(%i, %i)", width, height); - mjpegWidth = width; mjpegHeight = height; + DEBUG_LOG(ME, "sceJpegCreateMJpeg(%i, %i)", width, height); return 0; } @@ -323,10 +330,15 @@ int sceJpegInitMJpeg() int sceJpegMJpegCscWithColorOption() { - ERROR_LOG_REPORT(ME, "UNIMPL sceJpegMJpegCscWithColorOption()"); + DEBUG_LOG(ME, "UNIMPL sceJpegMJpegCscWithColorOption()"); return 0; } +int sceJpegDecompressAllImage() +{ + DEBUG_LOG(ME, "UNIMPL sceJpegDecompressAllImage()"); + return 0; +} const HLEFunction sceJpeg[] = { diff --git a/Core/HLE/sceMpeg.h b/Core/HLE/sceMpeg.h index b20d3b712a..4c3f0fb0e0 100644 --- a/Core/HLE/sceMpeg.h +++ b/Core/HLE/sceMpeg.h @@ -45,6 +45,8 @@ enum { ERROR_MPEG_AVC_INVALID_VALUE = 0x806201fe, ERROR_MPEG_AVC_DECODE_FATAL = 0x80628002, + + ERROR_JPEG_INVALID_VALUE = 0x80650051, }; // MPEG statics.