/* 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 #include #include "NDS.h" #include "GPU.h" #include "FIFO.h" namespace GPU3D { 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 }; typedef struct { u8 Command; u32 Param; } CmdFIFOEntry; FIFO* CmdFIFO; FIFO* CmdPIPE; u32 NumCommands, CurCommand, ParamCount, TotalParams; u32 GXStat; bool Init() { CmdFIFO = new FIFO(256); CmdPIPE = new FIFO(4); return true; } void DeInit() { delete CmdFIFO; delete CmdPIPE; } void Reset() { CmdFIFO->Clear(); CmdPIPE->Clear(); 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; } } }