aboutsummaryrefslogtreecommitdiff
path: root/src/DSi_Camera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/DSi_Camera.cpp')
-rw-r--r--src/DSi_Camera.cpp698
1 files changed, 526 insertions, 172 deletions
diff --git a/src/DSi_Camera.cpp b/src/DSi_Camera.cpp
index e83434f..842a9ee 100644
--- a/src/DSi_Camera.cpp
+++ b/src/DSi_Camera.cpp
@@ -20,17 +20,25 @@
#include <string.h>
#include "DSi.h"
#include "DSi_Camera.h"
+#include "Platform.h"
-DSi_Camera* DSi_Camera0; // 78 / facing outside
-DSi_Camera* DSi_Camera1; // 7A / selfie cam
+namespace DSi_CamModule
+{
+
+Camera* Camera0; // 78 / facing outside
+Camera* Camera1; // 7A / selfie cam
+
+u16 ModuleCnt;
+u16 Cnt;
-u16 DSi_Camera::ModuleCnt;
-u16 DSi_Camera::Cnt;
+u32 CropStart, CropEnd;
-u8 DSi_Camera::FrameBuffer[640*480*4];
-u32 DSi_Camera::FrameLength;
-u32 DSi_Camera::TransferPos;
+// pixel data buffer holds a maximum of 512 words, regardless of how long scanlines are
+u32 DataBuffer[512];
+u32 BufferReadPos, BufferWritePos;
+u32 BufferNumLines;
+Camera* CurCamera;
// note on camera data/etc intervals
// on hardware those are likely affected by several factors
@@ -41,133 +49,353 @@ const u32 kIRQInterval = 1120000; // ~30 FPS
const u32 kTransferStart = 60000;
-bool DSi_Camera::Init()
+bool Init()
{
- DSi_Camera0 = new DSi_Camera(0);
- DSi_Camera1 = new DSi_Camera(1);
+ Camera0 = new Camera(0);
+ Camera1 = new Camera(1);
return true;
}
-void DSi_Camera::DeInit()
+void DeInit()
{
- delete DSi_Camera0;
- delete DSi_Camera1;
+ delete Camera0;
+ delete Camera1;
}
-void DSi_Camera::Reset()
+void Reset()
{
- DSi_Camera0->ResetCam();
- DSi_Camera1->ResetCam();
+ Camera0->Reset();
+ Camera1->Reset();
ModuleCnt = 0; // CHECKME
Cnt = 0;
- memset(FrameBuffer, 0, 640*480*4);
- TransferPos = 0;
- FrameLength = 256*192*2; // TODO: make it check frame size, data type, etc
+ CropStart = 0;
+ CropEnd = 0;
+
+ memset(DataBuffer, 0, 512*sizeof(u32));
+ BufferReadPos = 0;
+ BufferWritePos = 0;
+ BufferNumLines = 0;
+ CurCamera = nullptr;
NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, true, kIRQInterval, IRQ, 0);
}
-void DSi_Camera::DoSavestate(Savestate* file)
+void DoSavestate(Savestate* file)
{
file->Section("CAMi");
file->Var16(&ModuleCnt);
file->Var16(&Cnt);
- file->VarArray(FrameBuffer, sizeof(FrameBuffer));
+ /*file->VarArray(FrameBuffer, sizeof(FrameBuffer));
file->Var32(&TransferPos);
- file->Var32(&FrameLength);
+ file->Var32(&FrameLength);*/
- DSi_Camera0->DoCamSavestate(file);
- DSi_Camera1->DoCamSavestate(file);
+ Camera0->DoSavestate(file);
+ Camera1->DoSavestate(file);
}
-void DSi_Camera::IRQ(u32 param)
+void IRQ(u32 param)
{
- DSi_Camera* activecam = nullptr;
+ Camera* activecam = nullptr;
- // TODO: check which camera has priority if both are activated
- // (or does it just jumble both data sources together, like it
- // does for, say, overlapping VRAM?)
- if (DSi_Camera0->IsActivated()) activecam = DSi_Camera0;
- else if (DSi_Camera1->IsActivated()) activecam = DSi_Camera1;
+ // TODO: cameras don't have any priority!
+ // activating both together will jumble the image data together
+ if (Camera0->IsActivated()) activecam = Camera0;
+ else if (Camera1->IsActivated()) activecam = Camera1;
if (activecam)
{
- RequestFrame(activecam->Num);
+ activecam->StartTransfer();
if (Cnt & (1<<11))
NDS::SetIRQ(0, NDS::IRQ_DSi_Camera);
if (Cnt & (1<<15))
- NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, kTransferStart, Transfer, 0);
+ {
+ BufferReadPos = 0;
+ BufferWritePos = 0;
+ BufferNumLines = 0;
+ CurCamera = activecam;
+ NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, kTransferStart, TransferScanline, 0);
+ }
}
NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, true, kIRQInterval, IRQ, 0);
}
-void DSi_Camera::RequestFrame(u32 cam)
+void TransferScanline(u32 line)
{
- if (!(Cnt & (1<<13))) printf("CAMERA: !! REQUESTING YUV FRAME\n");
+ u32* dstbuf = &DataBuffer[BufferWritePos];
+ int maxlen = 512 - BufferWritePos;
+
+ u32 tmpbuf[512];
+ int datalen = CurCamera->TransferScanline(tmpbuf, 512);
+
+ // TODO: must be tweaked such that each block has enough time to transfer
+ u32 delay = datalen*4 + 16;
- // TODO: picture size, data type, cropping, etc
- // generate test pattern
- // TODO: get picture from platform (actual camera, video file, whatever source)
- for (u32 y = 0; y < 192; y++)
+ int copystart = 0;
+ int copylen = datalen;
+
+ if (Cnt & (1<<14))
{
- for (u32 x = 0; x < 256; x++)
+ // crop picture
+
+ int ystart = (CropStart >> 16) & 0x1FF;
+ int yend = (CropEnd >> 16) & 0x1FF;
+ if (line < ystart || line > yend)
{
- u16* px = (u16*)&FrameBuffer[((y*256) + x) * 2];
+ if (!CurCamera->TransferDone())
+ NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, delay, TransferScanline, line+1);
- if ((x & 0x8) ^ (y & 0x8))
- *px = 0x8000;
- else
- *px = 0xFC00 | ((y >> 3) << 5);
+ return;
}
+
+ int xstart = (CropStart >> 1) & 0x1FF;
+ int xend = (CropEnd >> 1) & 0x1FF;
+
+ copystart = xstart;
+ copylen = xend+1 - xstart;
+
+ if ((copystart + copylen) > datalen)
+ copylen = datalen - copystart;
+ if (copylen < 0)
+ copylen = 0;
+ }
+
+ if (copylen > maxlen)
+ {
+ copylen = maxlen;
+ Cnt |= (1<<4);
+ }
+
+ if (Cnt & (1<<13))
+ {
+ // convert to RGB
+
+ for (u32 i = 0; i < copylen; i++)
+ {
+ u32 val = tmpbuf[copystart + i];
+
+ int y1 = val & 0xFF;
+ int u = (val >> 8) & 0xFF;
+ int y2 = (val >> 16) & 0xFF;
+ int v = (val >> 24) & 0xFF;
+
+ u -= 128; v -= 128;
+
+ int r1 = y1 + ((v * 91881) >> 16);
+ int g1 = y1 - ((v * 46793) >> 16) - ((u * 22544) >> 16);
+ int b1 = y1 + ((u * 116129) >> 16);
+
+ int r2 = y2 + ((v * 91881) >> 16);
+ int g2 = y2 - ((v * 46793) >> 16) - ((u * 22544) >> 16);
+ int b2 = y2 + ((u * 116129) >> 16);
+
+ r1 = std::clamp(r1, 0, 255); g1 = std::clamp(g1, 0, 255); b1 = std::clamp(b1, 0, 255);
+ r2 = std::clamp(r2, 0, 255); g2 = std::clamp(g2, 0, 255); b2 = std::clamp(b2, 0, 255);
+
+ u32 col1 = (r1 >> 3) | ((g1 >> 3) << 5) | ((b1 >> 3) << 10) | 0x8000;
+ u32 col2 = (r2 >> 3) | ((g2 >> 3) << 5) | ((b2 >> 3) << 10) | 0x8000;
+
+ dstbuf[i] = col1 | (col2 << 16);
+ }
+ }
+ else
+ {
+ // return raw data
+
+ memcpy(dstbuf, &tmpbuf[copystart], copylen*sizeof(u32));
+ }
+
+ u32 numscan = Cnt & 0x000F;
+ if (BufferNumLines >= numscan)
+ {
+ BufferReadPos = 0; // checkme
+ BufferWritePos = 0;
+ BufferNumLines = 0;
+ DSi::CheckNDMAs(0, 0x0B);
}
+ else
+ {
+ BufferWritePos += copylen;
+ if (BufferWritePos > 512) BufferWritePos = 512;
+ BufferNumLines++;
+ }
+
+ if (CurCamera->TransferDone())
+ return;
+
+ NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, delay, TransferScanline, line+1);
}
-void DSi_Camera::Transfer(u32 pos)
+
+u8 Read8(u32 addr)
{
- u32 numscan = (Cnt & 0x000F) + 1;
- u32 numpix = numscan * 256; // CHECKME
+ //
- // TODO: present data
- //printf("CAM TRANSFER POS=%d/%d\n", pos, 0x6000*2);
+ printf("unknown DSi cam read8 %08X\n", addr);
+ return 0;
+}
- DSi::CheckNDMAs(0, 0x0B);
+u16 Read16(u32 addr)
+{
+ switch (addr)
+ {
+ case 0x04004200: return ModuleCnt;
+ case 0x04004202: return Cnt;
+ }
- pos += numpix;
- if (pos >= 0x6000*2) // HACK
+ printf("unknown DSi cam read16 %08X\n", addr);
+ return 0;
+}
+
+u32 Read32(u32 addr)
+{
+ switch (addr)
{
- // transfer done
+ case 0x04004204:
+ {
+ u32 ret = DataBuffer[BufferReadPos];
+ if (Cnt & (1<<15))
+ {
+ if (BufferReadPos < 511)
+ BufferReadPos++;
+ // CHECKME!!!!
+ // also presumably we should set bit4 in Cnt if there's no new data to be read
+ }
+
+ return ret;
+ }
+
+ case 0x04004210: return CropStart;
+ case 0x04004214: return CropEnd;
}
- else
+
+ printf("unknown DSi cam read32 %08X\n", addr);
+ return 0;
+}
+
+void Write8(u32 addr, u8 val)
+{
+ //
+
+ printf("unknown DSi cam write8 %08X %02X\n", addr, val);
+}
+
+void Write16(u32 addr, u16 val)
+{
+ switch (addr)
{
- // keep going
+ case 0x04004200:
+ {
+ u16 oldcnt = ModuleCnt;
+ ModuleCnt = val;
- // TODO: must be tweaked such that each block has enough time to transfer
- u32 delay = numpix*2 + 16;
+ if ((ModuleCnt & (1<<1)) && !(oldcnt & (1<<1)))
+ {
+ // reset shit to zero
+ // CHECKME
- NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, delay, Transfer, pos);
+ Cnt = 0;
+ }
+
+ if ((ModuleCnt & (1<<5)) && !(oldcnt & (1<<5)))
+ {
+ // TODO: reset I2C??
+ }
+ }
+ return;
+
+ case 0x04004202:
+ {
+ // TODO: during a transfer, clearing bit15 does not reflect immediately
+ // maybe it needs to finish the trasnfer or atleast the current block
+
+ // checkme
+ u16 oldmask;
+ if (Cnt & 0x8000)
+ {
+ val &= 0x8F20;
+ oldmask = 0x601F;
+ }
+ else
+ {
+ val &= 0xEF2F;
+ oldmask = 0x0010;
+ }
+
+ Cnt = (Cnt & oldmask) | (val & ~0x0020);
+ if (val & (1<<5))
+ {
+ Cnt &= ~(1<<4);
+ BufferReadPos = 0;
+ BufferWritePos = 0;
+ }
+
+ if ((val & (1<<15)) && !(Cnt & (1<<15)))
+ {
+ // start transfer
+ //DSi::CheckNDMAs(0, 0x0B);
+ }
+ }
+ return;
+
+ case 0x04004210:
+ if (Cnt & (1<<15)) return;
+ CropStart = (CropStart & 0x01FF0000) | (val & 0x03FE);
+ return;
+ case 0x04004212:
+ if (Cnt & (1<<15)) return;
+ CropStart = (CropStart & 0x03FE) | ((val & 0x01FF) << 16);
+ return;
+ case 0x04004214:
+ if (Cnt & (1<<15)) return;
+ CropEnd = (CropEnd & 0x01FF0000) | (val & 0x03FE);
+ return;
+ case 0x04004216:
+ if (Cnt & (1<<15)) return;
+ CropEnd = (CropEnd & 0x03FE) | ((val & 0x01FF) << 16);
+ return;
+ }
+
+ printf("unknown DSi cam write16 %08X %04X\n", addr, val);
+}
+
+void Write32(u32 addr, u32 val)
+{
+ switch (addr)
+ {
+ case 0x04004210:
+ if (Cnt & (1<<15)) return;
+ CropStart = val & 0x01FF03FE;
+ return;
+ case 0x04004214:
+ if (Cnt & (1<<15)) return;
+ CropEnd = val & 0x01FF03FE;
+ return;
}
+
+ printf("unknown DSi cam write32 %08X %08X\n", addr, val);
}
-DSi_Camera::DSi_Camera(u32 num)
+
+Camera::Camera(u32 num)
{
Num = num;
}
-DSi_Camera::~DSi_Camera()
+Camera::~Camera()
{
}
-void DSi_Camera::DoCamSavestate(Savestate* file)
+void Camera::DoSavestate(Savestate* file)
{
char magic[5] = "CAMx";
magic[3] = '0' + Num;
@@ -185,12 +413,10 @@ void DSi_Camera::DoCamSavestate(Savestate* file)
file->Var16(&MiscCnt);
file->Var16(&MCUAddr);
- // TODO: MCUData??
-
file->VarArray(MCURegs, 0x8000);
}
-void DSi_Camera::ResetCam()
+void Camera::Reset()
{
DataPos = 0;
RegAddr = 0;
@@ -202,9 +428,18 @@ void DSi_Camera::ResetCam()
ClocksCnt = 0;
StandbyCnt = 0x4029; // checkme
MiscCnt = 0;
+
+ MCUAddr = 0;
+ memset(MCURegs, 0, 0x8000);
+
+ // default state is preview mode (checkme)
+ MCURegs[0x2104] = 3;
+
+ TransferY = 0;
+ memset(FrameBuffer, 0, (640*480/2)*sizeof(u32));
}
-bool DSi_Camera::IsActivated()
+bool Camera::IsActivated()
{
if (StandbyCnt & (1<<14)) return false; // standby
if (!(MiscCnt & (1<<9))) return false; // data transfer not enabled
@@ -213,31 +448,99 @@ bool DSi_Camera::IsActivated()
}
-void DSi_Camera::I2C_Start()
+void Camera::StartTransfer()
{
+ TransferY = 0;
+
+ u8 state = MCURegs[0x2104];
+ if (state == 3) // preview
+ {
+ FrameWidth = *(u16*)&MCURegs[0x2703];
+ FrameHeight = *(u16*)&MCURegs[0x2705];
+ FrameReadMode = *(u16*)&MCURegs[0x2717];
+ FrameFormat = *(u16*)&MCURegs[0x2755];
+ }
+ else if (state == 7) // capture
+ {
+ FrameWidth = *(u16*)&MCURegs[0x2707];
+ FrameHeight = *(u16*)&MCURegs[0x2709];
+ FrameReadMode = *(u16*)&MCURegs[0x272D];
+ FrameFormat = *(u16*)&MCURegs[0x2757];
+ }
+ else
+ {
+ FrameWidth = 0;
+ FrameHeight = 0;
+ FrameReadMode = 0;
+ FrameFormat = 0;
+ }
+
+ Platform::Camera_CaptureFrame(Num, FrameBuffer, 640, 480, true);
}
-u8 DSi_Camera::I2C_Read(bool last)
+bool Camera::TransferDone()
+{
+ return TransferY >= FrameHeight;
+}
+
+int Camera::TransferScanline(u32* buffer, int maxlen)
+{
+ if (TransferY >= FrameHeight)
+ return 0;
+
+ if (FrameWidth > 640 || FrameHeight > 480 ||
+ FrameWidth < 2 || FrameHeight < 2 ||
+ (FrameWidth & 1))
+ {
+ // TODO work out something for these cases?
+ printf("CAM%d: invalid resolution %dx%d\n", Num, FrameWidth, FrameHeight);
+ //memset(buffer, 0, width*height*sizeof(u16));
+ return 0;
+ }
+
+ // TODO: non-YUV pixel formats and all
+
+ int retlen = FrameWidth >> 1;
+ int sy = (TransferY * 480) / FrameHeight;
+ if (FrameReadMode & (1<<1))
+ sy = 479 - sy;
+
+ for (int dx = 0; dx < retlen; dx++)
+ {
+ if (dx >= maxlen) break;
+
+ int sx = (dx * 640) / FrameWidth;
+ if (!(FrameReadMode & (1<<0)))
+ sx = 639 - sx;
+
+ u32 pixel3 = FrameBuffer[sy*320 + sx];
+ buffer[dx] = pixel3;
+ }
+
+ TransferY++;
+
+ return retlen;
+}
+
+
+void Camera::I2C_Start()
+{
+ DataPos = 0;
+}
+
+u8 Camera::I2C_Read(bool last)
{
u8 ret;
- if (DataPos < 2)
+ if (DataPos & 0x1)
{
- printf("DSi_Camera: WHAT??\n");
- ret = 0;
+ ret = RegData & 0xFF;
+ RegAddr += 2; // checkme
}
else
{
- if (DataPos & 0x1)
- {
- ret = RegData & 0xFF;
- RegAddr += 2; // checkme
- }
- else
- {
- RegData = I2C_ReadReg(RegAddr);
- ret = RegData >> 8;
- }
+ RegData = I2C_ReadReg(RegAddr);
+ ret = RegData >> 8;
}
if (last) DataPos = 0;
@@ -246,7 +549,7 @@ u8 DSi_Camera::I2C_Read(bool last)
return ret;
}
-void DSi_Camera::I2C_Write(u8 val, bool last)
+void Camera::I2C_Write(u8 val, bool last)
{
if (DataPos < 2)
{
@@ -275,7 +578,7 @@ void DSi_Camera::I2C_Write(u8 val, bool last)
else DataPos++;
}
-u16 DSi_Camera::I2C_ReadReg(u16 addr)
+u16 Camera::I2C_ReadReg(u16 addr)
{
switch (addr)
{
@@ -287,6 +590,23 @@ u16 DSi_Camera::I2C_ReadReg(u16 addr)
case 0x0018: return StandbyCnt;
case 0x001A: return MiscCnt;
+ case 0x098C: return MCUAddr;
+ case 0x0990:
+ case 0x0992:
+ case 0x0994:
+ case 0x0996:
+ case 0x0998:
+ case 0x099A:
+ case 0x099C:
+ case 0x099E:
+ {
+ addr -= 0x0990;
+ u16 ret = MCU_Read((MCUAddr & 0x7FFF) + addr);
+ if (!(MCUAddr & (1<<15)))
+ ret |= (MCU_Read((MCUAddr & 0x7FFF) + addr+1) << 8);
+ return ret;
+ }
+
case 0x301A: return ((~StandbyCnt) & 0x4000) >> 12;
}
@@ -294,7 +614,7 @@ u16 DSi_Camera::I2C_ReadReg(u16 addr)
return 0;
}
-void DSi_Camera::I2C_WriteReg(u16 addr, u16 val)
+void Camera::I2C_WriteReg(u16 addr, u16 val)
{
switch (addr)
{
@@ -312,18 +632,47 @@ void DSi_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:
+ MCUAddr = val;
+ return;
+ case 0x0990:
+ case 0x0992:
+ case 0x0994:
+ case 0x0996:
+ case 0x0998:
+ case 0x099A:
+ case 0x099C:
+ case 0x099E:
+ addr -= 0x0990;
+ MCU_Write((MCUAddr & 0x7FFF) + addr, val&0xFF);
+ if (!(MCUAddr & (1<<15)))
+ MCU_Write((MCUAddr & 0x7FFF) + addr+1, val>>8);
return;
}
@@ -331,117 +680,122 @@ void DSi_Camera::I2C_WriteReg(u16 addr, u16 val)
}
-u8 DSi_Camera::Read8(u32 addr)
+// TODO: not sure at all what is the accessible range
+// or if there is any overlap in the address range
+
+u8 Camera::MCU_Read(u16 addr)
{
- //
+ addr &= 0x7FFF;
- printf("unknown DSi cam read8 %08X\n", addr);
- return 0;
+ return MCURegs[addr];
}
-u16 DSi_Camera::Read16(u32 addr)
+void Camera::MCU_Write(u16 addr, u8 val)
{
+ addr &= 0x7FFF;
+
switch (addr)
{
- case 0x04004200: return ModuleCnt;
- case 0x04004202: return Cnt;
+ case 0x2103: // SEQ_CMD
+ MCURegs[addr] = 0;
+ if (val == 2) MCURegs[0x2104] = 7; // capture mode
+ else if (val == 1) MCURegs[0x2104] = 3; // preview mode
+ else if (val != 5 && val != 6)
+ printf("CAM%d: atypical SEQ_CMD %04X\n", Num, val);
+ return;
+
+ case 0x2104: // SEQ_STATE, read-only
+ return;
}
- printf("unknown DSi cam read16 %08X\n", addr);
- return 0;
+ MCURegs[addr] = val;
}
-u32 DSi_Camera::Read32(u32 addr)
+
+void Camera::InputFrame(u32* data, int width, int height, bool rgb)
{
- switch (addr)
+ // TODO: double-buffering?
+
+ if (width == 640 && height == 480 && !rgb)
{
- case 0x04004204:
+ memcpy(FrameBuffer, data, (640*480/2)*sizeof(u32));
+ return;
+ }
+
+ if (rgb)
+ {
+ for (int dy = 0; dy < 480; dy++)
{
- // TODO
- return 0xFC00801F;
- /*if (!(Cnt & (1<<15))) return 0; // CHECKME
- u32 ret = *(u32*)&FrameBuffer[TransferPos];
- TransferPos += 4;
- if (TransferPos >= FrameLength) TransferPos = 0;
- dorp += 4;
- //if (dorp >= (256*4*2))
- if (TransferPos == 0)
+ int sy = (dy * height) / 480;
+
+ for (int dx = 0; dx < 640; dx+=2)
{
- dorp = 0;
- Cnt &= ~(1<<4);
- }
- return ret;*/
- }
- }
+ int sx;
- printf("unknown DSi cam read32 %08X\n", addr);
- return 0;
-}
+ sx = (dx * width) / 640;
+ u32 pixel1 = data[sy*width + sx];
-void DSi_Camera::Write8(u32 addr, u8 val)
-{
- //
+ sx = ((dx+1) * width) / 640;
+ u32 pixel2 = data[sy*width + sx];
- printf("unknown DSi cam write8 %08X %02X\n", addr, val);
-}
+ int r1 = (pixel1 >> 16) & 0xFF;
+ int g1 = (pixel1 >> 8) & 0xFF;
+ int b1 = pixel1 & 0xFF;
-void DSi_Camera::Write16(u32 addr, u16 val)
-{
- switch (addr)
- {
- case 0x04004200:
- {
- u16 oldcnt = ModuleCnt;
- ModuleCnt = val;
+ int r2 = (pixel2 >> 16) & 0xFF;
+ int g2 = (pixel2 >> 8) & 0xFF;
+ int b2 = pixel2 & 0xFF;
- if ((ModuleCnt & (1<<1)) && !(oldcnt & (1<<1)))
- {
- // reset shit to zero
- // CHECKME
+ int y1 = ((r1 * 19595) + (g1 * 38470) + (b1 * 7471)) >> 16;
+ int u1 = ((b1 - y1) * 32244) >> 16;
+ int v1 = ((r1 - y1) * 57475) >> 16;
- Cnt = 0;
- }
+ int y2 = ((r2 * 19595) + (g2 * 38470) + (b2 * 7471)) >> 16;
+ int u2 = ((b2 - y2) * 32244) >> 16;
+ int v2 = ((r2 - y2) * 57475) >> 16;
- if ((ModuleCnt & (1<<5)) && !(oldcnt & (1<<5)))
- {
- // TODO: reset I2C??
+ u1 += 128; v1 += 128;
+ u2 += 128; v2 += 128;
+
+ y1 = std::clamp(y1, 0, 255); u1 = std::clamp(u1, 0, 255); v1 = std::clamp(v1, 0, 255);
+ y2 = std::clamp(y2, 0, 255); u2 = std::clamp(u2, 0, 255); v2 = std::clamp(v2, 0, 255);
+
+ // huh
+ u1 = (u1 + u2) >> 1;
+ v1 = (v1 + v2) >> 1;
+
+ FrameBuffer[(dy*640 + dx) / 2] = y1 | (u1 << 8) | (y2 << 16) | (v1 << 24);
}
}
- return;
-
- case 0x04004202:
+ }
+ else
+ {
+ for (int dy = 0; dy < 480; dy++)
{
- // checkme
- u16 oldmask;
- if (Cnt & 0x8000)
- {
- val &= 0x8F20;
- oldmask = 0x601F;
- }
- else
- {
- val &= 0xEF2F;
- oldmask = 0x0010;
- }
+ int sy = (dy * height) / 480;
- Cnt = (Cnt & oldmask) | (val & ~0x0020);
- if (val & (1<<5)) Cnt &= ~(1<<4);
-
- if ((val & (1<<15)) && !(Cnt & (1<<15)))
+ for (int dx = 0; dx < 640; dx+=2)
{
- // start transfer
- //DSi::CheckNDMAs(0, 0x0B);
+ int sx = (dx * width) / 640;
+
+ FrameBuffer[(dy*640 + dx) / 2] = data[(sy*width + sx) / 2];
}
}
- return;
}
+}
- printf("unknown DSi cam write16 %08X %04X\n", addr, val);
}
-void DSi_Camera::Write32(u32 addr, u32 val)
-{
- //
- printf("unknown DSi cam write32 %08X %08X\n", addr, val);
-}
+
+
+
+
+
+
+
+
+
+
+
+