/* ______ ______ ______ /\___ \ /\ __ \ /\ \ \/__/ /__\ \ __ \\ \ \ \ /\_____\\ \_____\\ \_____\ Zilog \/_____/ \/_____/ \/_____/ CPU Emulator Copyright (C) 1999-2018 Manuel Sainz de Baranda y Goñi. This library is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this library. If not, see . */ #ifndef _emulation_CPU_Z80_H_ #define _emulation_CPU_Z80_H_ #ifdef CPU_Z80_DEPENDENCIES_H # include CPU_Z80_DEPENDENCIES_H #else # include #endif /** Z80 emulator instance object. * @details This structure contains the state of the emulated CPU and callback * pointers necessary to interconnect the emulator with external logic. There * is no constructor function, so, before using an object of this type, some * of its members must be initialized, in particular the following: * @c context, @c read, @c write, @c in, @c out, @c int_data and @c halt. */ typedef struct { /** Number of cycles executed in the current call to @c z80_run. * @details @c z80run sets this variable to 0 before starting to * execute instructions and its value persists after returning. * The callbacks can use this variable to know during what cycle * they are being called. */ zusize cycles; /** The value used as the first argument when calling a callback. * @details This variable should be initialized before using the * emulator and can be used to reference the context/instance of * the machine being emulated. */ void *context; /** CPU registers and internal bits. * @details It contains the state of the registers, as well as the * interrupt flip-flops, variables related to interrupts and other * necessary flags. This is what a debugger should use as its data * source. */ ZZ80State state; /** Temporay IX/IY register for instructions with DDh/FDh prefix. * @details Since instructions with prefix DD and FD behave similarly, * differing only in the use of register IX or IY, for reasons of size * optimization, a single register is used that acts as both. During * opcode analysis, the IX or IY register is copied to this variable * and, once the instruction emulation is complete, its contents are * copied back to the appropriate register. */ Z16Bit xy; /** Backup of the 7th bit of the R register. * @details The value of the R register is incremented as instructions * are executed, but its most significant bit remains unchanged. For * optimization reasons, this bit is saved at the beginning of the * execution of @c z80_run and restored before returning. If an * instruction directly affects the R register, this variable is also * updated accordingly. */ zuint8 r7; /** Temporary storage for opcode fetching. * @details This is an internal private variable. */ Z32Bit data; /** Callback: Called when the CPU needs to read 8 bits from memory. * @param context The value of the member @c context. * @param address The memory address to read from. * @return The 8 bits read from memory. */ zuint8 (* read)(void *context, zuint16 address); /** Callback: Called when the CPU needs to write 8 bits to memory. * @param context The value of the member @c context. * @param address The memory address to write to. * @param value The value to write. */ void (* write)(void *context, zuint16 address, zuint8 value); /** Callback: Called when the CPU needs to read 8 bits from an I/O port. * @param context The value of the member @c context. * @param port The number of the I/O port to read from. * @return The 8 bits read from the I/O port. */ zuint8 (* in)(void *context, zuint16 port); /** Callback: Called when the CPU needs to write 8 bits to an I/O port. * @param context The value of the member @c context. * @param port The number of the I/O port to write to. * @param value The value to write. */ void (* out)(void *context, zuint16 port, zuint8 value); /** Callback: Called when the CPU starts executing a maskable interrupt * and the interrupt mode is 0. This callback must return the bytes of * the instruction that the CPU would read from the data bus in this case. * @param context The value of the member @c context. * @return A 32-bit value containing the bytes of an instruction. The * instruction must begin at the most significant byte (big endian). */ zuint32 (* int_data)(void *context); /** Callback: Called when the CPU enters or exits the halt state. * @param context The value of the member @c context. * @param state @c TRUE if halted; @c FALSE otherwise. * @note This callback is optional and must be set to @c NULL if not * used. */ void (* halt)(void *context, zboolean state); } Z80; Z_C_SYMBOLS_BEGIN #ifndef CPU_Z80_API # ifdef CPU_Z80_STATIC # define CPU_Z80_API # else # define CPU_Z80_API Z_API # endif #endif /** Changes the CPU power status. * @param object A pointer to a Z80 emulator instance object. * @param state @c TRUE = power ON; @c FALSE = power OFF. */ CPU_Z80_API void z80_power(Z80 *object, zboolean state); /** Resets the CPU. * @details This is equivalent to a pulse in the RESET line of a real Z80. * @param object A pointer to a Z80 emulator instance object. */ CPU_Z80_API void z80_reset(Z80 *object); /** Runs the CPU for a given number of @p cycles. * @param object A pointer to a Z80 emulator instance object. * @param cycles The number of cycles to be executed. * @return The number of cycles executed. * @note Given the fact that one Z80 instruction needs between 4 and 23 cycles * to be executed, it's not always possible to run the CPU the exact number of * @p cycles specfified. */ CPU_Z80_API zusize z80_run(Z80 *object, zusize cycles); /** Performs a non-maskable interrupt. * @details This is equivalent to a pulse in the NMI line of a real Z80. * @param object A pointer to a Z80 emulator instance object. */ CPU_Z80_API void z80_nmi(Z80 *object); /** Changes the state of the maskable interrupt. * @details This is equivalent to a change in the INT line of a real Z80. * @param object A pointer to a Z80 emulator instance object. * @param state @c TRUE = line high; @c FALSE = line low. */ CPU_Z80_API void z80_int(Z80 *object, zboolean state); Z_C_SYMBOLS_END #ifdef CPU_Z80_USE_ABI # ifndef CPU_Z80_DEPENDENCIES_H # include # endif Z_C_SYMBOLS_BEGIN # ifndef CPU_Z80_ABI # ifdef CPU_Z80_STATIC # define CPU_Z80_ABI # else # define CPU_Z80_ABI Z_API # endif # endif CPU_Z80_ABI extern ZCPUEmulatorABI const abi_emulation_cpu_z80; Z_C_SYMBOLS_END #endif #endif /* _emulation_CPU_Z80_H_ */