110 lines
3.5 KiB
C#
110 lines
3.5 KiB
C#
using System;
|
|
using static Util;
|
|
|
|
namespace OptimeGBA
|
|
{
|
|
public enum SpiFlashState
|
|
{
|
|
Ready,
|
|
Identification,
|
|
ReceiveAddress,
|
|
Reading,
|
|
Status,
|
|
TakePrefix, // For cartridges with IR and Flash
|
|
}
|
|
|
|
public unsafe sealed class SpiFlash
|
|
{
|
|
public byte[] Data;
|
|
|
|
public SpiFlash(byte[] data) {
|
|
Data = data;
|
|
}
|
|
|
|
// Firmware flash state
|
|
public SpiFlashState FlashState;
|
|
public bool EnableWrite;
|
|
public byte IdIndex;
|
|
public uint Address;
|
|
public byte AddressByteNum = 0;
|
|
|
|
// From Nocash's original DS
|
|
byte[] Id = new byte[] { 0x20, 0x40, 0x12 };
|
|
|
|
public byte OutData;
|
|
|
|
public byte TransferTo(byte val, bool transferSize)
|
|
{
|
|
switch (FlashState)
|
|
{
|
|
case SpiFlashState.Ready:
|
|
// Console.WriteLine("SPI: Receive command! " + Hex(val, 2));
|
|
OutData = 0x00;
|
|
switch (val)
|
|
{
|
|
case 0x06:
|
|
EnableWrite = true;
|
|
break;
|
|
case 0x04:
|
|
EnableWrite = false;
|
|
break;
|
|
case 0x9F:
|
|
FlashState = SpiFlashState.Identification;
|
|
IdIndex = 0;
|
|
break;
|
|
case 0x03:
|
|
FlashState = SpiFlashState.ReceiveAddress;
|
|
Address = 0;
|
|
AddressByteNum = 0;
|
|
break;
|
|
case 0x05: // Identification
|
|
// Console.WriteLine("SPI ID");
|
|
OutData = 0x00;
|
|
break;
|
|
case 0x00:
|
|
break;
|
|
default:
|
|
throw new NotImplementedException("SPI: Unimplemented command: " + Hex(val, 2));
|
|
}
|
|
break;
|
|
case SpiFlashState.ReceiveAddress:
|
|
// Console.WriteLine("SPI: Address byte write: " + Hex(val, 2));
|
|
Address |= (uint)(val << ((2 - AddressByteNum) * 8));
|
|
AddressByteNum++;
|
|
if (AddressByteNum > 2)
|
|
{
|
|
AddressByteNum = 0;
|
|
FlashState = SpiFlashState.Reading;
|
|
// Console.WriteLine("SPI: Address written: " + Hex(Address, 6));
|
|
}
|
|
break;
|
|
case SpiFlashState.Reading:
|
|
// Console.WriteLine("SPI: Read from address: " + Hex(Address, 6));
|
|
// Nds7.Cpu.Error("SPI");
|
|
if (Address < 0x40000)
|
|
{
|
|
OutData = Data[Address];
|
|
}
|
|
else
|
|
{
|
|
OutData = 0;
|
|
}
|
|
Address += transferSize ? 2U : 1U;
|
|
Address &= 0xFFFFFF;
|
|
break;
|
|
case SpiFlashState.Identification:
|
|
OutData = Id[IdIndex];
|
|
IdIndex++;
|
|
IdIndex %= 3;
|
|
break;
|
|
}
|
|
|
|
return OutData;
|
|
}
|
|
|
|
public void Deselect()
|
|
{
|
|
FlashState = SpiFlashState.Ready;
|
|
}
|
|
}
|
|
} |