#include <stdint.h>
#include "gba.h"
#include "mem.h"

unsigned char eeprom[65536*2];
int flashstat=1;
unsigned char flashcommand;
int flasherase;
unsigned char flashbank=0;

void writeflash(unsigned long addr, unsigned char val)
{
//        printf("Write flash %08X %02X\n",addr,val);
        if (flashstat==6 && !(addr&0xFFFF))
        {
                flashbank=val;
                flashstat=0;
                return;
        }
        if (flashstat==5)
        {
//                printf("Change EEPROM f!\n");
                eeprom[(addr&0xFFFF)|(flashbank<<16)]=val;
                savechange=1;
                flashstat=0;
                return;
        }
        switch (addr)
        {
                case 0xE005555:
                if (val==0xAA) flashstat=1;
                if (val==0xF0) flashstat=0;
                if (flashstat==2)
                {
                        flashcommand=val;
//                        printf("Start flash command %02X\n",val);
                        switch (val)
                        {
                                case 0x10: /*Erase whole chip*/
                                if (!flasherase) return;
//                printf("Change EEPROM f1!\n");
//                                printf("Erasing whole chip!!\n");
                                memset(eeprom,0,65536);
                                flashstat=4;
                                savechange=1;
                                break;
                                case 0x90: /*ID*/
                                flashstat=3;
                                break;
                                case 0x80: /*ERASE!!*/
                                flasherase=1;
                                flashstat=0; /*We must wait for another command before erasing*/
                                return;
                                case 0xA0: /*Write single byte*/
                                flashstat=5;
                                break;
                                case 0xB0: /*Select bank*/
                                flashstat=6;
                                break;
                                
                                default:
                                printf("Bad flash command!\n");
                                dumpregs();
                                exit(-1);
                        }
                        flasherase=0;
                }
                return;
                case 0xE002AAA:
                if (val==0x55 && flashstat==1) flashstat=2;
                return;
        }
        if (flasherase && flashstat==2 && !(addr&0xFFF) && val==0x30)
        {
//                printf("Change EEPROM f2!\n");
//                printf("Erasing sector!\n");
                memset(eeprom+(addr&0xF000)+(flashbank<<16),0,4096);
                savechange=1;
                flasherase=0;
                flashstat=4;
                return;
        }
        flashstat=0;
}

unsigned char readflash(unsigned long addr)
{
        if (flashstat==3)
        {
                switch (flashcommand)
                {
                        case 0x90: /*ID*/
                        if (flashsize)
                        {
                                if (addr==0xE000000)
                                {
                                        printf("Read ID C2\n");
                                        return 0xC2;
                                }
                                if (addr==0xE000001)
                                {
                                        printf("Read ID 09\n");
                                        return 0x09;
                                }
                        }
                        else
                        {
                                if (addr==0xE000000)
                                {
                                        printf("Read ID C2\n");
                                        return 0xC2;
                                }
                                if (addr==0xE000001)
                                {
                                        printf("Read ID 1C\n");
                                        return 0x1C;
                                }
                        }
//                        printf("Read ID bad %08X\n",addr);
                        return 0;
                }
        }
        if (flashstat==4 && !(addr&0xFFF)) return 0xFF;
//        printf("Normal read\n");
        return eeprom[(addr&0xFFFF)|(flashbank<<16)];
}
