diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index 2b2cab2bf..b3bbad782 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -37,6 +37,29 @@ typedef uint32_t color_t; struct blip_t; +enum mColorFormat { + mCOLOR_XBGR8 = 0x00001, + mCOLOR_XRGB8 = 0x00002, + mCOLOR_BGRX8 = 0x00004, + mCOLOR_RGBX8 = 0x00008, + mCOLOR_ABGR8 = 0x00010, + mCOLOR_ARGB8 = 0x00020, + mCOLOR_BGRA8 = 0x00040, + mCOLOR_RGBA8 = 0x00080, + mCOLOR_RGB5 = 0x00100, + mCOLOR_BGR5 = 0x00200, + mCOLOR_RGB565 = 0x00400, + mCOLOR_BGR565 = 0x00800, + mCOLOR_ARGB5 = 0x01000, + mCOLOR_ABGR5 = 0x02000, + mCOLOR_RGBA5 = 0x04000, + mCOLOR_BGRA5 = 0x08000, + mCOLOR_RGB8 = 0x10000, + mCOLOR_BGR8 = 0x20000, + + mCOLOR_ANY = -1 +}; + struct mCoreCallbacks { void* context; void (*videoFrameStarted)(void* context); @@ -84,9 +107,9 @@ struct mRTCSource { }; struct mImageSource { - void (*startRequestImage)(struct mImageSource*, unsigned w, unsigned h); + void (*startRequestImage)(struct mImageSource*, unsigned w, unsigned h, int colorFormats); void (*stopRequestImage)(struct mImageSource*); - void (*requestImage)(struct mImageSource*, const uint32_t** buffer, size_t* stride); + void (*requestImage)(struct mImageSource*, const void** buffer, size_t* stride, enum mColorFormat* colorFormat); }; enum mRTCGenericType { diff --git a/src/gb/mbc.c b/src/gb/mbc.c index 366a25b26..341478764 100644 --- a/src/gb/mbc.c +++ b/src/gb/mbc.c @@ -244,7 +244,7 @@ void GBMBCInit(struct GB* gb) { gb->memory.mbcWrite = _GBPocketCam; gb->memory.mbcRead = _GBPocketCamRead; if (gb->memory.cam && gb->memory.cam->startRequestImage) { - gb->memory.cam->startRequestImage(gb->memory.cam, GBCAM_WIDTH, GBCAM_HEIGHT); + gb->memory.cam->startRequestImage(gb->memory.cam, GBCAM_WIDTH, GBCAM_HEIGHT, mCOLOR_ANY); } break; } @@ -791,9 +791,10 @@ void _GBPocketCamCapture(struct GBMemory* memory) { if (!memory->cam) { return; } - const uint32_t* image = NULL; + const void* image = NULL; size_t stride; - memory->cam->requestImage(memory->cam, &image, &stride); + enum mColorFormat format; + memory->cam->requestImage(memory->cam, &image, &stride, &format); if (!image) { return; } @@ -802,8 +803,44 @@ void _GBPocketCamCapture(struct GBMemory* memory) { size_t x, y; for (y = 0; y < GBCAM_HEIGHT; ++y) { for (x = 0; x < GBCAM_WIDTH; ++x) { - uint32_t color = image[y * stride + x]; - uint32_t gray = ((color & 0xFF) + ((color >> 8) & 0xFF) + ((color >> 16) & 0xFF)); + uint32_t gray; + uint32_t color; + switch (format) { + case mCOLOR_XBGR8: + case mCOLOR_XRGB8: + case mCOLOR_ARGB8: + case mCOLOR_ABGR8: + color = ((const uint32_t*) image)[y * stride + x]; + gray = (color & 0xFF) + ((color >> 8) & 0xFF) + ((color >> 16) & 0xFF); + break; + case mCOLOR_BGRX8: + case mCOLOR_RGBX8: + case mCOLOR_RGBA8: + case mCOLOR_BGRA8: + color = ((const uint32_t*) image)[y * stride + x]; + gray = ((color >> 8) & 0xFF) + ((color >> 16) & 0xFF) + ((color >> 24) & 0xFF); + break; + case mCOLOR_BGR5: + case mCOLOR_RGB5: + case mCOLOR_ARGB5: + case mCOLOR_ABGR5: + color = ((const uint16_t*) image)[y * stride + x]; + gray = ((color << 3) & 0xF8) + ((color >> 2) & 0xF8) + ((color >> 7) & 0xF8); + break; + case mCOLOR_BGR565: + case mCOLOR_RGB565: + color = ((const uint16_t*) image)[y * stride + x]; + gray = ((color << 3) & 0xF8) + ((color >> 3) & 0xFC) + ((color >> 8) & 0xF8); + break; + case mCOLOR_BGRA5: + case mCOLOR_RGBA5: + color = ((const uint16_t*) image)[y * stride + x]; + gray = ((color << 2) & 0xF8) + ((color >> 3) & 0xF8) + ((color >> 8) & 0xF8); + break; + default: + mLOG(GB_MBC, WARN, "Unsupported pixel format: %X", format); + return; + } uint16_t exposure = (pocketCam->registers[2] << 8) | (pocketCam->registers[3]); gray = (gray + 1) * exposure / 0x300; // TODO: Additional processing diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index 5e014adaa..9dbbb3aff 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -88,7 +88,7 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren #endif m_image.p = this; - m_image.startRequestImage = [](mImageSource* context, unsigned w, unsigned h) { + m_image.startRequestImage = [](mImageSource* context, unsigned w, unsigned h, int) { InputControllerImage* image = static_cast(context); image->w = w; image->h = h; @@ -109,19 +109,19 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren #endif }; - m_image.requestImage = [](mImageSource* context, const uint32_t** buffer, size_t* stride) { + m_image.requestImage = [](mImageSource* context, const void** buffer, size_t* stride, mColorFormat* format) { InputControllerImage* image = static_cast(context); QSize size; { QMutexLocker locker(&image->mutex); if (image->outOfDate) { image->resizedImage = image->image.scaled(image->w, image->h, Qt::KeepAspectRatioByExpanding); - image->resizedImage = image->resizedImage.convertToFormat(QImage::Format_RGB32); + image->resizedImage = image->resizedImage.convertToFormat(QImage::Format_RGB16); image->outOfDate = false; } } size = image->resizedImage.size(); - const uint32_t* bits = reinterpret_cast(image->resizedImage.constBits()); + const uint16_t* bits = reinterpret_cast(image->resizedImage.constBits()); if (size.width() > image->w) { bits += (size.width() - image->w) / 2; } @@ -129,7 +129,8 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren bits += ((size.height() - image->h) / 2) * size.width(); } *buffer = bits; - *stride = size.width(); + *stride = image->resizedImage.bytesPerLine() / sizeof(*bits); + *format = mCOLOR_RGB565; }; }