2017-02-07 21:23:46 +00:00
|
|
|
/*
|
|
|
|
Copyright 2016-2017 StapleButter
|
|
|
|
|
|
|
|
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 <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "NDS.h"
|
|
|
|
#include "GPU.h"
|
2017-02-07 21:41:33 +00:00
|
|
|
#include "FIFO.h"
|
2017-02-07 21:23:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace GPU3D
|
|
|
|
{
|
|
|
|
|
2017-02-07 22:31:21 +00:00
|
|
|
const u32 CmdNumParams[256] =
|
|
|
|
{
|
|
|
|
// 0x00
|
|
|
|
0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
// 0x10
|
|
|
|
1, 0, 1, 1, 1, 0, 16, 12, 16, 12, 9, 3, 3,
|
|
|
|
0, 0, 0,
|
|
|
|
// 0x20
|
|
|
|
1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
// 0x30
|
|
|
|
1, 1, 1, 1, 32,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
// 0x40
|
|
|
|
1, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
// 0x50
|
|
|
|
1,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
// 0x60
|
|
|
|
1,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
// 0x70
|
|
|
|
3, 2, 1,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
// 0x80+
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
|
2017-02-07 21:41:33 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
u8 Command;
|
|
|
|
u32 Param;
|
|
|
|
|
|
|
|
} CmdFIFOEntry;
|
|
|
|
|
|
|
|
FIFO<CmdFIFOEntry>* CmdFIFO;
|
|
|
|
FIFO<CmdFIFOEntry>* CmdPIPE;
|
|
|
|
|
2017-02-07 22:31:21 +00:00
|
|
|
u32 NumCommands, CurCommand, ParamCount, TotalParams;
|
|
|
|
|
|
|
|
u32 GXStat;
|
|
|
|
|
2017-02-07 21:41:33 +00:00
|
|
|
|
2017-02-07 21:23:46 +00:00
|
|
|
bool Init()
|
|
|
|
{
|
2017-02-07 21:41:33 +00:00
|
|
|
CmdFIFO = new FIFO<CmdFIFOEntry>(256);
|
|
|
|
CmdPIPE = new FIFO<CmdFIFOEntry>(4);
|
|
|
|
|
2017-02-07 21:23:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeInit()
|
|
|
|
{
|
2017-02-07 21:41:33 +00:00
|
|
|
delete CmdFIFO;
|
|
|
|
delete CmdPIPE;
|
2017-02-07 21:23:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Reset()
|
|
|
|
{
|
2017-02-07 21:41:33 +00:00
|
|
|
CmdFIFO->Clear();
|
|
|
|
CmdPIPE->Clear();
|
2017-02-07 22:31:21 +00:00
|
|
|
|
|
|
|
NumCommands = 0;
|
|
|
|
CurCommand = 0;
|
|
|
|
ParamCount = 0;
|
|
|
|
TotalParams = 0;
|
|
|
|
|
|
|
|
GXStat = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CmdFIFOWrite(CmdFIFOEntry entry)
|
|
|
|
{
|
|
|
|
printf("GX FIFO: %02X %08X\n", entry.Command, entry.Param);
|
|
|
|
|
|
|
|
if (CmdFIFO->IsEmpty() && !CmdPIPE->IsFull())
|
|
|
|
{
|
|
|
|
CmdPIPE->Write(entry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (CmdFIFO->IsFull())
|
|
|
|
{
|
|
|
|
printf("!!! GX FIFO FULL\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CmdFIFO->Write(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CmdFIFOEntry CmdFIFORead()
|
|
|
|
{
|
|
|
|
CmdFIFOEntry ret = CmdPIPE->Read();
|
|
|
|
|
|
|
|
if (CmdPIPE->Level() <= 2)
|
|
|
|
{
|
|
|
|
if (!CmdFIFO->IsEmpty())
|
|
|
|
CmdPIPE->Write(CmdFIFO->Read());
|
|
|
|
if (!CmdFIFO->IsEmpty())
|
|
|
|
CmdPIPE->Write(CmdFIFO->Read());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
u8 Read8(u32 addr)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 Read16(u32 addr)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 Read32(u32 addr)
|
|
|
|
{
|
|
|
|
switch (addr)
|
|
|
|
{
|
|
|
|
case 0x04000320:
|
|
|
|
return 46; // TODO, eventually
|
|
|
|
|
|
|
|
case 0x04000600:
|
|
|
|
{
|
|
|
|
u32 fifolevel = CmdFIFO->Level();
|
|
|
|
|
|
|
|
return GXStat |
|
|
|
|
// matrix stack levels, TODO
|
|
|
|
(fifolevel << 16) |
|
|
|
|
(fifolevel < 128 ? (1<<25) : 0) |
|
|
|
|
(fifolevel == 0 ? (1<<26) : 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Write8(u32 addr, u8 val)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
|
|
|
void Write16(u32 addr, u16 val)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
|
|
|
void Write32(u32 addr, u32 val)
|
|
|
|
{
|
|
|
|
switch (addr)
|
|
|
|
{
|
|
|
|
case 0x04000600:
|
|
|
|
if (val & 0x8000) GXStat &= ~0x8000;
|
|
|
|
val &= 0xC0000000;
|
|
|
|
GXStat &= 0x3FFFFFFF;
|
|
|
|
GXStat |= val;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addr >= 0x04000400 && addr < 0x04000440)
|
|
|
|
{
|
|
|
|
if (NumCommands == 0)
|
|
|
|
{
|
|
|
|
NumCommands = 4;
|
|
|
|
CurCommand = val;
|
|
|
|
ParamCount = 0;
|
|
|
|
TotalParams = CmdNumParams[CurCommand & 0xFF];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ParamCount++;
|
|
|
|
|
|
|
|
while (ParamCount == TotalParams)
|
|
|
|
{
|
|
|
|
CmdFIFOEntry entry;
|
|
|
|
entry.Command = CurCommand & 0xFF;
|
|
|
|
entry.Param = val;
|
|
|
|
CmdFIFOWrite(entry);
|
|
|
|
|
|
|
|
CurCommand >>= 8;
|
|
|
|
NumCommands--;
|
|
|
|
if (NumCommands == 0) break;
|
|
|
|
|
|
|
|
ParamCount = 0;
|
|
|
|
TotalParams = CmdNumParams[CurCommand & 0xFF];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addr >= 0x04000440 && addr < 0x040005CC)
|
|
|
|
{
|
|
|
|
CmdFIFOEntry entry;
|
|
|
|
entry.Command = (addr & 0x1FC) >> 2;
|
|
|
|
entry.Param = val;
|
|
|
|
CmdFIFOWrite(entry);
|
|
|
|
return;
|
|
|
|
}
|
2017-02-07 21:23:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|