Z80.h
  1  /** Z80: portable Z80 emulator *******************************/
  2  /**                                                         **/
  3  /**                           Z80.h                         **/
  4  /**                                                         **/
  5  /** This file contains declarations relevant to emulation   **/
  6  /** of Z80 CPU.                                             **/
  7  /**                                                         **/
  8  /** Copyright (C) Marat Fayzullin 1994-2007                 **/
  9  /**     You are not allowed to distribute this software     **/
 10  /**     commercially. Please, notify me, if you make any    **/
 11  /**     changes to this file.                               **/
 12  /*************************************************************/
 13  #ifndef Z80_H
 14  #define Z80_H
 15  
 16   #include <stdint.h>
 17  
 18  
 19  #define  EXECZ80 // run a few cycles
 20  
 21  #ifdef __cplusplus
 22  extern "C" {
 23  #endif
 24  
 25                                 /* Compilation options:       */
 26  /* #define DEBUG */            /* Compile debugging version  */
 27  #define LSB_FIRST         /* Compile for low-endian CPU */
 28  // #define MSB_FIRST         /* Compile for hi-endian CPU  */
 29  
 30                                 /* LoopZ80() may return:      */
 31  #define INT_RST00   0x00C7     /* RST 00h                    */
 32  #define INT_RST08   0x00CF     /* RST 08h                    */
 33  #define INT_RST10   0x00D7     /* RST 10h                    */
 34  #define INT_RST18   0x00DF     /* RST 18h                    */
 35  #define INT_RST20   0x00E7     /* RST 20h                    */
 36  #define INT_RST28   0x00EF     /* RST 28h                    */
 37  #define INT_RST30   0x00F7     /* RST 30h                    */
 38  #define INT_RST38   0x00FF     /* RST 38h                    */
 39  #define INT_IRQ     INT_RST38  /* Default IRQ opcode is FFh  */
 40  #define INT_NMI     0xFFFD     /* Non-maskable interrupt     */
 41  #define INT_NONE    0xFFFF     /* No interrupt required      */
 42  #define INT_QUIT    0xFFFE     /* Exit the emulation         */
 43  
 44                                 /* Bits in Z80 F register:    */
 45  #define S_FLAG      0x80       /* 1: Result negative         */
 46  #define Z_FLAG      0x40       /* 1: Result is zero          */
 47  #define H_FLAG      0x10       /* 1: Halfcarry/Halfborrow    */
 48  #define P_FLAG      0x04       /* 1: Result is even          */
 49  #define V_FLAG      0x04       /* 1: Overflow occured        */
 50  #define N_FLAG      0x02       /* 1: Subtraction occured     */
 51  #define C_FLAG      0x01       /* 1: Carry/Borrow occured    */
 52  
 53                                 /* Bits in IFF flip-flops:    */
 54  #define IFF_1       0x01       /* IFF1 flip-flop             */
 55  #define IFF_IM1     0x02       /* 1: IM1 mode                */
 56  #define IFF_IM2     0x04       /* 1: IM2 mode                */
 57  #define IFF_2       0x08       /* IFF2 flip-flop             */
 58  #define IFF_EI      0x20       /* 1: EI pending              */
 59  #define IFF_HALT    0x80       /* 1: CPU HALTed              */
 60  
 61  /** Simple Datatypes *****************************************/
 62  /** NOTICE: sizeof(byte)=1 and sizeof(word)=2               **/
 63  /*************************************************************/
 64  #ifndef BYTE_TYPE_DEFINED
 65  #define BYTE_TYPE_DEFINED
 66  typedef uint8_t byte;
 67  #endif
 68  #ifndef WORD_TYPE_DEFINED
 69  #define WORD_TYPE_DEFINED
 70  typedef uint16_t word;
 71  #endif
 72  typedef int8_t offset;
 73  
 74  /** Structured Datatypes *************************************/
 75  /** NOTICE: #define LSB_FIRST for machines where least      **/
 76  /**         signifcant byte goes first.                     **/
 77  /*************************************************************/
 78  typedef union
 79  {
 80  #ifdef LSB_FIRST
 81    struct { byte l,h; } B;
 82  #else
 83    struct { byte h,l; } B;
 84  #endif
 85    word W;
 86  } pair;
 87  
 88  typedef struct
 89  {
 90    pair AF,BC,DE,HL,IX,IY,PC,SP;       /* Main registers      */
 91    pair AF1,BC1,DE1,HL1;               /* Shadow registers    */
 92    byte IFF,I;                         /* Interrupt registers */
 93    byte R;                             /* Refresh register    */
 94  
 95    int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */
 96                        /* between calls to LoopZ80()          */
 97    int IBackup;        /* Private, don't touch                */
 98    word IRequest;      /* Set to address of pending IRQ       */
 99    byte IAutoReset;    /* Set to 1 to autom. reset IRequest   */
100    byte TrapBadOps;    /* Set to 1 to warn of illegal opcodes */
101    word Trap;          /* Set Trap to address to trace from   */
102    byte Trace;         /* Set Trace=1 to start tracing        */
103    void *User;         /* Arbitrary user data (ID,RAM*,etc.)  */
104  } Z80;
105  
106  /** ResetZ80() ***********************************************/
107  /** This function can be used to reset the registers before **/
108  /** starting execution with RunZ80(). It sets registers to  **/
109  /** their initial values.                                   **/
110  /*************************************************************/
111  void ResetZ80(register Z80 *R, register int Cycles);
112  
113  /** ExecZ80() ************************************************/
114  /** This function will execute given number of Z80 cycles.  **/
115  /** It will then return the number of cycles left, possibly **/
116  /** negative, and current register values in R.             **/
117  /*************************************************************/
118  #ifdef EXECZ80
119  int ExecZ80(register Z80 *R,register int RunCycles);
120  #endif
121  
122  /** IntZ80() *************************************************/
123  /** This function will generate interrupt of given vector.  **/
124  /*************************************************************/
125  void IntZ80(register Z80 *R,register word Vector);
126  
127  /** RunZ80() *************************************************/
128  /** This function will run Z80 code until an LoopZ80() call **/
129  /** returns INT_QUIT. It will return the PC at which        **/
130  /** emulation stopped, and current register values in R.    **/
131  /*************************************************************/
132  #ifndef EXECZ80
133  word RunZ80(register Z80 *R);
134  #endif
135  
136  /** RdZ80()/WrZ80() ******************************************/
137  /** These functions are called when access to RAM occurs.   **/
138  /** They allow to control memory access.                    **/
139  /************************************ TO BE WRITTEN BY USER **/
140  void WrZ80(register word Addr,register byte Value);
141  byte RdZ80(register word Addr);
142  
143  /** InZ80()/OutZ80() *****************************************/
144  /** Z80 emulation calls these functions to read/write from  **/
145  /** I/O ports. There can be 65536 I/O ports, but only first **/
146  /** 256 are usually used.                                   **/
147  /************************************ TO BE WRITTEN BY USER **/
148  void OutZ80(register word Port,register byte Value);
149  byte InZ80(register word Port);
150  
151  /** PatchZ80() ***********************************************/
152  /** Z80 emulation calls this function when it encounters a  **/
153  /** special patch command (ED FE) provided for user needs.  **/
154  /** For example, it can be called to emulate BIOS calls,    **/
155  /** such as disk and tape access. Replace it with an empty  **/
156  /** macro for no patching.                                  **/
157  /************************************ TO BE WRITTEN BY USER **/
158  void PatchZ80(register Z80 *R);
159  
160  /** DebugZ80() ***********************************************/
161  /** This function should exist if DEBUG is #defined. When   **/
162  /** Trace!=0, it is called after each command executed by   **/
163  /** the CPU, and given the Z80 registers. Emulation exits   **/
164  /** if DebugZ80() returns 0.                                **/
165  /*************************************************************/
166  #ifdef DEBUG
167  byte DebugZ80(register Z80 *R);
168  #endif
169  
170  /** LoopZ80() ************************************************/
171  /** Z80 emulation calls this function periodically to check **/
172  /** if the system hardware requires any interrupts. This    **/
173  /** function must return an address of the interrupt vector **/
174  /** (0x0038, 0x0066, etc.) or INT_NONE for no interrupt.    **/
175  /** Return INT_QUIT to exit the emulation loop.             **/
176  /************************************ TO BE WRITTEN BY USER **/
177  word LoopZ80(register Z80 *R);
178  
179  /** JumpZ80() ************************************************/
180  /** Z80 emulation calls this function when it executes a    **/
181  /** JP, JR, CALL, RST, or RET. You can use JumpZ80() to     **/
182  /** trap these opcodes and switch memory layout.            **/
183  /************************************ TO BE WRITTEN BY USER **/
184  #ifndef JUMPZ80
185  #define JumpZ80(PC)
186  #else
187  void JumpZ80(word PC);
188  #endif
189  
190  #ifdef __cplusplus
191  }
192  #endif
193  #endif /* Z80_H */