home *** CD-ROM | disk | FTP | other *** search
- #ifndef Z80_H
- #define Z80_H
- /*
- * C header file for the Z80 emulator.
- *
- * All (or most) of these types have to be defined (and to the correct
- * sizes): BYTE, UBYTE, WORD, UWORD, LONG and ULONG.
- *
- * If Z80_ENVDATA is defined, the last element of struct Z80_Control will
- * be a structure named Envdata, of the type "struct Z80_Envdata", which
- * you also must have defined.
- *
- */
-
-
- /* All sizes and offsets are in bytes: */
-
- /* The amount of bytes needed for the Z80 memory space */
- #define Z80_MEMSIZE 0x10000
-
- #define Z80_LBUFSIZE 16 /* Uninteresting to the normal user */
- #define Z80_HBUFSIZE 16
-
- /* The size of the memory used for the cache.
- It must be word-aligned! */
- #define Z80_CACHESIZE ((2*Z80_MEMSIZE)+Z80_LBUFSIZE+Z80_HBUFSIZE)
-
- /* The space needed for memory control flags */
- #define Z80_FLAGMEMSIZE Z80_MEMSIZE
-
- /* Memory write access control flags:
-
- ;Memory flag values (signed byte):
- ; -1 to -128 read-only
- ; 0 ok to write (no detection)
- ; 1 to 16 access counters 1 to 16
- ; 17 to 63 reserved
- ; 64 to 127 user exception
-
- Call Z80_SetMemFlag (described below) to set these flags.
- A zero flag marks ordinary RAM, and no detection is made.
- A negative flag (use Z80_MEM_ROM) marks read-only memory. Attempts
- to write are ignored.
- A value in the range Z80_MEM_CNT to Z80_MEM_CNT+Z80_MEM_CNTNUM-1
- corresponds to write a access counter from 0 to Z80_MEM_CNTNUM-1.
- On each write access, the corresponding counter in the Z80_AccessCnt
- array is incremented by one. If the corresponding flag in the
- Z80_CntType array is zero, the value is written, otherwise the attempt
- to write is ignored.
- A value in the range Z80_MEM_USR to Z80_MEM_USR+Z80_MEM_USRNUM-1
- corresponds to a user memory exception from 0 to Z80_MEM_USRNUM-1.
- If the Z80_MemHandler pointer is nonzero (non-NULL), the routine it
- points to is called with the following parameters:
- d1 contains the exception number (word).
- d2 contains the value (byte).
- a1 contains the Z80 address (word).
- a2 is scratch (address of user-def routine).
- Changes to a1 and a2 have no effect. The handler must protect any other
- registers it uses, and return the following values:
- d1 zero (longword) if value should be written, nonzero if not.
- d2 countains the value (byte).
- The memory handler call is mostly intended for more complex cases of
- write access detection than the simple counters can handle. Not many
- details can be found out about the current Cpu status from the memory
- handler, since it is called in mid-execution of an instruction, and only
- the base pointer registers TableB, Z0, CacheB and FlagsB can be trusted
- to have correct values. For a list of register aliases, see the file
- Z80_coding.i.
-
- Example in C:
- Z80_SetMemFlag(Control, $4000, $1B00, Z80_MEM_CNT+5);
- flags the area from $4000 to $5AFF as access counter 5.
- Z80_CntType[5] = 1;
- sets the type of counter 5 to 'do not write'.
- (Remember: the range is from 0 to Z80_MEM_CNTNUM - 1.)
- */
-
- #define Z80_MEM_ROM (-1)
- #define Z80_MEM_CNT 1
- #define Z80_MEM_CNTNUM 16
- #define Z80_MEM_USR 64
- #define Z80_MEM_USRNUM (128-Z80_MEM_USR)
-
-
- struct Z80_Control {
- LONG Workspace; /* temporary storage, byte swapping and so on */
-
- ULONG AccessCnt[Z80_MEM_CNTNUM]; /* Memory write access counters */
-
- #define Z80_BCDSTACKSIZE 7 /* BCD stack (must be word-aligned!) */
- BYTE Z80_BCDstack[6*Z80_BCDSTACKSIZE];
-
- BYTE CntType[Z80_MEM_CNTNUM];
- /* Counter type designations. Zero for write,
- nonzero for no write. */
-
- UBYTE Parity[256]; /* Parity translation table */
-
- /* Public: */
- BYTE * Memory; /* Pointer to the Z80 address space memory */
- WORD * Cachemem; /* Pointer to the cache memory */
-
- /* Public: */
- BYTE * Flagmem; /* Pointer to the flag memory */
- void * MemHandler; /* Pointer to User Memory Exception Handler */
-
- /* Public (read-only): */
- BYTE * zero; /* Pointer to Z80 address 0. The (signed)
- word-sized Z80 registers (like Z80_HL)
- can be used as offsets from this base
- to access the Z80 memory space. */
- WORD * cachezero; /* Corresponds to Z80_zero in cache memory */
- BYTE * flagzero; /* Corresponds to Z80_zero in flag memory */
-
- /* Public (read-only): */
- WORD Running; /* Nonzero if running, zero if not */
-
- /* Private: */
- WORD Request; /* Request pointer (offset from InstrBase) */
- WORD ReqLvl; /* Priority level of current request */
- UWORD alt_CCR; /* This is the internal F' in CCR format */
- WORD BCD_SP; /* Stack pointer for the BCD stack */
-
- /* Must be word-aligned here! */
-
- /* The Cpu Status structure (public fields):
-
- Fields storing a register have simply the register's name.
- The alternative registers are referred to as alt_<register>.
- <register> here is one of:
- byte-valued A, B, C, D, E, H, L, F, I, R
- word-valued HL, IX, IY, SP, PC
- special IFF, INTMOD
- Accessing HL will affect H and L and vice versa (HL is an 'alias').
- Only the word-valued entries are guaranteed to also be word-aligned.
- IFF and INTMOD are byte-sized, and should be interpreted as follows:
- IFF Bit 7 holds IFF2. Bit 6 holds IFF1. Bits 5-0 are zero.
- INTMOD The values in the range -1 to 1 correspond to interrupt
- modes 0 to 2, respectively.
-
- None of these entries should be written to (and rather not read either)
- unless the emulator is stopped, since their contents are then undefined.
- Most are never updated or read from except upon exiting and continuing.
-
- */
-
- struct CpuStatus {
- BYTE pad_d0_3, alt_A, pad_d0_1, A;
- BYTE pad_d1_3, alt_B, pad_d1_1, B;
- BYTE pad_d2_3, alt_C, pad_d2_1, C;
- BYTE pad_d3_3, alt_D, pad_d3_1, D;
- BYTE pad_d4_3, alt_E, pad_d4_1, E;
- WORD pad_d5_u;
- union {
- WORD w; /* HL can be word-accessed as s.Cpu.HL.w */
- struct {
- BYTE H;
- BYTE L;
- } b; /* or byte accessed as s.Cpu.HL.b.H (or L) */
- } HL;
-
- WORD pad_a2_u;
- WORD SP;
-
- /* Private fields */
- LONG pad_a3, pad_a4, pad_a5, pad_a6;
-
- union {
- WORD w; /* IX can be word-accessed as s.Cpu.IX.w */
- struct {
- BYTE H;
- BYTE L;
- } b; /* or byte accessed as s.Cpu.IX.b.H (or L) */
- } IX;
-
- union {
- WORD w; /* IY can be word-accessed as s.Cpu.IY.w */
- struct {
- BYTE H;
- BYTE L;
- } b; /* or byte accessed as s.Cpu.IY.b.H (or L) */
- } IY;
-
- union {
- WORD w; /* H'L' can be word-accessed as s.Cpu.alt_HL.w */
- struct {
- BYTE H;
- BYTE L;
- } b; /* or byte accessed as s.Cpu.alt_HL.b.H (or L) */
- } alt_HL;
-
- WORD PC; /* PC (written/read only at exit/continue) */
-
- BYTE F; /* These flags are calculated upon exit. */
- BYTE alt_F; /* During emulation, they are unused. */
-
- BYTE IFF; /* IFF2 in bit 7, IFF1 in bit 6 */
- BYTE INTMOD; /* Interruptmode (-1 to 1) = (modes 0 to 2) */
- BYTE I;
- BYTE R; /* Only bit 7 is valid. See "notes.txt" */
- /* word aligned here */
-
- /* These could be inspected. If nonzero, a request has been
- received but not yet served. */
- WORD INT_FF; /* INTreq status */
- WORD NMI_FF; /* NMIreq status */
- WORD RES_FF; /* RESETreq status */
-
- WORD BCD_OP; /* BCD operation */
- UWORD BCD_C; /* BCD carry, in bit 0 */
- BYTE BCD_A; /* BCD destination */
- BYTE BCD_B; /* BCD source */
-
- } Cpu;
-
- #ifdef Z80_ENVDATA
- /* User environment data area. Should be word-aligned here. */
- struct Z80_Envdata Envdata;
- #endif
-
- }; /* end of struct Z80_Control */
-
-
-
- /* Function prototypes and descriptions */
-
-
- int Z80_Init(struct Z80_Control *);
-
- /* Before the emulator is started, the control structure must be
- initialised by calling Z80_Init() with a pointer to the structure.
- The fields Z80_Memory and Z80_Cachemem must be pointing to
- allocated memory. If the memory write access checking feature is
- used, the field Z80_Flagmem must also be set, and if Z80_MemHandler
- is nonzero it is assumed to point to a user memory exception handler.
- See memory flag definitions above for details.
- The user environment data area is not changed. All other fields
- are automatically initialised. The Cpu Status fields are set up as
- after a reset.
- The return value is nonzero if an error occurred, and zero
- otherwise.
- */
-
-
- int Z80_Coldstart(struct Z80_Control *);
-
- /* The emulator is started 'from scratch' with a CPU reset through a
- call to Z80_Coldstart. A pointer to a control structure must be
- given, and the structure must be initialised (see Z80_Init above).
- The return value is nonzero if an error occurred, and zero
- otherwise.
- */
-
-
- int Z80_Continue(struct Z80_Control *);
-
- /* Continue as if nothing happened since last exit (unless the saved
- processor status has been manipulated). A pointer to a control
- structure must be given.
- Changes to other fields than the Cpu status structure entries
- are not recommended; calling Z80_Continue does not guarantee
- that such changes have any effect (see Z80_NewSettings).
- The return value is the same as for Z80_Coldstart.
- */
-
-
- /* About reallocating memory:
-
- Call Z80_Exitreq and make sure the emulator has stopped before
- reallocating memory (remember to copy the old memory contents to the
- new areas), then update the corresponding entries in the control
- structure (Z80_Memory, Z80_Cachemem and Z80_Flagmem). Calling
- Z80_NewSettings will then make sure that Z80_Continue will resume
- the emulation from the new addresses.
- The control structure can be moved whenever the emulator is not
- running, without doing anything other than passing the new address
- to Z80_Continue.
- */
-
- int Z80_NewSettings(struct Z80_Control *);
-
- /* This subroutine makes the emulator update the private fields of the
- control structure when changes to any of the public fields have taken
- place, for instance if the Z80_Memory field is changed. Do not call
- this routine while the emulator is running.
- The return value is nonzero if an error occurred, and zero
- otherwise.
- */
-
-
- void Z80_SetByte(struct Z80_Control *, UWORD addr, BYTE val);
-
- void Z80_SetWordLH(struct Z80_Control *, UWORD addr, UWORD val);
-
- BYTE Z80_GetByte(struct Z80_Control *, UWORD addr);
-
- WORD Z80_GetWordLH(struct Z80_Control *, UWORD addr);
-
- void Z80_SetBlock(struct Z80_Control *,
- UWORD start_addr, ULONG size, BYTE val);
-
- void Z80_ReadBlock(struct Z80_Control *,
- void *buffer, UWORD start_addr, ULONG size);
-
- void Z80_WriteBlock(struct Z80_Control *,
- void *buffer, UWORD start_addr, ULONG size);
-
- /* Routines to access the Z80 address space.
- All need a pointer to the control structure and a word-sized Z80
- address (for block functions this is the block start address).
- Z80_SetByte is passed a byte value to be written. It returns
- nothing.
- Z80_SetWordLH is passed a (high-end first) word value to be written
- and writes it low-end first. It returns nothing.
- Z80_GetByte returns the byte value.
- Z80_GetWordLH reads a (low-end first) word value and returns it
- high-end first.
- All block functions are passed the block size as an unsigned
- longword. They return nothing.
- Z80_SetBlock is also passed the byte value to be written.
- Z80_ReadBlock and Z80_WriteBlock are passed the buffer address
- (in the 680x0 address space) as a pointer to void.
- All Z80 address arithmetic is word-sized. For instance, calling
- Z80_SetWordLH(ctrl, 0xffff, 0x1234) will set address $ffff to $34
- and address $0000 to $12. The block functions will also wrap at $ffff.
- */
-
-
- void Z80_SetMemFlag(struct Z80_Control *,
- UWORD start_addr, ULONG size, BYTE flag);
-
- /* Sets memory flags.
- Takes a pointer to a control structure, a (word-sized) Z80 address,
- the block size (an unsigned longword) and the flag value (a byte) as
- parameters. Nothing is returned. For ranges of flag values, see the
- definition of memory write access control flags above.
- */
-
- BYTE Z80_GetMemFlag(struct Z80_Control *, UWORD addr);
-
- /* Returns the memory flag value for an address.
- Takes a pointer to a control structure and a (word-sized) Z80
- address as parameters. It returns a byte-sized flag. For ranges of
- flag values, see the definition of memory write access control flags
- above.
- */
-
-
- /* The requests could be called from hardware interrupts, keypresses,
- menus or whatever. They do not affect any registers (apart from CCR),
- and return nothing.
- They all need a pointer to the control structure.
-
- The detection time is currently not guaranteed to be anything.
- Hopefully, it is always finite. It shouldn't be more than a few
- emulated Z80 instructions.
- */
-
-
- void Z80_EXITreq(struct Z80_Control *);
- /*
- The emulation can only be interrupted between (Z80) instructions, as
- with the Z80 processor interrupts (and presently only after *certain*
- Z80 instructions). Therefore, stopping the emulator 'from the outside'
- is just another request call.
- */
-
-
- void Z80_INTreq(struct Z80_Control *);
- /*
- Emulates pulling the INT line low.
- */
-
-
- void Z80_NMIreq(struct Z80_Control *);
- /*
- Emulates a Non-Maskable Interrupt. (Negative edge triggered
- on a real Z80.)
- */
-
-
- void Z80_RESETreq(struct Z80_Control *);
- /*
- Emulates pulling the RESET line low.
- */
-
- #endif /* Z80.h */
-