From 0010e296bd6d5e12c93791c7481bc04430a58ab5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 5 Sep 2019 11:42:08 +0200 Subject: [PATCH 1/9] GPU2D: delay palette lookup for sprites --- src/GPU2D.cpp | 129 +++++++++++++++++++++++++++++++------------------- src/GPU2D.h | 2 +- 2 files changed, 80 insertions(+), 51 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 288ee581..ef9be41c 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -1193,33 +1193,33 @@ u16* GPU2D::GetBGExtPal(u32 slot, u32 pal) return dst; } -u16* GPU2D::GetOBJExtPal(u32 pal) +u16* GPU2D::GetOBJExtPal() { - u16* dst = &OBJExtPalCache[pal << 8]; + u16* dst = OBJExtPalCache; - if (!(OBJExtPalStatus & (1< void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos) { - u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000; + u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0x40000; u32 tilenum = attrib[2] & 0x03FF; u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3); u32 xmos = 0, xmossize = 0; @@ -2337,7 +2374,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (!alpha) return; alpha++; - prio |= (0xC0000000 | (alpha << 24)); + pixelattr |= (0xC0000000 | (alpha << 24)); if (DispCnt & 0x40) { @@ -2387,7 +2424,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (color & 0x8000) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | prio; + else OBJLine[xpos] = color | pixelattr; } } else @@ -2414,8 +2451,8 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 ytilefactor = 0x20; } - if (spritemode == 1) prio |= 0x80000000; - else prio |= 0x10000000; + if (spritemode == 1) pixelattr |= 0x80000000; + else pixelattr |= 0x10000000; if (attrib[0] & 0x2000) { @@ -2424,13 +2461,9 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 ytilefactor <<= 5; u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; - u32 extpal = (DispCnt & 0x80000000); - - u16* pal; if (!window) { - if (extpal) pal = GetOBJExtPal(attrib[2] >> 12); - else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; + if (!(DispCnt & 0x80000000)) pixelattr |= 0x1000; } if (xmos && !(attrib[0]&0x0200)) @@ -2451,7 +2484,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } } else @@ -2473,11 +2506,10 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 ytilefactor <<= 5; u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; - u16* pal; if (!window) { - pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; - pal += (attrib[2] & 0xF000) >> 8; + pixelattr |= 0x1000; + pixelattr |= ((attrib[2] & 0xF000) >> 8); } if (xmos && !(attrib[0]&0x0200)) @@ -2509,7 +2541,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } } else @@ -2530,7 +2562,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 template void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) { - u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000; + u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0x40000; u32 tilenum = attrib[2] & 0x03FF; u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3); u32 xmos = 0, xmossize = 0; @@ -2572,7 +2604,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (!alpha) return; alpha++; - prio |= (0xC0000000 | (alpha << 24)); + pixelattr |= (0xC0000000 | (alpha << 24)); if (DispCnt & 0x40) { @@ -2625,7 +2657,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color & 0x8000) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; @@ -2652,7 +2684,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color & 0x8000) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; @@ -2672,8 +2704,8 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) tilenum += ((ypos >> 3) * 0x20); } - if (spritemode == 1) prio |= 0x80000000; - else prio |= 0x10000000; + if (spritemode == 1) pixelattr |= 0x80000000; + else pixelattr |= 0x10000000; if (attrib[0] & 0x2000) { @@ -2682,13 +2714,9 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; pixelsaddr += ((ypos & 0x7) << 3); - u32 extpal = (DispCnt & 0x80000000); - - u16* pal; if (!window) { - if (extpal) pal = GetOBJExtPal(attrib[2] >> 12); - else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; + if (!(DispCnt & 0x80000000)) pixelattr |= 0x1000; } if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works @@ -2712,7 +2740,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; @@ -2741,7 +2769,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; @@ -2757,13 +2785,14 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; pixelsaddr += ((ypos & 0x7) << 2); - u16* pal; if (!window) { - pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; - pal += (attrib[2] & 0xF000) >> 8; + pixelattr |= 0x1000; + pixelattr |= ((attrib[2] & 0xF000) >> 8); } + // TODO: optimize VRAM access!! + if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works { pixelsaddr += (((width-1 - xoff) & wmask) << 2); @@ -2790,7 +2819,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; @@ -2824,7 +2853,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; diff --git a/src/GPU2D.h b/src/GPU2D.h index 6ad97830..9184215f 100644 --- a/src/GPU2D.h +++ b/src/GPU2D.h @@ -63,7 +63,7 @@ public: void OBJExtPalDirty(); u16* GetBGExtPal(u32 slot, u32 pal); - u16* GetOBJExtPal(u32 pal); + u16* GetOBJExtPal(); private: u32 Num; From 1aaf0c33cef521b86b72110e82ba6ef7ac0581dd Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 5 Sep 2019 11:49:22 +0200 Subject: [PATCH 2/9] guess who the idiot is who broke sprite extpal --- src/GPU2D.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index ef9be41c..9297643d 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -2463,7 +2463,10 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (!window) { - if (!(DispCnt & 0x80000000)) pixelattr |= 0x1000; + if (!(DispCnt & 0x80000000)) + pixelattr |= 0x1000; + else + pixelattr |= ((attrib[2] & 0xF000) >> 4); } if (xmos && !(attrib[0]&0x0200)) @@ -2716,7 +2719,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (!window) { - if (!(DispCnt & 0x80000000)) pixelattr |= 0x1000; + if (!(DispCnt & 0x80000000)) + pixelattr |= 0x1000; + else + pixelattr |= ((attrib[2] & 0xF000) >> 4); } if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works From 9d376335b722c627b00061d89143c5a70ddeeb99 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 13 Sep 2019 22:43:02 +0200 Subject: [PATCH 3/9] HARK HARK HARK HARK --- melonDS.cbp | 22 +++++++++++++++++++ src/libui_sdl/MelonCap.cpp | 43 ++++++++++++++++++++++++++++++++++++++ src/libui_sdl/MelonCap.h | 34 ++++++++++++++++++++++++++++++ src/libui_sdl/main.cpp | 16 ++++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 src/libui_sdl/MelonCap.cpp create mode 100644 src/libui_sdl/MelonCap.h diff --git a/melonDS.cbp b/melonDS.cbp index 0af2f4ab..a9a7b722 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -53,6 +53,22 @@ + + @@ -143,6 +159,12 @@ + + + + diff --git a/src/libui_sdl/MelonCap.cpp b/src/libui_sdl/MelonCap.cpp new file mode 100644 index 00000000..aea187fe --- /dev/null +++ b/src/libui_sdl/MelonCap.cpp @@ -0,0 +1,43 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include "MelonCap.h" + + +namespace MelonCap +{ + +void Init() +{ + printf("MelonCap init\n"); +} + +void DeInit() +{ + // +} + + +void Update() +{ + // +} + +} diff --git a/src/libui_sdl/MelonCap.h b/src/libui_sdl/MelonCap.h new file mode 100644 index 00000000..1185dea0 --- /dev/null +++ b/src/libui_sdl/MelonCap.h @@ -0,0 +1,34 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef MELONCAP_H +#define MELONCAP_H + +#include "types.h" + +namespace MelonCap +{ + +void Init(); +void DeInit(); + +void Update(); + +} + +#endif // MELONCAP_H diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index d4afa228..13778ec9 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -48,6 +48,10 @@ #include "OSD.h" +#ifdef MELONCAP +#include "MelonCap.h" +#endif // MELONCAP + // savestate slot mapping // 1-8: regular slots (quick access) @@ -999,6 +1003,10 @@ int EmuThreadFunc(void* burp) // emulate u32 nlines = NDS::RunFrame(); +#ifdef MELONCAP + MelonCap::Update(); +#endif // MELONCAP + if (EmuRunning == 0) break; if (Screen_UseGL) @@ -2739,6 +2747,10 @@ int main(int argc, char** argv) uiMenuItemSetChecked(MenuItem_AudioSync, Config::AudioSync==1); uiMenuItemSetChecked(MenuItem_ShowOSD, Config::ShowOSD==1); +#ifdef MELONCAP + MelonCap::Init(); +#endif // MELONCAP + AudioSync = SDL_CreateCond(); AudioSyncLock = SDL_CreateMutex(); @@ -2822,6 +2834,10 @@ int main(int argc, char** argv) if (MicWavBuffer) delete[] MicWavBuffer; +#ifdef MELONCAP + MelonCap::DeInit(); +#endif // MELONCAP + if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]); if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]); From 1c3661f33d9ee2a0985fe0a7782c81f3ed21821d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 14 Sep 2019 01:16:38 +0200 Subject: [PATCH 4/9] BLAHAHAHAHHHH --- melonDS.cbp | 2 + src/libui_sdl/MelonCap.cpp | 299 ++++++++++++++++++++++++++++++++++++- 2 files changed, 299 insertions(+), 2 deletions(-) diff --git a/melonDS.cbp b/melonDS.cbp index a9a7b722..a1fd6d5d 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -67,6 +67,8 @@ + + diff --git a/src/libui_sdl/MelonCap.cpp b/src/libui_sdl/MelonCap.cpp index aea187fe..0383ec14 100644 --- a/src/libui_sdl/MelonCap.cpp +++ b/src/libui_sdl/MelonCap.cpp @@ -19,25 +19,320 @@ #include #include #include "MelonCap.h" +#include "libui/ui.h" +#include "../NDS.h" +#include "../GPU.h" + +#include +#include +#include +#include namespace MelonCap { +uiWindow* Window; +uiArea* Area; +uiAreaHandler AreaHandler; +uiDrawBitmap* WinBitmap; +bool WinBitmapInited; + +u32* WinBitmapData; + +// this crap was built from the reverse-engineering of ds_capture.exe + +GUID InterfaceClass = {0xA0B880F6, 0xD6A5, 0x4700, {0xA8, 0xEA, 0x22, 0x28, 0x2A, 0xCA, 0x55, 0x87}}; +HANDLE CapHandle; +WINUSB_INTERFACE_HANDLE CapUSBHandle; + + +void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params) +{ + if (!WinBitmapInited) + { + if (WinBitmap) uiDrawFreeBitmap(WinBitmap); + + WinBitmapInited = true; + WinBitmap = uiDrawNewBitmap(params->Context, 768, 384, 0); + } + + if (!WinBitmap) return; + if (!WinBitmapData) return; + + uiRect rc = {0, 0, 768, 384}; + + uiDrawBitmapUpdate(WinBitmap, WinBitmapData); + uiDrawBitmapDraw(params->Context, WinBitmap, &rc, &rc, 0); +} + +void OnAreaMouseEvent(uiAreaHandler* handler, uiArea* area, uiAreaMouseEvent* evt) +{ +} + +void OnAreaMouseCrossed(uiAreaHandler* handler, uiArea* area, int left) +{ +} + +void OnAreaDragBroken(uiAreaHandler* handler, uiArea* area) +{ +} + +int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) +{ + return 1; +} + +void OnAreaResize(uiAreaHandler* handler, uiArea* area, int width, int height) +{ +} + + void Init() { printf("MelonCap init\n"); + + // TODO: flags value!!!!! + HDEVINFO devinfo = SetupDiGetClassDevsW(&InterfaceClass, NULL, NULL, 0x12); + if (devinfo == INVALID_HANDLE_VALUE) return; + + int member = 0; + bool good = false; + for (;;) + { + SP_DEVICE_INTERFACE_DATA interfacedata; + memset(&interfacedata, 0, sizeof(interfacedata)); + interfacedata.cbSize = sizeof(interfacedata); + + BOOL ret = SetupDiEnumDeviceInterfaces(devinfo, NULL, &InterfaceClass, member, &interfacedata); + if (!ret) + { + printf("found %d interfaces\n", member); + break; + } + + DWORD requiredsize = 0; + SetupDiGetDeviceInterfaceDetailW(devinfo, &interfacedata, NULL, NULL, &requiredsize, NULL); + printf("%d: required size %d\n", member, requiredsize); + + PSP_DEVICE_INTERFACE_DETAIL_DATA_W interfacedetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)new u8[requiredsize]; + interfacedetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA_W); + ret = SetupDiGetDeviceInterfaceDetailW(devinfo, &interfacedata, interfacedetail, requiredsize, NULL, NULL); + if (ret) + { + printf("got interface detail: path=%S\n", interfacedetail->DevicePath); + HANDLE file = CreateFileW(interfacedetail->DevicePath, 0xC0000000, 3, NULL, 3, 0x40000080, NULL); + if (file != INVALID_HANDLE_VALUE) + { + WINUSB_INTERFACE_HANDLE usbhandle; + ret = WinUsb_Initialize(file, &usbhandle); + if (ret) + { + int val; + val = 0x1E; + WinUsb_SetPipePolicy(usbhandle, 0x00, 3, 4, &val); + val = 0x32; + WinUsb_SetPipePolicy(usbhandle, 0x82, 3, 4, &val); + val = 0x01; + WinUsb_SetPipePolicy(usbhandle, 0x82, 7, 1, &val); + + printf("looking good\n"); + good = true; + + CapHandle = file; + CapUSBHandle = usbhandle; + } + else + CloseHandle(file); + } + } + + delete[] (u8*)interfacedetail; + + if (good) break; + + member++; + } + + SetupDiDestroyDeviceInfoList(devinfo); + + + AreaHandler.Draw = OnAreaDraw; + AreaHandler.MouseEvent = OnAreaMouseEvent; + AreaHandler.MouseCrossed = OnAreaMouseCrossed; + AreaHandler.DragBroken = OnAreaDragBroken; + AreaHandler.KeyEvent = OnAreaKeyEvent; + AreaHandler.Resize = OnAreaResize; + + WinBitmapInited = false; + WinBitmapData = new u32[768*384]; + + Window = uiNewWindow("melonDS - topnotch pixel checker", 768, 384, 0, 0, 0); + Area = uiNewArea(&AreaHandler); + uiWindowSetChild(Window, uiControl(Area)); + + uiControlShow(uiControl(Window)); } void DeInit() { - // + uiControlDestroy(uiControl(Window)); + uiDrawFreeBitmap(WinBitmap); + WinBitmapInited = false; + delete[] WinBitmapData; + + WinUsb_Free(CapUSBHandle); + CloseHandle(CapHandle); } +u32 VendorIn(u8 req, u16 len, u8* buf) +{ + WINUSB_SETUP_PACKET pkt; + pkt.RequestType = 0xC0; // device to host + pkt.Request = req; + pkt.Value = 0; // ????? + pkt.Index = 0; + pkt.Length = len; + + ULONG ret = 0; + BOOL res = WinUsb_ControlTransfer(CapUSBHandle, pkt, buf, len, &ret, NULL); + if (!res) return -1; + return ret; +} + +u32 VendorOut(u8 req, u16 val, u16 len, u8* buf) +{ + WINUSB_SETUP_PACKET pkt; + pkt.RequestType = 0x40; // device to host + pkt.Request = req; + pkt.Value = val; + pkt.Index = 0; + pkt.Length = len; + + ULONG ret = 0; + BOOL res = WinUsb_ControlTransfer(CapUSBHandle, pkt, buf, len, &ret, NULL); + if (!res) return -1; + return ret; +} + +u32 BulkIn(u8* buf, u32 len) +{ + ULONG ret = 0; + BOOL res = WinUsb_ReadPipe(CapUSBHandle, 0x82, buf, len, &ret, NULL); + if (!res) return -1; + return ret; +} + + +u32 ConvertColor(u16 col) +{ + u32 b = col & 0x001F; + u32 g = (col & 0x07E0) >> 5; + u32 r = (col & 0xF800) >> 11; + + u32 ret = 0xFF000000; + ret |= ((r << 3) | (r >> 2)) << 16; + ret |= ((g << 2) | (g >> 4)) << 8; + ret |= (b << 3) | (b >> 2); + return ret; +} + +void CaptureFrame() +{ + u32 ret; + u8 derp; + u32 framelen = 256*384*2; + u16 frame[framelen/2]; + u32 framepos = 0; + u8 frameinfo[64]; + + ret = VendorOut(0x30, 0, 0, &derp); + if (ret < 0) return; + + while (framepos < framelen) + { + ret = BulkIn((u8*)&frame[framepos/2], framelen-framepos); + if (ret < 0) break; + if (ret > 0) framepos += ret; + } + + ret = VendorIn(0x30, 64, frameinfo); + if (ret < 0) return; + if ((frameinfo[0] & 0x03) != 0x03) return; + if (!frameinfo[52]) return; + + u16* in = &frame[0]; + u32* out = &WinBitmapData[256]; + + for (int y = 0; y < 384; y++) + { + u32* out = &WinBitmapData[((y/2)*768) + ((y&1)*128) + 256]; + + if (!(frameinfo[y>>3] & (1<<(y&7)))) + { + continue; + } + + for (int x = 0; x < 256/2; x++) + { + out[0] = ConvertColor(in[1]); + out[768*192] = ConvertColor(in[0]); + out++; + in += 2; + } + } +} + void Update() { - // + // melonDS output + + int frontbuf = GPU::FrontBuffer; + + u32* topbuf = GPU::Framebuffer[frontbuf][0]; + if (topbuf) + { + for (int y = 0; y < 192; y++) + { + memcpy(&WinBitmapData[y*768], &topbuf[y*256], 256*4); + } + } + + u32* botbuf = GPU::Framebuffer[frontbuf][1]; + if (botbuf) + { + for (int y = 0; y < 192; y++) + { + memcpy(&WinBitmapData[(y+192)*768], &botbuf[y*256], 256*4); + } + } + + // DS capture + + CaptureFrame(); + + // compare + + for (int y = 0; y < 384; y++) + { + for (int x = 0; x < 256; x++) + { + u32 colA = WinBitmapData[(y*768) + x + 0]; + u32 colB = WinBitmapData[(y*768) + x + 256]; + + // best we get from the capture card is RGB565 + // so we'll ignore the lower bits + const u32 mask = 0x00F8FCF8; + colA &= mask; + colB &= mask; + + if (colA == colB) WinBitmapData[(y*768) + x + 512] = 0xFF00FF00; + else WinBitmapData[(y*768) + x + 512] = 0xFFFF0000; + } + } + + uiAreaQueueRedrawAll(Area); } } From 20a97b79d4c37ba40ee39ae0d3ab142184c234c4 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 14 Sep 2019 01:38:46 +0200 Subject: [PATCH 5/9] make it a bit less braindead --- melonDS.cbp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/melonDS.cbp b/melonDS.cbp index a1fd6d5d..fb42cb47 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -55,8 +55,8 @@