/*
 * Copyright (c) Des Herriott 1993, 1994
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of the copyright holder not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  The copyright holder makes no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
 * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * Author: Des Herriott
 */

/*
 * Header file z80.h - defines the processor and its regiesters.
 * Also declares some common functions.
 */

/* make sure that one and only one source file #define's MAIN */
#ifdef Z80_MAIN
#define Global
#else
#define Global extern
#endif

/* Make sure that the unsigned short type on this machine is 16 bits */
/* or the moon will explode */
typedef unsigned short uns16;
typedef unsigned char  uns8;
typedef signed short   sgn16;
typedef signed char    sgn8;
typedef unsigned int   uns32;
typedef signed int     sgn32;

/* Pointer to void function */
typedef void (*PFV)();

/* The definition of the z80 chip & its registers */
struct z80 {
	uns16 af_pair, bc_pair, de_pair, hl_pair;
	uns16 af_alt,  bc_alt,  de_alt,  hl_alt;
	uns16 ix_reg,  iy_reg;
	uns16 sp_reg;
	uns16 pc_reg;
	uns8  refresh, int_vec;
	uns8  im;
	uns8  iff1, iff2;
};

Global struct z80 *theProcessor;
Global uns8 *theMemory, *inPorts, *outPorts;

/* A bunch of aliases for the registers. */
Global uns16 *af, *hl, *bc, *de;
Global uns16 *sp, *pc, *ix, *iy;
Global uns8 *a, *f, *h, *l;
Global uns8 *b, *c, *d, *e;
Global uns8 *pc_low, *pc_high;

/* Declare each flag as an int, since integer arithmetic is
 * faster than bit-shuffling.
 */
Global int carryFlag,  addsubFlag, par_overFlag;
Global int hcarryFlag, zeroFlag,   signFlag;


/* A few useful macros... */
#define GetNextOp   theMemory[(*pc)++]
#if 1
#define GetNext2Ops (*pc += 2, \
  (uns16)theMemory[(uns16)(*pc-2)] + ((uns16)theMemory[(uns16)(*pc-1)] << 8))
#define PopValue    (*sp += 2, \
  (uns16)theMemory[(uns16)(*sp-2)] + ((uns16)theMemory[(uns16)(*sp-1)] << 8))
#define PushValue(reg) (*sp -= 2, \
  mem_write(*sp,(reg)&0xff), mem_write((*sp)+1,(reg)>>8))
  /* theMemory[*sp] = (reg) & 0xff, theMemory[(*sp)+1] = (reg) >> 8) */
#else
#define PopValue ((uns16) (theMemory[(*sp)++] + (theMemory[(*sp)++] << 8)))
#define GetNext2Ops ((uns16) (theMemory[(*pc)++] + (theMemory[(*pc)++] << 8)))
#define PushValue(reg) mem_write(--(*sp), (uns8) (reg / 256)) ; \
						mem_write(--(*sp), (uns8) (reg % 256))
#endif

/* Constants used to bit-mask the F register */
#define F_CARRY		0x01
#define F_NADD		0x02	/* For BCD. */
#define F_PARITY	0x04
#define F_OVERFLOW	0x04
#define F_HCARRY	0x10	/* For BCD. */
#define F_ZERO		0x40
#define F_NEG		0x80

/* Macros for setting, clearing, testing and complementing flags */
#define Set(flag) flag=1
#define Clr(flag) flag=0
#define Tst(flag) flag
#define Cpl(flag) flag=!(flag)

/* An interrupt occurs every I_INTERVAL instructions */
#define I_INTERVAL 7800

#define MEM_SIZE 65536
#define IN_SIZE 256
#define OUT_SIZE 256


#ifdef ZXSPEC

/* Default ROM name */
#define ROM_NAME "spectrum.rom"

/* From spectrum.c */
uns8 in_byte(uns16 port);
void out_byte(uns16 port, uns8 val);
void refesh_screen(void);
void screen_write(uns16 addr, uns8 val);
void attr_write(uns16 addr, uns8 val);
void do_flashing(void);

#endif

#ifdef NEED_STRCASECMP
int strcasecmp(char *s1, char *s2);
int strncasecmp(char *s1, char *s2, int n);
#endif
