From e1d3b69a78a152e90a103d582395b7e4fd5aef68 Mon Sep 17 00:00:00 2001 From: CPkmn Date: Thu, 4 Jul 2013 02:55:06 -0700 Subject: [PATCH 1/6] Update sceJpeg.cpp --- Core/HLE/sceJpeg.cpp | 117 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 12 deletions(-) diff --git a/Core/HLE/sceJpeg.cpp b/Core/HLE/sceJpeg.cpp index 726ca7b36d..d0dfeb2bbb 100644 --- a/Core/HLE/sceJpeg.cpp +++ b/Core/HLE/sceJpeg.cpp @@ -17,7 +17,16 @@ #include "Core/HLE/HLE.h" #include "Core/Reporting.h" +#include "Common.h" +#include "native\ext\cityhash\city.h" +// http://keyj.emphy.de/nanojpeg/ +#include "native\ext\njpeg\nanojpeg.h" + +int jpegWidth, jpegHeight; + +//Uncomment if you want to dump JPEGs loaded through sceJpeg to a file +//#define JPEG_DEBUG int sceJpegDecompressAllImage() { @@ -64,19 +73,90 @@ int sceJpegCsc() int sceJpegFinishMJpeg() { ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegFinishMJpeg"); + + njDone(); + return 0; } -int sceJpegGetOutputInfo() +int getYCbCrBufferSize() { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegGetOutputInfo"); - return 0; + int w = njGetWidth(); + int h = njGetHeight(); + // Return necessary buffer size for conversion: 12 bits per pixel + return ((w * h) >> 1) * 3; } -int sceJpegDecodeMJpegYCbCr() +int sceJpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr, int dhtMode) { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDecodeMJpegYCbCr"); - return 0; + ERROR_LOG_REPORT(HLE, "sceJpegGetOutputInfo(%i, %i, %i, %i)", jpegAddr, jpegSize, colourInfoAddr, dhtMode); + + // 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)) + Memory::Write_U32(0x00020202, colourInfoAddr); + + if (!Memory::IsValidAddress(jpegAddr)) + { + ERROR_LOG(HLE, "sceJpegGetOutputInfo: Bad JPEG address 0x%08x", jpegAddr); + return 0xC000; + } + else // Memory address is good + { + // But data may not be...so check it + u8 *buf = Memory::GetPointer(jpegAddr); + int result = njDecode(buf, jpegSize); + if (result != 0) // (0 = success) + { + ERROR_LOG(HLE, "sceJpegGetOutputInfo: Bad JPEG data"); + return 0xC000; + } + } + +#ifdef JPEG_DEBUG + char jpeg_fname[256]; + u8 *jpegBuf = Memory::GetPointer(jpegAddr); + uint32 jpeg_cityhash = CityHash32((const char *)jpegBuf, jpegSize); + sprintf(jpeg_fname, "Jpeg\\%X.jpg", jpeg_cityhash); + FILE *wfp = fopen(jpeg_fname, "wb"); + fwrite(jpegBuf, 1, jpegSize, wfp); + fclose(wfp); +#endif //JPEG_DEBUG + + return getYCbCrBufferSize(); +} + +int getWidthHeight(int width, int height) +{ + return (width << 16) | height; +} + +int sceJpegDecodeMJpegYCbCr(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCrSize, int dhtMode) +{ + ERROR_LOG_REPORT(HLE, "sceJpegDecodeMJpegYCbCr(%i, %i, %i, %i, %i)", jpegAddr, jpegSize, yCbCrAddr, yCbCrSize, dhtMode); + + if (!Memory::IsValidAddress(jpegAddr)) + { + return getWidthHeight(0, 0); + } + + u8 *jpegBuf = Memory::GetPointer(jpegAddr); + int result = njDecode(jpegBuf, jpegSize); + + if (result != 0) // (0 = success) + { + return getWidthHeight(0, 0); + } + + int width = njGetWidth(); + int height = njGetHeight(); + + // TODO: There's more... + + return getWidthHeight(width, height); } int sceJpeg_9B36444C() @@ -85,15 +165,28 @@ int sceJpeg_9B36444C() return 0; } -int sceJpegCreateMJpeg() +int sceJpegCreateMJpeg(int width, int height) { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegCreateMJpeg"); + ERROR_LOG_REPORT(HLE, "sceJpegCreateMJpeg(%i, %i)", width, height); + + jpegWidth = width; + jpegHeight = height; + return 0; } int sceJpegInitMJpeg() { ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegInitMJpeg"); + + njInit(); + + return 0; +} + +int sceJpeg_A06A75C4() +{ + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpeg_A06A75C4"); return 0; } @@ -108,12 +201,12 @@ const HLEFunction sceJpeg[] = {0x64B6F978, WrapI_V, "sceJpegDecodeMJpegSuccessively"}, {0x67F0ED84, WrapI_V, "sceJpegCsc"}, {0x7D2F3D7F, WrapI_V, "sceJpegFinishMJpeg"}, - {0x8F2BB012, WrapI_V, "sceJpegGetOutputInfo"}, - {0x91EED83C, WrapI_V, "sceJpegDecodeMJpegYCbCr"}, + {0x8F2BB012, WrapI_UIUI, "sceJpegGetOutputInfo"}, + {0x91EED83C, WrapI_UIUII, "sceJpegDecodeMJpegYCbCr"}, {0x9B36444C, WrapI_V, "sceJpeg_9B36444C"}, - {0x9D47469C, WrapI_V, "sceJpegCreateMJpeg"}, + {0x9D47469C, WrapI_II, "sceJpegCreateMJpeg"}, {0xAC9E70E6, WrapI_V, "sceJpegInitMJpeg"}, - {0xa06a75c4, 0, "sceJpeg_A06A75C4"}, + {0xa06a75c4, WrapI_V, "sceJpeg_A06A75C4"}, }; void Register_sceJpeg() From a0379d5ac87f3993d90d7540c06b14dbb469a079 Mon Sep 17 00:00:00 2001 From: CPkmn Date: Thu, 4 Jul 2013 03:00:22 -0700 Subject: [PATCH 2/6] Update FunctionWrappers.h --- Core/HLE/FunctionWrappers.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index d7c72d1a1f..1546c228da 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -256,11 +256,21 @@ template void WrapU_UIUII() { RETURN(retval); } +template void WrapI_UIUII() { + int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); + RETURN(retval); +} + template void WrapU_UIUI() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); RETURN(retval); } +template void WrapI_UIUI() { + u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); + RETURN(retval); +} + template void WrapU_UIU() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); RETURN(retval); From ba7860927e4e96a0637934e05b2e0efc3cd9a0b2 Mon Sep 17 00:00:00 2001 From: CPkmn Date: Thu, 4 Jul 2013 12:56:20 -0700 Subject: [PATCH 3/6] *nix include fix --- Core/HLE/sceJpeg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceJpeg.cpp b/Core/HLE/sceJpeg.cpp index d0dfeb2bbb..55726d5605 100644 --- a/Core/HLE/sceJpeg.cpp +++ b/Core/HLE/sceJpeg.cpp @@ -18,7 +18,7 @@ #include "Core/HLE/HLE.h" #include "Core/Reporting.h" #include "Common.h" -#include "native\ext\cityhash\city.h" +#include "native/ext/cityhash/city.h" // http://keyj.emphy.de/nanojpeg/ #include "native\ext\njpeg\nanojpeg.h" From 7ae259627d64fdd012f8b30f50bfa4ec353bdfcf Mon Sep 17 00:00:00 2001 From: CPkmn Date: Thu, 4 Jul 2013 14:51:32 -0700 Subject: [PATCH 4/6] Remove NanoJpeg, and add arguments for known functions --- Core/HLE/sceJpeg.cpp | 86 ++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/Core/HLE/sceJpeg.cpp b/Core/HLE/sceJpeg.cpp index 55726d5605..30b8a72622 100644 --- a/Core/HLE/sceJpeg.cpp +++ b/Core/HLE/sceJpeg.cpp @@ -19,9 +19,7 @@ #include "Core/Reporting.h" #include "Common.h" #include "native/ext/cityhash/city.h" - -// http://keyj.emphy.de/nanojpeg/ -#include "native\ext\njpeg\nanojpeg.h" +#include "native/ext/jpgd/jpgd.h" int jpegWidth, jpegHeight; @@ -30,59 +28,54 @@ int jpegWidth, jpegHeight; int sceJpegDecompressAllImage() { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDecompressAllImage"); + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDecompressAllImage()"); return 0; } -int sceJpegMJpegCsc() +int sceJpegMJpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth) { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegMJpegCsc"); + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegMJpegCsc(%i, %i, %i, %i)", imageAddr, yCbCrAddr, widthHeight, bufferWidth); return 0; } -int sceJpegDecodeMJpeg() +int sceJpegDecodeMJpeg(u32 jpegAddr, int jpegSize, u32 imageAddr, int dhtMode) { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDecodeMJpeg"); + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDecodeMJpeg(%i, %i, %i, %i)", jpegAddr, jpegSize, imageAddr, dhtMode); return 0; } -int sceJpegDecodeMJpegYCbCrSuccessively() +int sceJpegDecodeMJpegYCbCrSuccessively(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCrSize, int dhtMode) { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDecodeMJpegYCbCrSuccessively"); + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDecodeMJpegYCbCrSuccessively(%i, %i, %i, %i, %i)", jpegAddr, jpegSize, yCbCrAddr, yCbCrSize, dhtMode); return 0; } int sceJpegDeleteMJpeg() { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDeleteMJpeg"); + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDeleteMJpeg()"); return 0; } -int sceJpegDecodeMJpegSuccessively() +int sceJpegDecodeMJpegSuccessively(u32 jpegAddr, int jpegSize, u32 imageAddr, int dhtMode) { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDecodeMJpegSuccessively"); + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegDecodeMJpegSuccessively(%i, %i, %i, %i)", jpegAddr, jpegSize, imageAddr, dhtMode); return 0; } -int sceJpegCsc() +int sceJpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth, int colourInfo) { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegCsc"); + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegCsc(%i, %i, %i, %i, %i)", imageAddr, yCbCrAddr, widthHeight, bufferWidth, colourInfo); return 0; } int sceJpegFinishMJpeg() { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegFinishMJpeg"); - - njDone(); - + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegFinishMJpeg()"); return 0; } -int getYCbCrBufferSize() +int getYCbCrBufferSize(int w, int h) { - int w = njGetWidth(); - int h = njGetHeight(); // Return necessary buffer size for conversion: 12 bits per pixel return ((w * h) >> 1) * 3; } @@ -99,6 +92,8 @@ int sceJpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr, int dht if (Memory::IsValidAddress(colourInfoAddr)) Memory::Write_U32(0x00020202, colourInfoAddr); + int w = 0, h = 0, actual_components = 0; + if (!Memory::IsValidAddress(jpegAddr)) { ERROR_LOG(HLE, "sceJpegGetOutputInfo: Bad JPEG address 0x%08x", jpegAddr); @@ -108,8 +103,14 @@ int sceJpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr, int dht { // But data may not be...so check it u8 *buf = Memory::GetPointer(jpegAddr); - int result = njDecode(buf, jpegSize); - if (result != 0) // (0 = success) + unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &w, &h, &actual_components, 3); + if (actual_components != 3) + { + // The assumption that the + int components = actual_components; + jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &w, &h, &actual_components, components); + } + if (jpegBuf == NULL) { ERROR_LOG(HLE, "sceJpegGetOutputInfo: Bad JPEG data"); return 0xC000; @@ -126,7 +127,7 @@ int sceJpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr, int dht fclose(wfp); #endif //JPEG_DEBUG - return getYCbCrBufferSize(); + return getYCbCrBufferSize(w, h); } int getWidthHeight(int width, int height) @@ -143,16 +144,16 @@ int sceJpegDecodeMJpegYCbCr(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCr return getWidthHeight(0, 0); } - u8 *jpegBuf = Memory::GetPointer(jpegAddr); - int result = njDecode(jpegBuf, jpegSize); - - if (result != 0) // (0 = success) + 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) { - return getWidthHeight(0, 0); + int components = actual_components; + jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &width, &height, &actual_components, components); } - - int width = njGetWidth(); - int height = njGetHeight(); + if (jpegBuf == NULL) + return getWidthHeight(0, 0); // TODO: There's more... @@ -161,7 +162,7 @@ int sceJpegDecodeMJpegYCbCr(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCr int sceJpeg_9B36444C() { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpeg_9B36444C"); + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpeg_9B36444C()"); return 0; } @@ -177,16 +178,13 @@ int sceJpegCreateMJpeg(int width, int height) int sceJpegInitMJpeg() { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegInitMJpeg"); - - njInit(); - + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpegInitMJpeg()"); return 0; } int sceJpeg_A06A75C4() { - ERROR_LOG_REPORT(HLE, "UNIMPL sceJpeg_A06A75C4"); + ERROR_LOG_REPORT(HLE, "UNIMPL sceJpeg_A06A75C4()"); return 0; } @@ -194,12 +192,12 @@ int sceJpeg_A06A75C4() const HLEFunction sceJpeg[] = { {0x0425B986, WrapI_V, "sceJpegDecompressAllImage"}, - {0x04B5AE02, WrapI_V, "sceJpegMJpegCsc"}, - {0x04B93CEF, WrapI_V, "sceJpegDecodeMJpeg"}, - {0x227662D7, WrapI_V, "sceJpegDecodeMJpegYCbCrSuccessively"}, + {0x04B5AE02, WrapI_UUII, "sceJpegMJpegCsc"}, + {0x04B93CEF, WrapI_UIUI, "sceJpegDecodeMJpeg"}, + {0x227662D7, WrapI_UIUII, "sceJpegDecodeMJpegYCbCrSuccessively"}, {0x48B602B7, WrapI_V, "sceJpegDeleteMJpeg"}, - {0x64B6F978, WrapI_V, "sceJpegDecodeMJpegSuccessively"}, - {0x67F0ED84, WrapI_V, "sceJpegCsc"}, + {0x64B6F978, WrapI_UIUI, "sceJpegDecodeMJpegSuccessively"}, + {0x67F0ED84, WrapI_UUIII, "sceJpegCsc"}, {0x7D2F3D7F, WrapI_V, "sceJpegFinishMJpeg"}, {0x8F2BB012, WrapI_UIUI, "sceJpegGetOutputInfo"}, {0x91EED83C, WrapI_UIUII, "sceJpegDecodeMJpegYCbCr"}, From 17493f3c4e7372b81abd30a05f0a4e48736d4774 Mon Sep 17 00:00:00 2001 From: CPkmn Date: Thu, 4 Jul 2013 14:51:51 -0700 Subject: [PATCH 5/6] Update FunctionWrappers.h --- Core/HLE/FunctionWrappers.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 1546c228da..f964aeac57 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -296,6 +296,16 @@ template void WrapI_UIIUU() { RETURN(retval); } +template void WrapI_UUII() { + int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); + RETURN(retval); +} + +template void WrapI_UUIII() { + int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); + RETURN(retval); +} + template void WrapV_UIII() { func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); } From b901e403618b3b9a9e324e27748a927937f8c7b7 Mon Sep 17 00:00:00 2001 From: CPkmn Date: Thu, 4 Jul 2013 14:58:19 -0700 Subject: [PATCH 6/6] Oops, comment about RGB was cut off early --- Core/HLE/sceJpeg.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceJpeg.cpp b/Core/HLE/sceJpeg.cpp index 30b8a72622..bf267553d7 100644 --- a/Core/HLE/sceJpeg.cpp +++ b/Core/HLE/sceJpeg.cpp @@ -106,7 +106,8 @@ int sceJpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr, int dht unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &w, &h, &actual_components, 3); if (actual_components != 3) { - // The assumption that the + // 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); } @@ -149,6 +150,8 @@ int sceJpegDecodeMJpegYCbCr(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCr unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &width, &height, &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); }