mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 21:37:42 -07:00
159 lines
2.2 KiB
C++
159 lines
2.2 KiB
C++
|
#include <stdio.h>
|
||
|
#include "NDS.h"
|
||
|
#include "SPI.h"
|
||
|
|
||
|
|
||
|
namespace SPI_Firmware
|
||
|
{
|
||
|
|
||
|
u8* Firmware;
|
||
|
u32 FirmwareLength;
|
||
|
|
||
|
u32 Hold;
|
||
|
u8 CurCmd;
|
||
|
u32 DataPos;
|
||
|
u8 Data;
|
||
|
|
||
|
u32 Addr;
|
||
|
|
||
|
void Init()
|
||
|
{
|
||
|
Firmware = NULL;
|
||
|
}
|
||
|
|
||
|
void Reset()
|
||
|
{
|
||
|
if (Firmware) delete[] Firmware;
|
||
|
|
||
|
FILE* f = fopen("firmware.bin", "rb");
|
||
|
fseek(f, 0, SEEK_END);
|
||
|
FirmwareLength = (u32)ftell(f);
|
||
|
Firmware = new u8[FirmwareLength];
|
||
|
|
||
|
fseek(f, 0, SEEK_SET);
|
||
|
fread(Firmware, FirmwareLength, 1, f);
|
||
|
|
||
|
fclose(f);
|
||
|
|
||
|
Hold = 0;
|
||
|
CurCmd = 0;
|
||
|
Data = 0;
|
||
|
}
|
||
|
|
||
|
u8 Read()
|
||
|
{
|
||
|
return Data;
|
||
|
}
|
||
|
|
||
|
void Write(u8 val, u32 hold)
|
||
|
{
|
||
|
if (!hold)
|
||
|
{
|
||
|
Hold = 0;
|
||
|
}
|
||
|
|
||
|
if (hold && (!Hold))
|
||
|
{
|
||
|
CurCmd = val;
|
||
|
Hold = 1;
|
||
|
DataPos = 1;
|
||
|
Addr = 0;
|
||
|
printf("firmware SPI command %02X\n", CurCmd);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
switch (CurCmd)
|
||
|
{
|
||
|
case 0x03: // read
|
||
|
{
|
||
|
if (DataPos < 4)
|
||
|
{
|
||
|
Addr <<= 8;
|
||
|
Addr |= val;
|
||
|
Data = 0;
|
||
|
|
||
|
if (DataPos == 3) printf("firmware SPI read %08X\n", Addr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (Addr >= FirmwareLength)
|
||
|
Data = 0;
|
||
|
else
|
||
|
Data = Firmware[Addr];
|
||
|
|
||
|
Addr++;
|
||
|
}
|
||
|
|
||
|
DataPos++;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
printf("unknown firmware SPI command %02X\n", CurCmd);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
namespace SPI
|
||
|
{
|
||
|
|
||
|
u16 CNT;
|
||
|
|
||
|
u32 CurDevice;
|
||
|
|
||
|
|
||
|
void Init()
|
||
|
{
|
||
|
SPI_Firmware::Init();
|
||
|
}
|
||
|
|
||
|
void Reset()
|
||
|
{
|
||
|
CNT = 0;
|
||
|
|
||
|
SPI_Firmware::Reset();
|
||
|
}
|
||
|
|
||
|
|
||
|
u16 ReadCnt()
|
||
|
{
|
||
|
return CNT;
|
||
|
}
|
||
|
|
||
|
void WriteCnt(u16 val)
|
||
|
{
|
||
|
CNT = val & 0xCF03;
|
||
|
if (val & 0x0400) printf("!! CRAPOED 16BIT SPI MODE\n");
|
||
|
}
|
||
|
|
||
|
u8 ReadData()
|
||
|
{
|
||
|
if (!(CNT & (1<<15))) return 0;
|
||
|
|
||
|
switch (CNT & 0x0300)
|
||
|
{
|
||
|
case 0x0100: return SPI_Firmware::Read();
|
||
|
default: return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void WriteData(u8 val)
|
||
|
{
|
||
|
if (!(CNT & (1<<15))) return;
|
||
|
|
||
|
// TODO: take delays into account
|
||
|
|
||
|
switch (CNT & 0x0300)
|
||
|
{
|
||
|
case 0x0100: SPI_Firmware::Write(val, CNT&(1<<11)); break;
|
||
|
}
|
||
|
|
||
|
if (CNT & (1<<14))
|
||
|
NDS::TriggerIRQ(1, NDS::IRQ_SPI);
|
||
|
}
|
||
|
|
||
|
}
|