diff --git a/src/DSi_Camera.cpp b/src/DSi_Camera.cpp index f7f52f6e..8442960f 100644 --- a/src/DSi_Camera.cpp +++ b/src/DSi_Camera.cpp @@ -20,6 +20,7 @@ #include #include "DSi.h" #include "DSi_Camera.h" +#include "Platform.h" namespace DSi_CamModule @@ -33,10 +34,6 @@ u16 Cnt; u32 CropStart, CropEnd; -/*u8 FrameBuffer[640*480*4]; -u32 FrameLength; -u32 TransferPos;*/ - // pixel data buffer holds a maximum of 512 words, regardless of how long scanlines are u32 DataBuffer[512]; u32 BufferReadPos, BufferWritePos; @@ -77,9 +74,6 @@ void Reset() CropStart = 0; CropEnd = 0; - /*memset(FrameBuffer, 0, 640*480*4); - TransferPos = 0; - FrameLength = 256*192*2;*/ // TODO: make it check frame size, data type, etc memset(DataBuffer, 0, 512*sizeof(u32)); BufferReadPos = 0; BufferWritePos = 0; @@ -495,6 +489,8 @@ void Camera::StartTransfer() FrameReadMode = 0; FrameFormat = 0; } + + Platform::Camera_CaptureFrame(Num, FrameBuffer, 640, 480, true); } bool Camera::TransferDone() @@ -687,18 +683,30 @@ void Camera::I2C_WriteReg(u16 addr, u16 val) return; case 0x0016: ClocksCnt = val; - printf("ClocksCnt=%04X\n", val); + //printf("ClocksCnt=%04X\n", val); return; case 0x0018: - // TODO: this shouldn't be instant, but uh - val &= 0x003F; - val |= ((val & 0x0001) << 14); - StandbyCnt = val; - printf("CAM%d STBCNT=%04X (%04X)\n", Num, StandbyCnt, val); + { + bool wasactive = IsActivated(); + // TODO: this shouldn't be instant, but uh + val &= 0x003F; + val |= ((val & 0x0001) << 14); + StandbyCnt = val; + //printf("CAM%d STBCNT=%04X (%04X)\n", Num, StandbyCnt, val); + bool isactive = IsActivated(); + if (isactive && !wasactive) Platform::Camera_Start(Num); + else if (wasactive && !isactive) Platform::Camera_Stop(Num); + } return; case 0x001A: - MiscCnt = val & 0x0B7B; - printf("CAM%d MISCCNT=%04X (%04X)\n", Num, MiscCnt, val); + { + bool wasactive = IsActivated(); + MiscCnt = val & 0x0B7B; + //printf("CAM%d MISCCNT=%04X (%04X)\n", Num, MiscCnt, val); + bool isactive = IsActivated(); + if (isactive && !wasactive) Platform::Camera_Start(Num); + else if (wasactive && !isactive) Platform::Camera_Stop(Num); + } return; case 0x098C: diff --git a/src/Platform.h b/src/Platform.h index 4106977b..d0562712 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -144,6 +144,8 @@ void Mutex_Lock(Mutex* mutex); void Mutex_Unlock(Mutex* mutex); bool Mutex_TryLock(Mutex* mutex); +void Sleep(u64 usecs); + // functions called when the NDS or GBA save files need to be written back to storage // savedata and savelen are always the entire save memory buffer and its full length @@ -166,7 +168,15 @@ void LAN_DeInit(); int LAN_SendPacket(u8* data, int len); int LAN_RecvPacket(u8* data); -void Sleep(u64 usecs); + +// interface for camera emulation +// camera numbers: +// 0 = DSi outer camera +// 1 = DSi inner camera +// other values reserved for future camera addon emulation +void Camera_Start(int num); +void Camera_Stop(int num); +void Camera_CaptureFrame(int num, u32* frame, int width, int height, bool yuv); } diff --git a/src/frontend/qt_sdl/CameraManager.cpp b/src/frontend/qt_sdl/CameraManager.cpp index d9820731..1357c2d1 100644 --- a/src/frontend/qt_sdl/CameraManager.cpp +++ b/src/frontend/qt_sdl/CameraManager.cpp @@ -15,3 +15,123 @@ You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ + +#include "CameraManager.h" + + +CameraFrameDumper::CameraFrameDumper(QObject* parent) : QAbstractVideoSurface(parent) +{ +} + +bool CameraFrameDumper::present(const QVideoFrame& _frame) +{ + QVideoFrame frame(_frame); + if (!frame.map(QAbstractVideoBuffer::ReadOnly)) + return false; +printf("FRAMEZORZ!! %d %d %d\n", frame.pixelFormat(), frame.isMapped(), frame.isReadable()); + //NDS::CamInputFrame(0, (u32*)frame.bits(), frame.width(), frame.height(), false); + + frame.unmap(); + + return true; +} + +QList CameraFrameDumper::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const +{ + QList ret; + + ret.append(QVideoFrame::Format_RGB32); + ret.append(QVideoFrame::Format_YUYV); + + return ret; +} + + +CameraManager::CameraManager(int num, int width, int height, bool yuv) +{ + Num = num; + + FrameWidth = width; + FrameHeight = height; + FrameFormatYUV = yuv; + + int fbsize = FrameWidth * FrameHeight; + if (yuv) fbsize /= 2; + FrameBuffer = new u32[fbsize]; + + InputType = -1; + Init(); +} + +CameraManager::~CameraManager() +{ + DeInit(); + + // save settings here? + + delete[] FrameBuffer; +} + +void CameraManager::Init() +{ + if (InputType != -1) + DeInit(); + + // TODO: load settings from config!! + InputType = 0; + + { + // fill the framebuffer with black + + int total = FrameWidth * FrameHeight; + u32 fill = 0; + if (FrameFormatYUV) + { + total /= 2; + fill = 0x80008000; + } + + for (int i = 0; i < total; i++) + FrameBuffer[i] = fill; + } + + if (InputType == 1) + { + // still image + + // + } +} + +void CameraManager::DeInit() +{ + InputType = -1; +} + +void CameraManager::Start() +{ + // +} + +void CameraManager::Stop() +{ + // +} + +void CameraManager::CaptureFrame(u32* frame, int width, int height, bool yuv) +{ + FrameMutex.lock(); + + if (width == FrameWidth && height == FrameHeight && yuv == FrameFormatYUV) + { + int len = width * height; + if (yuv) len /= 2; + memcpy(frame, FrameBuffer, len * sizeof(u32)); + } + else + { + // + } + + FrameMutex.unlock(); +} diff --git a/src/frontend/qt_sdl/CameraManager.h b/src/frontend/qt_sdl/CameraManager.h index 7f734c66..b4158497 100644 --- a/src/frontend/qt_sdl/CameraManager.h +++ b/src/frontend/qt_sdl/CameraManager.h @@ -22,5 +22,47 @@ #include #include #include +#include +#include + +#include "types.h" + +class CameraFrameDumper : public QAbstractVideoSurface +{ + Q_OBJECT + +public: + CameraFrameDumper(QObject* parent = nullptr); + + bool present(const QVideoFrame& frame) override; + QList supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override; +}; + +class CameraManager +{ +public: + CameraManager(int num, int width, int height, bool yuv); + ~CameraManager(); + + void Init(); + void DeInit(); + + void Start(); + void Stop(); + + void CaptureFrame(u32* frame, int width, int height, bool yuv); + +private: + int Num; + + int InputType; + QString ImagePath; + QString CamDeviceName; + + int FrameWidth, FrameHeight; + bool FrameFormatYUV; + u32* FrameBuffer; + QMutex FrameMutex; +}; #endif // CAMERAMANAGER_H diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index 4306c988..d031e3b4 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -53,6 +53,7 @@ #include "Platform.h" #include "Config.h" #include "ROMManager.h" +#include "CameraManager.h" #include "LAN_Socket.h" #include "LAN_PCap.h" #include @@ -66,6 +67,8 @@ std::string EmuDirectory; void emuStop(); +extern CameraManager* camManager[2]; + namespace Platform { @@ -372,6 +375,11 @@ bool Mutex_TryLock(Mutex* mutex) return ((QMutex*) mutex)->try_lock(); } +void Sleep(u64 usecs) +{ + QThread::usleep(usecs); +} + void WriteNDSSave(const u8* savedata, u32 savelen, u32 writeoffset, u32 writelen) { @@ -529,7 +537,6 @@ int MP_RecvPacket(u8* data, bool block) } - bool LAN_Init() { if (Config::DirectLAN) @@ -573,9 +580,20 @@ int LAN_RecvPacket(u8* data) return LAN_Socket::RecvPacket(data); } -void Sleep(u64 usecs) + +void Camera_Start(int num) { - QThread::usleep(usecs); + return camManager[num]->Start(); +} + +void Camera_Stop(int num) +{ + return camManager[num]->Stop(); +} + +void Camera_CaptureFrame(int num, u32* frame, int width, int height, bool yuv) +{ + return camManager[num]->CaptureFrame(frame, width, height, yuv); } } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index d3a2d36f..43e1c3ba 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -86,6 +86,7 @@ #include "ROMManager.h" #include "ArchiveUtil.h" +#include "CameraManager.h" // TODO: uniform variable spelling @@ -112,6 +113,8 @@ u32 micExtBufferWritePos; u32 micWavLength; s16* micWavBuffer; +CameraManager* camManager[2]; + const struct { int id; float ratio; const char* label; } aspectRatios[] = { { 0, 1, "4:3 (native)" }, @@ -325,57 +328,6 @@ void micProcess() } -void camOpen() -{ - // -} - -void camClose() -{ - // -} - -void camProcess() -{ - // -} - -CameraFrameDumper::CameraFrameDumper(QObject* parent) : QAbstractVideoSurface(parent) -{ - printf("BAKA!!\n"); -} - -/*CameraFrameDumper::~CameraFrameDumper() -{ - printf("SAYONARA\n"); -}*/ - -bool CameraFrameDumper::present(const QVideoFrame& _frame) -{ - //printf("FRAMEZORZ!! %d %d %d\n", frame.pixelFormat(), frame.isMapped(), frame.isReadable()); - - QVideoFrame frame(_frame); - if (!frame.map(QAbstractVideoBuffer::ReadOnly)) - return false; -printf("FRAMEZORZ!! %d %d %d\n", frame.pixelFormat(), frame.isMapped(), frame.isReadable()); - NDS::CamInputFrame(0, (u32*)frame.bits(), frame.width(), frame.height(), false); - - frame.unmap(); - - return true; -} - -QList CameraFrameDumper::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const -{ - QList ret; -printf("PENIS. %d\n", type); - ret.append(QVideoFrame::Format_RGB32); - ret.append(QVideoFrame::Format_YUYV); - - return ret; -} - - EmuThread::EmuThread(QObject* parent) : QThread(parent) { EmuStatus = 0; @@ -436,7 +388,7 @@ void EmuThread::deinitOpenGL() delete oglContext; delete oglSurface; } -#include + void EmuThread::run() { bool hasOGL = mainWindow->hasOGL; @@ -604,9 +556,6 @@ printf("PROULON\n"); OSD::AddMessage(0, lid ? "Lid closed" : "Lid opened"); } - // camera input test - //NDS::CamInputFrame(0, (u32*)testimg_conv.bits(), testimg_conv.width(), testimg_conv.height(), true); - // microphone input micProcess(); @@ -3257,11 +3206,13 @@ int main(int argc, char** argv) micDevice = 0; - memset(micExtBuffer, 0, sizeof(micExtBuffer)); micExtBufferWritePos = 0; micWavBuffer = nullptr; + camManager[0] = new CameraManager(0, 640, 480, true); + camManager[1] = new CameraManager(1, 640, 480, true); + ROMManager::EnableCheats(Config::EnableCheats != 0); Frontend::Init_Audio(audioFreq); @@ -3312,6 +3263,9 @@ int main(int argc, char** argv) if (micWavBuffer) delete[] micWavBuffer; + delete camManager[0]; + delete camManager[1]; + Config::Save(); SDL_Quit(); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index df02a69e..6a2539eb 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -36,24 +36,8 @@ #include #include -#include -#include -#include - #include "FrontendUtil.h" -class CameraFrameDumper : public QAbstractVideoSurface -{ - Q_OBJECT - -public: - CameraFrameDumper(QObject* parent = nullptr); - //~CameraFrameDumper(); - - bool present(const QVideoFrame& frame) override; - QList supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override; -}; - class EmuThread : public QThread { Q_OBJECT