mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-27 00:00:07 -06:00
camera: model FIFO more accurately (avoids weird bugs when DMA fails)
This commit is contained in:
@ -67,9 +67,7 @@ void DSi_CamModule::Reset()
|
|||||||
CropStart = 0;
|
CropStart = 0;
|
||||||
CropEnd = 0;
|
CropEnd = 0;
|
||||||
|
|
||||||
memset(DataBuffer, 0, 512*sizeof(u32));
|
DataBuffer.Clear();
|
||||||
BufferReadPos = 0;
|
|
||||||
BufferWritePos = 0;
|
|
||||||
BufferNumLines = 0;
|
BufferNumLines = 0;
|
||||||
CurCamera = nullptr;
|
CurCamera = nullptr;
|
||||||
|
|
||||||
@ -89,6 +87,8 @@ void DSi_CamModule::DoSavestate(Savestate* file)
|
|||||||
file->Var16(&ModuleCnt);
|
file->Var16(&ModuleCnt);
|
||||||
file->Var16(&Cnt);
|
file->Var16(&Cnt);
|
||||||
|
|
||||||
|
// TODO: should other stuff be savestated? (pixel buffer, etc)
|
||||||
|
|
||||||
/*file->VarArray(FrameBuffer, sizeof(FrameBuffer));
|
/*file->VarArray(FrameBuffer, sizeof(FrameBuffer));
|
||||||
file->Var32(&TransferPos);
|
file->Var32(&TransferPos);
|
||||||
file->Var32(&FrameLength);*/
|
file->Var32(&FrameLength);*/
|
||||||
@ -113,8 +113,6 @@ void DSi_CamModule::IRQ(u32 param)
|
|||||||
|
|
||||||
if (Cnt & (1<<15))
|
if (Cnt & (1<<15))
|
||||||
{
|
{
|
||||||
BufferReadPos = 0;
|
|
||||||
BufferWritePos = 0;
|
|
||||||
BufferNumLines = 0;
|
BufferNumLines = 0;
|
||||||
CurCamera = activecam;
|
CurCamera = activecam;
|
||||||
DSi.ScheduleEvent(Event_DSi_CamTransfer, false, kTransferStart, 0, 0);
|
DSi.ScheduleEvent(Event_DSi_CamTransfer, false, kTransferStart, 0, 0);
|
||||||
@ -126,8 +124,10 @@ void DSi_CamModule::IRQ(u32 param)
|
|||||||
|
|
||||||
void DSi_CamModule::TransferScanline(u32 line)
|
void DSi_CamModule::TransferScanline(u32 line)
|
||||||
{
|
{
|
||||||
u32* dstbuf = &DataBuffer[BufferWritePos];
|
if (Cnt & (1<<4))
|
||||||
int maxlen = 512 - BufferWritePos;
|
return;
|
||||||
|
|
||||||
|
int maxlen = DataBuffer.FreeSpace();
|
||||||
|
|
||||||
u32 tmpbuf[512];
|
u32 tmpbuf[512];
|
||||||
int lines_next;
|
int lines_next;
|
||||||
@ -195,28 +195,28 @@ void DSi_CamModule::TransferScanline(u32 line)
|
|||||||
u32 col1 = (r1 >> 3) | ((g1 >> 3) << 5) | ((b1 >> 3) << 10) | 0x8000;
|
u32 col1 = (r1 >> 3) | ((g1 >> 3) << 5) | ((b1 >> 3) << 10) | 0x8000;
|
||||||
u32 col2 = (r2 >> 3) | ((g2 >> 3) << 5) | ((b2 >> 3) << 10) | 0x8000;
|
u32 col2 = (r2 >> 3) | ((g2 >> 3) << 5) | ((b2 >> 3) << 10) | 0x8000;
|
||||||
|
|
||||||
dstbuf[i] = col1 | (col2 << 16);
|
DataBuffer.Write(col1 | (col2 << 16));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// return raw data
|
// return raw data
|
||||||
|
|
||||||
memcpy(dstbuf, &tmpbuf[copystart], copylen*sizeof(u32));
|
for (u32 i = 0; i < copylen; i++)
|
||||||
|
{
|
||||||
|
u32 val = tmpbuf[copystart + i];
|
||||||
|
DataBuffer.Write(val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
numscan = Cnt & 0x000F;
|
numscan = Cnt & 0x000F;
|
||||||
if (BufferNumLines >= numscan)
|
if (BufferNumLines >= numscan)
|
||||||
{
|
{
|
||||||
BufferReadPos = 0; // checkme
|
|
||||||
BufferWritePos = 0;
|
|
||||||
BufferNumLines = 0;
|
BufferNumLines = 0;
|
||||||
DSi.CheckNDMAs(0, 0x0B);
|
DSi.CheckNDMAs(0, 0x0B);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BufferWritePos += copylen;
|
|
||||||
if (BufferWritePos > 512) BufferWritePos = 512;
|
|
||||||
BufferNumLines++;
|
BufferNumLines++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,10 +225,9 @@ skip_line:
|
|||||||
{
|
{
|
||||||
// when the frame is finished, transfer any remaining data if needed
|
// when the frame is finished, transfer any remaining data if needed
|
||||||
// (if the frame height isn't a multiple of the DMA interval)
|
// (if the frame height isn't a multiple of the DMA interval)
|
||||||
|
// (TODO: should it be done earlier?)
|
||||||
if (BufferNumLines > 0)
|
if (BufferNumLines > 0)
|
||||||
{
|
{
|
||||||
BufferReadPos = 0;
|
|
||||||
BufferWritePos = 0;
|
|
||||||
BufferNumLines = 0;
|
BufferNumLines = 0;
|
||||||
DSi.CheckNDMAs(0, 0x0B);
|
DSi.CheckNDMAs(0, 0x0B);
|
||||||
}
|
}
|
||||||
@ -266,14 +265,19 @@ u32 DSi_CamModule::Read32(u32 addr)
|
|||||||
{
|
{
|
||||||
case 0x04004204:
|
case 0x04004204:
|
||||||
{
|
{
|
||||||
u32 ret = DataBuffer[BufferReadPos];
|
u32 ret;
|
||||||
if (Cnt & (1<<15))
|
if (Cnt & (1<<15))
|
||||||
{
|
{
|
||||||
if (BufferReadPos < 511)
|
if (DataBuffer.IsEmpty())
|
||||||
BufferReadPos++;
|
{
|
||||||
// CHECKME!!!!
|
ret = 0;
|
||||||
// also presumably we should set bit4 in Cnt if there's no new data to be read
|
Cnt |= (1<<4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = DataBuffer.Read();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ret = DataBuffer.Peek();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -339,8 +343,7 @@ void DSi_CamModule::Write16(u32 addr, u16 val)
|
|||||||
if (val & (1<<5))
|
if (val & (1<<5))
|
||||||
{
|
{
|
||||||
Cnt &= ~(1<<4);
|
Cnt &= ~(1<<4);
|
||||||
BufferReadPos = 0;
|
DataBuffer.Clear();
|
||||||
BufferWritePos = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((val & (1<<15)) && !(Cnt & (1<<15)))
|
if ((val & (1<<15)) && !(Cnt & (1<<15)))
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "Savestate.h"
|
#include "Savestate.h"
|
||||||
#include "DSi_I2C.h"
|
#include "DSi_I2C.h"
|
||||||
|
#include "FIFO.h"
|
||||||
|
|
||||||
namespace melonDS
|
namespace melonDS
|
||||||
{
|
{
|
||||||
@ -119,8 +120,7 @@ private:
|
|||||||
u32 CropStart, CropEnd;
|
u32 CropStart, CropEnd;
|
||||||
|
|
||||||
// pixel data buffer holds a maximum of 512 words, regardless of how long scanlines are
|
// pixel data buffer holds a maximum of 512 words, regardless of how long scanlines are
|
||||||
u32 DataBuffer[512];
|
FIFO<u32, 512> DataBuffer;
|
||||||
u32 BufferReadPos, BufferWritePos;
|
|
||||||
u32 BufferNumLines;
|
u32 BufferNumLines;
|
||||||
DSi_Camera* CurCamera;
|
DSi_Camera* CurCamera;
|
||||||
|
|
||||||
|
@ -90,6 +90,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 Level() const { return NumOccupied; }
|
u32 Level() const { return NumOccupied; }
|
||||||
|
u32 FreeSpace() const { return NumEntries - NumOccupied; }
|
||||||
bool IsEmpty() const { return NumOccupied == 0; }
|
bool IsEmpty() const { return NumOccupied == 0; }
|
||||||
bool IsFull() const { return NumOccupied >= NumEntries; }
|
bool IsFull() const { return NumOccupied >= NumEntries; }
|
||||||
|
|
||||||
|
@ -979,7 +979,7 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
|
|||||||
if (event->isAutoRepeat()) return;
|
if (event->isAutoRepeat()) return;
|
||||||
|
|
||||||
// TODO!! REMOVE ME IN RELEASE BUILDS!!
|
// TODO!! REMOVE ME IN RELEASE BUILDS!!
|
||||||
//if (event->key() == Qt::Key_F11) emuThread->NDS->debug(0);
|
//if (event->key() == Qt::Key_F11) emuInstance->getNDS()->debug(0);
|
||||||
|
|
||||||
emuInstance->onKeyPress(event);
|
emuInstance->onKeyPress(event);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user