
#include "PicoInt.h"

int PicoVer=0x0022;
struct Pico Pico;

int PicoPad[2]; // Joypads, format is SACB RLDU

int PicoInit()
{
  // Blank space for state:
  memset(&Pico,0,sizeof(Pico));
  memset(&PicoPad,0,sizeof(PicoPad));
  Pico.m.dirtyPal=1;

  // Init CPU:
  SekInit();

  // Setup memory callbacks:
  PicoMemInit();
  SoundReset();
  return 0;
}

void PicoExit()
{
  memset(&Pico,0,sizeof(struct Pico));
}

int PicoReset()
{
  unsigned int region=0;
  int support=0,hw=0,i=0;
  unsigned char pal=0;

  SekReset();
  SoundReset();

  // Read cartridge region data:
  region=PicoRead32(0x1f0);

  for (i=0;i<4;i++)
  {
    int c=0;
    
    c=region>>(i<<3); c&=0xff;
    if (c<=' ') continue;

         if (c=='J') support|=1;
    else if (c=='U') support|=4;
    else if (c=='E') support|=8;
    else
    {
      // New style code:
      char s[2]={0,0};
      s[0]=(char)c;
      support|=strtol(s,NULL,16);
    }

  }

  // Try to pick the best hardware value for English/60hz:
       if (support&4)   hw=0x80;          // USA
  else if (support&8) { hw=0xc0; pal=1; } // Europe
  else if (support&1)   hw=0x00;          // Japan NTSC
  else if (support&2) { hw=0x40; pal=1; } // Japan PAL
  else hw=0x80; // USA

  Pico.m.hardware=(unsigned char)(hw|0x20); // No disk attached
  Pico.m.pal=pal;

  return 0;
}

// Accurate but slower frame which does hints
static int PicoFrameHints()
{
  int total=0,aim=0;
  int y=0;
  int hint=0x400; // Hint counter

  if (Pico.video.reg[1]&0x20) SekInterrupt(6); // V-Int
  Pico.video.status|=0x88; // V-Int happened / go into vblank

  for (y=-38;y<224;y++)
  {
    if (PicoScan && y>=0) PicoLine(y);

    if (y==0)
    {
      // Come out of vblank if display is enabled
      if (Pico.video.reg[1]&0x40) Pico.video.status&=~8;
    }

    // Handle H-Interrupts:
    if (hint<=0 && Pico.video.reg[0]&0x10) SekInterrupt(4); // H-Int
    if (y<=0 || hint<=0) hint=Pico.video.reg[10]+1; // Reload H-Int counter

    Pico.m.scanline=(short)y;
    aim+=489; total+=SekRun(aim-total); // Run scanline
    hint--;
  }

  SekInterrupt(0); // Cancel interrupt

  return 0;
}

int PicoFrame()
{
  int total=0,y=0;
  
  if (Pico.rom==NULL) return 1; // No Rom plugged in

  if (Pico.video.reg[0]&0x10) return PicoFrameHints();

  Pico.m.scanline=-64;

  // V-Blanking period:
  if (Pico.video.reg[1]&0x20) SekInterrupt(6); // Set IRQ
  Pico.video.status|=0x88; // V-Int happened / go into vblank
  total+=SekRun(18560);

  // Active Scan:
  if (Pico.video.reg[1]&0x40) Pico.video.status&=~8; // Come out of vblank if display is enabled
  SekInterrupt(0); // Clear IRQ
  total+=SekRun(127969-total);

  SoundRender();

  if (PicoScan)
  {
    // Draw the screen
    for (y=0;y<224;y++) PicoLine(y);
  }

  return 0;
}
