/*
 * ASCD : copyright (c) Aley Keprt 1998-2012
 *
 * File fux.cpp - .fux file handling (Fuxoft emulator snapshots)
 *
    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This library 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 */


#include <stdio.h>
#include "zlib.h"

#include "z80cpu/z80.h"
#include "z80_snap.h"
#include "memory.h"


typedef struct {
  BYTE res,i;
  BYTE iffpv,r;
  BYTE iy[2],ix[2],hl1[2],de1[2],bc1[2],f1,a1;
  BYTE hl[2],de[2],bc[2],sp[2];
} FUX_header;

//-----------------------------------------------------------------------------------

static int load_fux_internal(gzFile &f) {
//
//internal function
//load .fux snapshot
//
//return: error flag
//
  FUX_header hdr;

  if(gzread(f,&hdr,24)!=24) return -1; //error

  Z80_Regs r;
  memset(&r, 0, sizeof(r));

  //initialize registers
  #define mw(reg) (r.reg = hdr.reg[0] + hdr.reg[1]*256)
  #define mb(h,l,hl) (r.h = hdr.hl[1], r.l=hdr.hl[0])

  mb(b,c,bc);
  mb(d,e,de);
  mb(h,l,hl);

  mw(ix);
  mw(iy);
  mw(sp);

  r.a1=hdr.a1;
  r.f1=hdr.f1;

  mb(b1,c1,bc1);
  mb(d1,e1,de1);
  mb(h1,l1,hl1);

  #undef mw
  #undef mb

  r.i=hdr.i;
  r.r=hdr.r;

  r.im = (hdr.i<0x40) ? 1 : 2;
  r.iff = hdr.iffpv ? 3 : 0;

  set_emulation_mode(EM_48k);

  //load 48KB body
  if(gzread(f, theWrMemory[1], 16384) != 16384) return -1; //error
  if(gzread(f, theWrMemory[2], 16384) != 16384) return -1; //error
  if(gzread(f, theWrMemory[3], 16384) != 16384) return -1; //error

  //initialize ports
  out_byte(BORDER_PORT,0);

  //af and pc are on the stack
  r.f = read_byte(r.sp);
  r.sp++;
  r.a=read_byte(r.sp);
  r.sp++;
  r.pc = read_word(r.sp);
  r.sp += 2;

  //important! NMI routine must be replaced by an empty one!
  memset(theRdMemory[0] + 0x68, 0, 8);

  Z80SetRegs(&r);

  return 0;
}

//-----------------------------------------------------------------------

//Load .fux snapshot
//return: error flag
int load_fux(const char *fname) {

  gzFile gzf = gzopen(fname,"rb");
  if(!gzf) return -1;

  int r = load_fux_internal(gzf);
  gzclose(gzf);
  return r; //return error flag
}
