implement some obscure DMA types
This commit is contained in:
parent
a56bf5c76c
commit
2150240cbd
20
src/DMA.cpp
20
src/DMA.cpp
|
@ -20,7 +20,7 @@
|
|||
#include "NDS.h"
|
||||
#include "DMA.h"
|
||||
#include "NDSCart.h"
|
||||
#include "GPU3D.h"
|
||||
#include "GPU.h"
|
||||
|
||||
|
||||
// NOTES ON DMA SHIT
|
||||
|
@ -153,8 +153,8 @@ void DMA::WriteCnt(u32 val)
|
|||
else if (StartMode == 0x07)
|
||||
GPU3D::CheckFIFODMA();
|
||||
|
||||
if (StartMode==0x04 || StartMode==0x06 || StartMode==0x13)
|
||||
printf("UNIMPLEMENTED ARM%d DMA%d START MODE %02X\n", CPU?7:9, Num, StartMode);
|
||||
if (StartMode==0x06 || StartMode==0x13)
|
||||
printf("UNIMPLEMENTED ARM%d DMA%d START MODE %02X, %08X->%08X\n", CPU?7:9, Num, StartMode, SrcAddr, DstAddr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,6 +194,20 @@ void DMA::Start()
|
|||
return;
|
||||
}
|
||||
|
||||
// special path for the display FIFO. another gross hack.
|
||||
// the display FIFO seems to be more like a circular buffer that holds 16 pixels
|
||||
// from which the display controller reads. DMA is triggered every 8 pixels to fill it
|
||||
// as it is being read from. emulating it properly would be resource intensive.
|
||||
// proper emulation would only matter if something is trying to feed the FIFO manually
|
||||
// instead of using the DMA. which is probably never happening. the only thing I know of
|
||||
// that even uses the display FIFO is the aging cart.
|
||||
if (StartMode == 0x04)
|
||||
{
|
||||
GPU::GPU2D_A->FIFODMA(CurSrcAddr);
|
||||
CurSrcAddr += 256*2;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO eventually: not stop if we're running code in ITCM
|
||||
|
||||
Running = true;
|
||||
|
|
|
@ -40,6 +40,12 @@ public:
|
|||
Start();
|
||||
}
|
||||
|
||||
void StopIfNeeded(u32 mode)
|
||||
{
|
||||
if (mode == StartMode)
|
||||
Cnt &= ~0x80000000;
|
||||
}
|
||||
|
||||
u32 SrcAddr;
|
||||
u32 DstAddr;
|
||||
u32 Cnt;
|
||||
|
|
22
src/GPU.cpp
22
src/GPU.cpp
|
@ -678,13 +678,23 @@ void StartScanline(u32 line)
|
|||
else
|
||||
DispStat[1] &= ~(1<<2);
|
||||
|
||||
if (line >= 2 && line < 194)
|
||||
NDS::CheckDMAs(0, 0x03);
|
||||
else if (line == 194)
|
||||
NDS::StopDMAs(0, 0x03);
|
||||
|
||||
if (line < 192)
|
||||
{
|
||||
// fill a line from the display FIFO if needed.
|
||||
// this isn't how the real thing works, but emulating it
|
||||
// properly would be too much trouble given barely anything
|
||||
// uses FIFO display
|
||||
// (TODO, eventually: emulate it properly)
|
||||
NDS::CheckDMAs(0, 0x04);
|
||||
|
||||
// draw
|
||||
GPU2D_A->DrawScanline(line);
|
||||
GPU2D_B->DrawScanline(line);
|
||||
|
||||
//NDS::ScheduleEvent(LINE_CYCLES, StartScanline, line+1);
|
||||
}
|
||||
else if (line == 262)
|
||||
{
|
||||
|
@ -701,6 +711,8 @@ void StartScanline(u32 line)
|
|||
DispStat[0] |= (1<<0);
|
||||
DispStat[1] |= (1<<0);
|
||||
|
||||
NDS::StopDMAs(0, 0x04);
|
||||
|
||||
NDS::CheckDMAs(0, 0x01);
|
||||
NDS::CheckDMAs(1, 0x11);
|
||||
|
||||
|
@ -711,14 +723,8 @@ void StartScanline(u32 line)
|
|||
GPU2D_B->VBlank();
|
||||
GPU3D::VBlank();
|
||||
}
|
||||
|
||||
//NDS::ScheduleEvent(LINE_CYCLES, StartScanline, line+1);
|
||||
//NDS::ScheduleEvent(NDS::Event_LCD, true, LINE_CYCLES, StartScanline, line+1);
|
||||
}
|
||||
|
||||
// checkme
|
||||
if (line == 0) NDS::CheckDMAs(0, 0x03);
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_LCD, true, HBLANK_CYCLES, StartHBlank, line);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ void GPU2D::Reset()
|
|||
EVB = 0;
|
||||
EVY = 0;
|
||||
|
||||
memset(DispFIFOBuffer, 0, 256*2);
|
||||
|
||||
CaptureCnt = 0;
|
||||
|
||||
MasterBrightness = 0;
|
||||
|
@ -337,9 +339,17 @@ void GPU2D::DrawScanline(u32 line)
|
|||
}
|
||||
break;
|
||||
|
||||
case 3: // FIFO display
|
||||
case 3: // FIFO display (grossly inaccurate)
|
||||
{
|
||||
// TODO
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
u16 color = DispFIFOBuffer[i];
|
||||
u8 r = (color & 0x001F) << 1;
|
||||
u8 g = (color & 0x03E0) >> 4;
|
||||
u8 b = (color & 0x7C00) >> 9;
|
||||
|
||||
dst[i] = r | (g << 8) | (b << 16);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -445,7 +455,8 @@ void GPU2D::DoCapture(u32 line, u32 width, u32* src)
|
|||
|
||||
if (CaptureCnt & (1<<25))
|
||||
{
|
||||
// TODO: FIFO mode
|
||||
srcB = &DispFIFOBuffer[0];
|
||||
srcBaddr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -570,6 +581,17 @@ void GPU2D::DoCapture(u32 line, u32 width, u32* src)
|
|||
}
|
||||
}
|
||||
|
||||
void GPU2D::FIFODMA(u32 addr)
|
||||
{
|
||||
for (int i = 0; i < 256; i += 2)
|
||||
{
|
||||
u32 val = NDS::ARM9Read32(addr);
|
||||
addr += 4;
|
||||
DispFIFOBuffer[i] = val & 0xFFFF;
|
||||
DispFIFOBuffer[i+1] = val >> 16;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GPU2D::BGExtPalDirty(u32 base)
|
||||
{
|
||||
|
|
|
@ -45,10 +45,14 @@ public:
|
|||
u16* GetBGExtPal(u32 slot, u32 pal);
|
||||
u16* GetOBJExtPal(u32 pal);
|
||||
|
||||
void FIFODMA(u32 addr);
|
||||
|
||||
private:
|
||||
u32 Num;
|
||||
u32* Framebuffer;
|
||||
|
||||
u16 DispFIFOBuffer[256];
|
||||
|
||||
u32 DispCnt;
|
||||
u16 BGCnt[4];
|
||||
|
||||
|
|
|
@ -622,6 +622,15 @@ void CheckDMAs(u32 cpu, u32 mode)
|
|||
DMAs[cpu+3]->StartIfNeeded(mode);
|
||||
}
|
||||
|
||||
void StopDMAs(u32 cpu, u32 mode)
|
||||
{
|
||||
cpu <<= 2;
|
||||
DMAs[cpu+0]->StopIfNeeded(mode);
|
||||
DMAs[cpu+1]->StopIfNeeded(mode);
|
||||
DMAs[cpu+2]->StopIfNeeded(mode);
|
||||
DMAs[cpu+3]->StopIfNeeded(mode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue