v0.2-alpha
This commit is contained in:
@@ -6,3 +6,13 @@ end_of_line = lf
|
||||
indent_size = 8
|
||||
indent_style = tab
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{md,rst}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.rc]
|
||||
charset = utf-8-bom
|
||||
|
||||
[*.{cff,yml}]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
|
||||
4
.github/FUNDING.yml
vendored
Normal file
4
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
github: redcode
|
||||
ko_fi: redcode
|
||||
liberapay: redcode
|
||||
patreon: redcode
|
||||
7
.github/pull_request_template.md
vendored
Normal file
7
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Thank you for your contribution to the Z80 library. It is required that contributors assign copyright to the original author so that he retains full ownership of the project.
|
||||
|
||||
This makes it easier for other entities to use the software because they only have to deal with one copyright holder. It also gives the original author assurance that he will be able to make decisions in the future without gathering and consulting all contributors.
|
||||
|
||||
By submitting this PR, you agree to the following:
|
||||
|
||||
> You hereby assign copyright in this PR's code to the Z80 library and its copyright holder, Manuel Sainz de Baranda y Goñi, to be licensed under the same terms as the rest of the code. You agree to relinquish any and all copyright interest in the software, to the detriment of your heirs and successors.
|
||||
72
.github/workflows/documentation-ci.yml
vendored
Normal file
72
.github/workflows/documentation-ci.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
name: Documentation CI
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.github/**'
|
||||
- 'API/**'
|
||||
- 'CMake/FindBreathe.cmake'
|
||||
- 'CMake/FindSphinx.cmake'
|
||||
- 'documentation/**'
|
||||
- 'CMakeLists.txt'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/**'
|
||||
- 'API/**'
|
||||
- 'CMake/FindBreathe.cmake'
|
||||
- 'CMake/FindSphinx.cmake'
|
||||
- 'documentation/**'
|
||||
- 'CMakeLists.txt'
|
||||
|
||||
env:
|
||||
BUILD_SHARED_LIBS: NO
|
||||
CMAKE_BUILD_TYPE: Release
|
||||
CMAKE_VERBOSE_MAKEFILE: YES
|
||||
Z80_DOWNLOAD_TEST_FILES: NO
|
||||
Z80_WITH_CMAKE_SUPPORT: NO
|
||||
Z80_WITH_HTML_DOCUMENTATION: YES
|
||||
Z80_WITH_PDF_DOCUMENTATION: YES
|
||||
Z80_WITH_PKGCONFIG_SUPPORT: NO
|
||||
Z80_WITH_STANDARD_DOCUMENTS: NO
|
||||
Z80_WITH_TESTS: NO
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Build Tools
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install doxygen
|
||||
sudo apt-get -y install python3-pip
|
||||
sudo apt-get -y install texlive-full
|
||||
pip3 install --user sphinx
|
||||
pip3 install --user breathe
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
mkdir -p ${{github.workspace}}/build
|
||||
curl -L http://zeta.st/downloads/Zeta-latest.tar.xz | xz -cd | tar -C ${{github.workspace}}/build --strip-components=2 -xvf - Zeta/API/Z
|
||||
|
||||
- name: Configure CMake
|
||||
run: >
|
||||
cmake -B ${{github.workspace}}/build
|
||||
-DBUILD_SHARED_LIBS=${{env.BUILD_SHARED_LIBS}}
|
||||
-DCMAKE_BUILD_TYPE=${{env.CMAKE_BUILD_TYPE}}
|
||||
-DCMAKE_VERBOSE_MAKEFILE=${{env.CMAKE_VERBOSE_MAKEFILE}}
|
||||
-DZ80_DOWNLOAD_TEST_FILES=${{env.Z80_DOWNLOAD_TEST_FILES}}
|
||||
-DZ80_WITH_CMAKE_SUPPORT=${{env.Z80_WITH_CMAKE_SUPPORT}}
|
||||
-DZ80_WITH_HTML_DOCUMENTATION=${{env.Z80_WITH_HTML_DOCUMENTATION}}
|
||||
-DZ80_WITH_PDF_DOCUMENTATION=${{env.Z80_WITH_PDF_DOCUMENTATION}}
|
||||
-DZ80_WITH_PKGCONFIG_SUPPORT=${{env.Z80_WITH_PKGCONFIG_SUPPORT}}
|
||||
-DZ80_WITH_STANDARD_DOCUMENTS=${{env.Z80_WITH_STANDARD_DOCUMENTS}}
|
||||
-DZ80_WITH_TESTS=${{env.Z80_WITH_TESTS}}
|
||||
|
||||
- name: Build HTML Documentation
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.CMAKE_BUILD_TYPE}} --target Documentation-HTML
|
||||
|
||||
- name: Build PDF Documentation
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.CMAKE_BUILD_TYPE}} --target Documentation-PDF
|
||||
92
.github/workflows/library-ci.yml
vendored
Normal file
92
.github/workflows/library-ci.yml
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
name: Library CI
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.github/**'
|
||||
- 'API/**'
|
||||
- 'CMake/FindZeta.cmake'
|
||||
- 'sources/**'
|
||||
- 'support/*.sha512sum'
|
||||
- 'CMakeLists.txt'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/**'
|
||||
- 'API/**'
|
||||
- 'CMake/FindZeta.cmake'
|
||||
- 'sources/**'
|
||||
- 'support/*.sha512sum'
|
||||
- 'CMakeLists.txt'
|
||||
|
||||
env:
|
||||
BUILD_SHARED_LIBS: YES
|
||||
CMAKE_BUILD_TYPE: Release
|
||||
CMAKE_VERBOSE_MAKEFILE: YES
|
||||
Z80_DOWNLOAD_TEST_FILES: YES
|
||||
Z80_NOSTDLIB_FLAGS: Auto
|
||||
Z80_WITH_CMAKE_SUPPORT: NO
|
||||
Z80_WITH_HTML_DOCUMENTATION: NO
|
||||
Z80_WITH_PDF_DOCUMENTATION: NO
|
||||
Z80_WITH_PKGCONFIG_SUPPORT: NO
|
||||
Z80_WITH_STANDARD_DOCUMENTS: NO
|
||||
Z80_WITH_TESTS: YES
|
||||
Z80_WITH_EXECUTE: YES
|
||||
Z80_WITH_FULL_IM0: YES
|
||||
Z80_WITH_Q: YES
|
||||
Z80_WITH_RESET_SIGNAL: YES
|
||||
Z80_WITH_SPECIAL_RESET_SIGNAL: NO
|
||||
Z80_WITH_UNOFFICIAL_RETI: NO
|
||||
Z80_WITH_ZILOG_NMOS_LD_A_IR_BUG: YES
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies (POSIX)
|
||||
if: startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
mkdir -p ${{github.workspace}}/build
|
||||
curl -L http://zeta.st/downloads/Zeta-latest.tar.xz | xz -cd | tar -C ${{github.workspace}}/build --strip-components=2 -xvf - Zeta/API/Z
|
||||
|
||||
- name: Install Dependencies (Windows)
|
||||
if: startsWith(matrix.os, 'windows')
|
||||
shell: cmd
|
||||
run: |
|
||||
mkdir ${{github.workspace}}\build
|
||||
curl -L http://zeta.st/downloads/Zeta-latest.tar.xz | 7z x -txz -si -so | 7z x -si -ttar -o${{github.workspace}}\build Zeta/API/Z
|
||||
|
||||
- name: Configure CMake
|
||||
run: >
|
||||
cmake -B ${{github.workspace}}/build
|
||||
-DBUILD_SHARED_LIBS=${{env.BUILD_SHARED_LIBS}}
|
||||
-DCMAKE_BUILD_TYPE=${{env.CMAKE_BUILD_TYPE}}
|
||||
-DCMAKE_VERBOSE_MAKEFILE=${{env.CMAKE_VERBOSE_MAKEFILE}}
|
||||
-DZ80_DOWNLOAD_TEST_FILES=${{env.Z80_DOWNLOAD_TEST_FILES}}
|
||||
-DZ80_NOSTDLIB_FLAGS=${{env.Z80_NOSTDLIB_FLAGS}}
|
||||
-DZ80_WITH_CMAKE_SUPPORT=${{env.Z80_WITH_CMAKE_SUPPORT}}
|
||||
-DZ80_WITH_HTML_DOCUMENTATION=${{env.Z80_WITH_HTML_DOCUMENTATION}}
|
||||
-DZ80_WITH_PDF_DOCUMENTATION=${{env.Z80_WITH_PDF_DOCUMENTATION}}
|
||||
-DZ80_WITH_PKGCONFIG_SUPPORT=${{env.Z80_WITH_PKGCONFIG_SUPPORT}}
|
||||
-DZ80_WITH_STANDARD_DOCUMENTS=${{env.Z80_WITH_STANDARD_DOCUMENTS}}
|
||||
-DZ80_WITH_TESTS=${{env.Z80_WITH_TESTS}}
|
||||
-DZ80_WITH_EXECUTE=${{env.Z80_WITH_EXECUTE}}
|
||||
-DZ80_WITH_FULL_IM0=${{env.Z80_WITH_FULL_IM0}}
|
||||
-DZ80_WITH_Q=${{env.Z80_WITH_Q}}
|
||||
-DZ80_WITH_RESET_SIGNAL=${{env.Z80_WITH_RESET_SIGNAL}}
|
||||
-DZ80_WITH_SPECIAL_RESET_SIGNAL=${{env.Z80_WITH_SPECIAL_RESET_SIGNAL}}
|
||||
-DZ80_WITH_UNOFFICIAL_RETI=${{env.Z80_WITH_UNOFFICIAL_RETI}}
|
||||
-DZ80_WITH_ZILOG_NMOS_LD_A_IR_BUG=${{env.Z80_WITH_ZILOG_NMOS_LD_A_IR_BUG}}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.CMAKE_BUILD_TYPE}}
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: ctest --output-on-failure -C ${{env.CMAKE_BUILD_TYPE}}
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
.directory
|
||||
.DS_Store
|
||||
.directory
|
||||
Thumbs.db
|
||||
build/
|
||||
|
||||
4
.vimrc
Normal file
4
.vimrc
Normal file
@@ -0,0 +1,4 @@
|
||||
set noexpandtab
|
||||
set shiftwidth=8
|
||||
set tabstop=8
|
||||
autocmd BufWritePre * %s/\s\+$//e
|
||||
672
API/Z80.h
Normal file
672
API/Z80.h
Normal file
@@ -0,0 +1,672 @@
|
||||
/* Z80 API
|
||||
______ ______ ______
|
||||
/\___ \/\ __ \\ __ \
|
||||
____ \/__/ /\_\ __ \\ \/\ \ ________________________________________________
|
||||
| /\_____\\_____\\_____\ |
|
||||
| Zilog \/_____//_____//_____/ CPU Emulator |
|
||||
| Copyright (C) 1999-2022 Manuel Sainz de Baranda y Goñi. |
|
||||
| |
|
||||
| This emulator 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 emulator 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 this emulator. If not, see <http://www.gnu.org/licenses/>. |
|
||||
| |
|
||||
'=============================================================================*/
|
||||
|
||||
#ifndef Z80_H
|
||||
|
||||
/** @file Z80.h
|
||||
* @brief Zilog Z80 CPU emulator.
|
||||
*
|
||||
* @details The Z80 library implements a fast, small and accurate emulator
|
||||
* of the Zilog Z80. It emulates all that is known to date about this CPU,
|
||||
* including the undocumented flags and instructions, MEMPTR, Q, and the
|
||||
* special RESET.
|
||||
*
|
||||
* @version 0.2
|
||||
* @date 2022-05-29
|
||||
* @author Manuel Sainz de Baranda y Goñi. */
|
||||
|
||||
#ifdef Z80_DEPENDENCIES_HEADER
|
||||
# define Z80_H
|
||||
# include Z80_DEPENDENCIES_HEADER
|
||||
# undef Z80_H
|
||||
#else
|
||||
# include <Z/macros/language.h>
|
||||
# include <Z/types/bitwise.h>
|
||||
#endif
|
||||
|
||||
#ifndef Z80_API
|
||||
# if defined(Z80_STATIC) || defined(__DOXYGEN__)
|
||||
# define Z80_API
|
||||
# else
|
||||
# define Z80_API Z_API_IMPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/** @brief The major version number of the Z80 library. */
|
||||
|
||||
#define Z80_LIBRARY_VERSION_MAJOR 0
|
||||
|
||||
/** @brief The minor version number of the Z80 library. */
|
||||
|
||||
#define Z80_LIBRARY_VERSION_MINOR 2
|
||||
|
||||
/** @brief The micro version number of the Z80 library. */
|
||||
|
||||
#define Z80_LIBRARY_VERSION_MICRO 0
|
||||
|
||||
/** @brief A string literal with the version number of the Z80 library. */
|
||||
|
||||
#define Z80_LIBRARY_VERSION_STRING "0.2"
|
||||
|
||||
/** @brief The maximum number of clock cycles that the @ref z80_run and @ref
|
||||
* z80_execute functions can emulate per call. */
|
||||
|
||||
#define Z80_CYCLE_LIMIT (Z_USIZE_MAXIMUM - Z_USIZE(30))
|
||||
#define Z80_CYCLES_PER_RESET 5
|
||||
|
||||
/** @brief The 8-bit value interpreted as a hook by the Z80 emulator, which
|
||||
* corresponds to the <tt>ld h,h</tt> opcode in the Z80 ISA. */
|
||||
|
||||
#define Z80_HOOK Z_UINT8(0x64)
|
||||
|
||||
/** @brief Defines a pointer to a callback function used by the Z80 emulator
|
||||
* to read a byte.
|
||||
*
|
||||
* @param context The value of the @ref Z80.context member variable of the
|
||||
* object invoking the callback.
|
||||
* @param address The memory address or I/O port to read from.
|
||||
* @return The byte read. */
|
||||
|
||||
typedef zuint8 (* Z80Read)(void *context, zuint16 address);
|
||||
|
||||
/** @brief Defines a pointer to a callback function used by the Z80 emulator
|
||||
* to write a byte.
|
||||
*
|
||||
* @param context The value of the @ref Z80.context member variable of the
|
||||
* object invoking the callback.
|
||||
* @param address The memory address or I/O port to write to.
|
||||
* @param value The byte to write. */
|
||||
|
||||
typedef void (* Z80Write)(void *context, zuint16 address, zuint8 value);
|
||||
|
||||
/** @brief Defines a pointer to a callback function used by the Z80 emulator
|
||||
* to notify the change of state of the HALT line.
|
||||
*
|
||||
* @param context The value of the @ref Z80.context member variable of the
|
||||
* object invoking the callback.
|
||||
* @param state
|
||||
* @c TRUE if the HALT line goes low (the CPU enters the HALT state);
|
||||
* @c FALSE if the HALT line goes high (the CPU exits the HALT state). */
|
||||
|
||||
typedef void (* Z80HALT)(void *context, zboolean state);
|
||||
|
||||
/** @brief Defines a pointer to a callback function used by the Z80 emulator
|
||||
* to notify an event.
|
||||
*
|
||||
* @param context The value of the @ref Z80.context member variable of the
|
||||
* object invoking the callback. */
|
||||
|
||||
typedef void (* Z80Notify)(void *context);
|
||||
|
||||
|
||||
typedef zusize (* Z80Reset)(void *context, zuint16 address);
|
||||
|
||||
/** @struct Z80 Z80.h
|
||||
*
|
||||
* @brief A Z80 CPU emulator.
|
||||
*
|
||||
* @details @c Z80 contains the state of an emulated Z80 CPU
|
||||
* and the callback pointers needed to interconnect it with the external logic.
|
||||
* Before using an object of this type, some of its members
|
||||
* must be initialized. In particular the following (in alphabetical order):
|
||||
* @ref Z80.context, @ref Z80.fetch, @ref Z80.fetch_opcode, @ref Z80.halt_nop,
|
||||
* @ref Z80.in, @ref Z80.out, @ref Z80.read, @ref Z80.write, @ref Z80.read_bus,
|
||||
* @ref Z80.halt, @ref Z80.inta, @ref Z80.reti @ref Z80.hook and @ref
|
||||
* Z80.model.
|
||||
*
|
||||
* Callback | Mandatory
|
||||
* --------------------- | ---------
|
||||
* @ref Z80.fetch_opcode | yes
|
||||
* @ref Z80.fetch | yes
|
||||
* @ref Z80.read | yes
|
||||
* @ref Z80.write | yes
|
||||
* @ref Z80.in | yes
|
||||
* @ref Z80.out | yes
|
||||
* @ref Z80.halt | no
|
||||
* @ref Z80.halt_nop | no
|
||||
* @ref Z80.nmia | yes
|
||||
* @ref Z80.inta | yes
|
||||
* @ref Z80.int_fetch | no
|
||||
* @ref Z80.ld_i_a | no
|
||||
* @ref Z80.ld_r_a | no
|
||||
* @ref Z80.reti | no
|
||||
* @ref Z80.retn | no
|
||||
* @ref Z80.hook | no
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
|
||||
/** @brief Clock cycle counter.
|
||||
*
|
||||
* This clock cycle counter is updated as the emulator executes
|
||||
* instructions and responds to different signals. */
|
||||
|
||||
zusize cycles;
|
||||
|
||||
/** @brief Maximum number of clock cycles to be executed in the current
|
||||
* invokation of @ref z80_run. */
|
||||
|
||||
zusize cycle_limit;
|
||||
|
||||
/** @brief Pointer passed as the first argument to the callbacks.
|
||||
*
|
||||
* @details This member variable can be used to maintain a reference to
|
||||
* the object or context to which the Z80 emulator object belongs. */
|
||||
|
||||
void *context;
|
||||
|
||||
/** @brief Callback used to perform opcode fetch operations.
|
||||
*
|
||||
* @details This type of operation is used by the CPU to read the first
|
||||
* byte of an instruction or an instruction prefix. A succession of
|
||||
* @c DDh and/or @c FDh prefixes will cause multiple consecutive such
|
||||
* operations until an opcode is fetched. In the instructions with
|
||||
* double prefix (@c CBDDh or @c CBFDh), only the prefixes are fetched
|
||||
* with this operation, the remaining 2 bytes are accessed by using
|
||||
* normal memory read operations.
|
||||
*
|
||||
* The emulator always incrementents the R register @b before calling
|
||||
* this callback, but the value of its most-significant bit (R7) is not
|
||||
* preserved for speed optimization reasons. In the rare case that the
|
||||
* callback function needs to access that register, it must take R7
|
||||
* from the 7th bit of the @c r7 member variable.
|
||||
*
|
||||
* Implementations that do not distinguish between opcode fetch and
|
||||
* memory read operations should use the same callback function for
|
||||
* both.
|
||||
*
|
||||
* @attention This callback is mandatory, initializing it to @c Z_NULL
|
||||
* will cause the emulator to crash. */
|
||||
|
||||
Z80Read fetch_opcode;
|
||||
|
||||
/** @brief Callback used to perform memory read operations on instruction data.
|
||||
*
|
||||
* @attention This callback is mandatory, initializing it to @c Z_NULL
|
||||
* will cause the emulator to crash. */
|
||||
|
||||
Z80Read fetch;
|
||||
|
||||
/** @brief Callback used to perform a memory read operation.
|
||||
*
|
||||
* @details This type of operation is used by the CPU to read a byte
|
||||
* from a memory address.
|
||||
*
|
||||
* @attention This callback is mandatory, initializing it to @c Z_NULL
|
||||
* will cause the emulator to crash. */
|
||||
|
||||
Z80Read read;
|
||||
|
||||
/** @brief Callback used to perform a memory write operation.
|
||||
*
|
||||
* @details This type of operation is used by the CPU to write a byte
|
||||
* to a memory address.
|
||||
*
|
||||
* @attention This callback is mandatory, initializing it to @c Z_NULL
|
||||
* will cause the emulator to crash. */
|
||||
|
||||
Z80Write write;
|
||||
|
||||
/** @brief Callback used to perform an I/O read operation.
|
||||
*
|
||||
* @details This type of operation is used by the CPU to read a byte
|
||||
* from an I/O port.
|
||||
*
|
||||
* @attention This callback is mandatory, initializing it to @c Z_NULL
|
||||
* will cause the emulator to crash. */
|
||||
|
||||
Z80Read in;
|
||||
|
||||
/** @brief Callback used to perform an I/O write operation.
|
||||
*
|
||||
* @details This type of operation is used by the CPU to write a byte
|
||||
* to an I/O port.
|
||||
*
|
||||
* @attention This callback is mandatory, initializing it to @c Z_NULL
|
||||
* will cause the emulator to crash. */
|
||||
|
||||
Z80Write out;
|
||||
|
||||
/** @brief Callback used to notify that the state of the HALT output
|
||||
* line has changed.
|
||||
*
|
||||
* @details The @c HALT instruction halts the CPU by not incrementing
|
||||
* the PC register, so the instruction is re-executed until an
|
||||
* interrupt is accepted. Only then the PC register is incremented
|
||||
* again and the next instruction is executed. The HALT output line is
|
||||
* active (low) during the HALT state.
|
||||
*
|
||||
* The emulator invokes this callback after changing the value of the
|
||||
* @c halt_line member variable and, when exiting the HALT state,
|
||||
* immediately before executing the interrupt response.
|
||||
*
|
||||
* @attention This callback is optional and @b must be initialized to
|
||||
* @c Z_NULL if not used. */
|
||||
|
||||
Z80HALT halt;
|
||||
|
||||
/** @brief Callback invoked... */
|
||||
|
||||
Z80Read nop;
|
||||
|
||||
/** @brief Callback invoked... */
|
||||
|
||||
Z80Read nmia;
|
||||
|
||||
/** @brief Callback used to notify a maskable interrupt acknowledge
|
||||
* (INTA).
|
||||
*
|
||||
* @details When a maskable interrupt (INT) is accepted, the CPU
|
||||
* generates a special M1 cycle to indicate that the interrupting I/O
|
||||
* device can write to the data bus. Two wait clock cycles are added
|
||||
* to this M1 cycle, allowing sufficient time to identify which device
|
||||
* must insert the data.
|
||||
*
|
||||
* The emulator invokes this callback during the execution of the INT
|
||||
* response. It should be used to identify and prepare the context of
|
||||
* the interrupting device, so that subsequent invocations of the @c
|
||||
* read_bus callback can read the interrupt response vector or the
|
||||
* instruction to be executed.
|
||||
*
|
||||
* @note This callback is optional and @b must be initialized to @c
|
||||
* Z_NULL if not used.
|
||||
|
||||
* @details When a maskable interrupt (INT) is accepted, the CPU reads
|
||||
* the interrupt response data provided by the interrupting device via
|
||||
* the data bus. Usually only one data bus read operation is performed
|
||||
* during the INT acknowledge cycle, but when the CPU responds to the
|
||||
* interrupt in mode 0, it will perform as many such operations as
|
||||
* needed to read the byte sequence of the instruction to be executed.
|
||||
*
|
||||
* The emulator invokes this callback during the execution of the INT
|
||||
* response. The return value is ignored in interrupt mode 1. In mode
|
||||
* 0, the emulator invokes this callback as many times as needed to
|
||||
* read a complete instruction. Illegal instructions and instruction
|
||||
* prefix sequences are fully supported.
|
||||
*
|
||||
* @attention This callback is optional and @b must be initialized to
|
||||
* @c Z_NULL if not used, in which case the emulator will assume that
|
||||
* the byte read from the data bus is always @c FFh. */
|
||||
|
||||
Z80Read inta;
|
||||
|
||||
/** @brief Callback used to perform a data bus read operation during a
|
||||
* maskable interrupt (INT) response.
|
||||
**/
|
||||
|
||||
Z80Read int_fetch;
|
||||
|
||||
Z80Reset reset;
|
||||
|
||||
/** @brief Callback invoked before executing the <tt>ld i,a</tt>
|
||||
* instruction. */
|
||||
|
||||
Z80Notify ld_i_a;
|
||||
|
||||
/** @brief Callback invoked before executing the <tt>ld r,a</tt>
|
||||
* instruction.
|
||||
*
|
||||
* @attention This callback is optional and @b must be initialized to
|
||||
* @c Z_NULL if not used. */
|
||||
|
||||
Z80Notify ld_r_a;
|
||||
|
||||
/** @brief Callback invoked before executing the @c reti instruction.
|
||||
*
|
||||
* The Z80 Counter/Timer Circuit (CTC) detects the two-byte @c reti
|
||||
* opcode when it is fetched by the CPU. This instruction is used to
|
||||
* return from an ISR and signal that the computer should initialize
|
||||
* the daisy-chain enable lines for control of nested priority
|
||||
* interrupt handling.
|
||||
*
|
||||
* Although the Z80 CTC is not part of the CPU, the emulator can signal
|
||||
* the execution of a @c reti instruction by invoking this callback in
|
||||
* order to simplify the emulation of machines that use daisy-chain
|
||||
* interrupt servicing, thus avoiding having to implement the detection
|
||||
* of this instruction externally, which is not optimal and would cause
|
||||
* a speed penalty.
|
||||
*
|
||||
* @attention This callback is optional and @b must be initialized to
|
||||
* @c Z_NULL if not used. */
|
||||
|
||||
Z80Notify reti;
|
||||
|
||||
/** @brief Callback invoked before executing the @c retn instruction.
|
||||
|
||||
* @attention This callback is optional and @b must be initialized to
|
||||
* @c Z_NULL if not used. */
|
||||
|
||||
Z80Notify retn;
|
||||
|
||||
/** @brief Callback invoked...
|
||||
*
|
||||
* @attention This callback is optional and @b must be initialized to
|
||||
* @c Z_NULL if not used. */
|
||||
|
||||
Z80Read hook;
|
||||
|
||||
/** @brief Temporary storage used for instruction fetch. */
|
||||
|
||||
ZInt32 data;
|
||||
|
||||
/** @brief Temporay IX/IY register. */
|
||||
|
||||
ZInt16 xy;
|
||||
|
||||
ZInt16 memptr; /**< @brief MEMPTR register. */
|
||||
ZInt16 pc; /**< @brief PC register. */
|
||||
ZInt16 sp; /**< @brief SP register. */
|
||||
ZInt16 ix; /**< @brief IX register. */
|
||||
ZInt16 iy; /**< @brief IY register. */
|
||||
ZInt16 af; /**< @brief AF register. */
|
||||
ZInt16 bc; /**< @brief BC register. */
|
||||
ZInt16 de; /**< @brief DE register. */
|
||||
ZInt16 hl; /**< @brief HL register. */
|
||||
ZInt16 af_; /**< @brief AF' register. */
|
||||
ZInt16 bc_; /**< @brief BC' register. */
|
||||
ZInt16 de_; /**< @brief DE' register. */
|
||||
ZInt16 hl_; /**< @brief HL' register. */
|
||||
zuint8 r; /**< @brief R register. */
|
||||
zuint8 i; /**< @brief I register. */
|
||||
|
||||
/** @brief The most significant bit of the R register (R7).
|
||||
*
|
||||
* @details The R register is incremented during each M1 cycle, but its
|
||||
* most significant bit (R7) is not affected. For optimization reasons,
|
||||
* this behavior is not emulated in every M1 cycle, so successive
|
||||
* increments of R corrupt R7. @c z80_run keeps the value of R7 in this
|
||||
* temporary member variable while executing operations and copies it
|
||||
* back to R before returning. Since this variable is a snapshot of the
|
||||
* R register at a given time, the value of the 7 least significant
|
||||
* bits must be considered garbage. */
|
||||
|
||||
zuint8 r7;
|
||||
|
||||
/** @brief Maskable interrup mode.
|
||||
*
|
||||
* @details Contains the number of the maskable interrupt mode in use:
|
||||
* `0`, `1` or `2`. */
|
||||
|
||||
zuint8 im;
|
||||
|
||||
/** @brief Number of signals pending to be processed. */
|
||||
|
||||
zuint8 request;
|
||||
|
||||
/** @brief TODO */
|
||||
|
||||
zuint8 resume;
|
||||
|
||||
zuint8 iff1; /**< @brief Interrupt flip-flop 1 (IFF1). */
|
||||
zuint8 iff2; /**< @brief Interrupt flip-flop 2 (IFF2). */
|
||||
zuint8 q; /**< @brief Q register. */
|
||||
|
||||
/** @brief CPU model.
|
||||
*
|
||||
* @details todo... */
|
||||
|
||||
zuint8 options;
|
||||
|
||||
/** @brief State of the INT line.
|
||||
*
|
||||
* @details Contains @c TRUE if the INT line is active, or @c FALSE
|
||||
* otherwise. */
|
||||
|
||||
zuint8 int_line;
|
||||
|
||||
/** @brief State of the HALT line.
|
||||
*
|
||||
* @details Contains @c TRUE if the HALT line is active, or @c FALSE
|
||||
* otherwise. The emulator always modifies this variable before
|
||||
* invoking the @ref Z80.halt callback. */
|
||||
|
||||
zuint8 halt_line;
|
||||
} Z80;
|
||||
|
||||
#define Z80_MEMPTR(self) (self).memptr.uint16_value
|
||||
#define Z80_MEMPTRH(self) (self).memptr.uint8_values.at_1
|
||||
#define Z80_MEMPTRL(self) (self).memptr.uint8_values.at_0
|
||||
#define Z80_PC(self) (self).pc.uint16_value
|
||||
#define Z80_SP(self) (self).sp.uint16_value
|
||||
#define Z80_XY(self) (self).xy.uint16_value
|
||||
#define Z80_IX(self) (self).ix.uint16_value
|
||||
#define Z80_IY(self) (self).iy.uint16_value
|
||||
#define Z80_AF(self) (self).af.uint16_value
|
||||
#define Z80_BC(self) (self).bc.uint16_value
|
||||
#define Z80_DE(self) (self).de.uint16_value
|
||||
#define Z80_HL(self) (self).hl.uint16_value
|
||||
#define Z80_AF_(self) (self).af_.uint16_value
|
||||
#define Z80_BC_(self) (self).bc_.uint16_value
|
||||
#define Z80_DE_(self) (self).de_.uint16_value
|
||||
#define Z80_HL_(self) (self).hl_.uint16_value
|
||||
#define Z80_PCH(self) (self).pc.uint8_values.at_1
|
||||
#define Z80_PCL(self) (self).pc.uint8_values.at_0
|
||||
#define Z80_SPH(self) (self).sp.uint8_values.at_1
|
||||
#define Z80_SPL(self) (self).sp.uint8_values.at_0
|
||||
#define Z80_XYH(self) (self).xy.uint8_values.at_1
|
||||
#define Z80_XYL(self) (self).xy.uint8_values.at_0
|
||||
#define Z80_IXH(self) (self).ix.uint8_values.at_1
|
||||
#define Z80_IXL(self) (self).ix.uint8_values.at_0
|
||||
#define Z80_IYH(self) (self).iy.uint8_values.at_1
|
||||
#define Z80_IYL(self) (self).iy.uint8_values.at_0
|
||||
#define Z80_A(self) (self).af.uint8_values.at_1
|
||||
#define Z80_F(self) (self).af.uint8_values.at_0
|
||||
#define Z80_B(self) (self).bc.uint8_values.at_1
|
||||
#define Z80_C(self) (self).bc.uint8_values.at_0
|
||||
#define Z80_D(self) (self).de.uint8_values.at_1
|
||||
#define Z80_E(self) (self).de.uint8_values.at_0
|
||||
#define Z80_H(self) (self).hl.uint8_values.at_1
|
||||
#define Z80_L(self) (self).hl.uint8_values.at_0
|
||||
#define Z80_A_(self) (self).af_.uint8_values.at_1
|
||||
#define Z80_F_(self) (self).af_.uint8_values.at_0
|
||||
#define Z80_B_(self) (self).bc_.uint8_values.at_1
|
||||
#define Z80_C_(self) (self).bc_.uint8_values.at_0
|
||||
#define Z80_D_(self) (self).de_.uint8_values.at_1
|
||||
#define Z80_E_(self) (self).de_.uint8_values.at_0
|
||||
#define Z80_H_(self) (self).hl_.uint8_values.at_1
|
||||
#define Z80_L_(self) (self).hl_.uint8_values.at_0
|
||||
|
||||
#define Z80_SF 128
|
||||
#define Z80_ZF 64
|
||||
#define Z80_YF 32
|
||||
#define Z80_HF 16
|
||||
#define Z80_XF 8
|
||||
#define Z80_PF 4
|
||||
#define Z80_NF 2
|
||||
#define Z80_CF 1
|
||||
|
||||
#define Z80_OPTION_LD_A_IR_BUG 1
|
||||
#define Z80_OPTION_OUT_VC_255 2
|
||||
#define Z80_OPTION_XQ 8
|
||||
#define Z80_OPTION_HALT_SKIP 16
|
||||
#define Z80_OPTION_YQ 32
|
||||
|
||||
/** @brief Zilog Z80 NMOS version. */
|
||||
#define Z80_MODEL_ZILOG_NMOS \
|
||||
(Z80_OPTION_LD_A_IR_BUG | Z80_OPTION_XQ | Z80_OPTION_YQ)
|
||||
|
||||
/** @brief Zilog Z80 CMOS version. */
|
||||
#define Z80_MODEL_ZILOG_CMOS \
|
||||
(Z80_OPTION_OUT_VC_255 | Z80_OPTION_XQ | Z80_OPTION_YQ)
|
||||
|
||||
#define Z80_MODEL_NEC_NMOS \
|
||||
Z80_OPTION_LD_A_IR_BUG
|
||||
|
||||
#define Z80_MODEL_ST_CMOS \
|
||||
(Z80_OPTION_LD_A_IR_BUG | Z80_OPTION_YQ)
|
||||
|
||||
|
||||
#define Z80_REQUEST_RESET 3
|
||||
#define Z80_REQUEST_REJECT_NMI 4
|
||||
#define Z80_REQUEST_NMI 8 /**< NMI pending. */
|
||||
#define Z80_REQUEST_CLEAR_PC 16
|
||||
#define Z80_REQUEST_SPECIAL_RESET 32
|
||||
#define Z80_REQUEST_INT 64 /**< INT pending. */
|
||||
#define Z80_REQUEST_ANY_RESET 35
|
||||
|
||||
|
||||
#define Z80_REQUEST_RESET 3
|
||||
#define Z80_REQUEST_INTERRUPT 5
|
||||
|
||||
#define Z80_RESUME_HALT 1 /**< Resume the execution of the HALT state. */
|
||||
#define Z80_RESUME_XY 2 /**< Resume at opcode decode stage in INT mode 0. */
|
||||
#define Z80_RESUME_IM0_XY 3 /**< Resume at opcode decode stage. */
|
||||
#define Z80_RESUME_NORMAL_RESET 4
|
||||
#define Z80_RESUME_SPECIAL_RESET_XY 5
|
||||
#define Z80_RESUME_SPECIAL_RESET_NOP 6
|
||||
|
||||
Z_EXTERN_C_BEGIN
|
||||
|
||||
/** @brief Sets the power state of a Z80 emulator.
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called.
|
||||
* @param state
|
||||
* @c TRUE = power ON;
|
||||
* @c FALSE = power OFF. */
|
||||
|
||||
Z80_API void z80_power(Z80 *self, zboolean state);
|
||||
|
||||
/** @brief Performs a normal RESET on a Z80 emulator.
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called. */
|
||||
|
||||
Z80_API void z80_instant_reset(Z80 *self);
|
||||
|
||||
/** @brief Sends a normal RESET signal to a Z80 emulator.
|
||||
*
|
||||
* @details todo
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called. */
|
||||
|
||||
Z80_API void z80_reset(Z80 *self);
|
||||
|
||||
/** @brief Sends a special RESET signal to a Z80 emulator.
|
||||
*
|
||||
* @details todo
|
||||
*
|
||||
* @sa
|
||||
* - http://www.primrosebank.net/computers/z80/z80_special_reset.htm
|
||||
* - US Patent 4486827
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called. */
|
||||
|
||||
Z80_API void z80_special_reset(Z80 *self);
|
||||
|
||||
/** @brief Sets the state of the INT line of a Z80 emulator.
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called.
|
||||
* @param state
|
||||
* @c TRUE = ON (line low);
|
||||
* @c FALSE = OFF (line high). */
|
||||
|
||||
Z80_API void z80_int(Z80 *self, zboolean state);
|
||||
|
||||
/** @brief Sends a NMI signal to a Z80 emulator.
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called. */
|
||||
|
||||
Z80_API void z80_nmi(Z80 *self);
|
||||
|
||||
Z80_API void z80_busreq(Z80 *self, zboolean state);
|
||||
|
||||
/** @brief Runs a Z80 emulator for a given number of clock @p cycles, executing
|
||||
* only instructions without responding to signals.
|
||||
*
|
||||
* @details Given the fact that one Z80 instruction takes between 4 and 23
|
||||
* cycles to be executed, it is not always possible to run the CPU the exact
|
||||
* number of @p cycles specfified.
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called.
|
||||
* @param cycles Number of clock cycles to be emulated.
|
||||
* @return The actual number of clock cycles emulated. */
|
||||
|
||||
Z80_API zusize z80_execute(Z80 *self, zusize cycles);
|
||||
|
||||
/** @brief Runs a Z80 emulator for a given number of clock @p cycles.
|
||||
*
|
||||
* @details Given the fact that one Z80 instruction takes between 4 and 23
|
||||
* cycles to be executed, it is not always possible to run the CPU the exact
|
||||
* number of @p cycles specfified.
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called.
|
||||
* @param cycles Number of clock cycles to be emulated.
|
||||
* @return The actual number of clock cycles emulated. */
|
||||
|
||||
Z80_API zusize z80_run(Z80 *self, zusize cycles);
|
||||
|
||||
|
||||
/** @brief Obtains the refresh address of the M1 cycle being executed by a Z80
|
||||
* emulator.
|
||||
*
|
||||
* @details todo
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called.
|
||||
* @return todo */
|
||||
|
||||
static Z_INLINE zuint16 z80_refresh_address(Z80 *self)
|
||||
{return ((zuint16)self->i << 8) | ((self->r - 1) & 127);}
|
||||
|
||||
|
||||
/** @brief Computes the clock cycle, relative to the start of the instruction,
|
||||
* at which the I/O read M-cycle being executed by a Z80 emulator begins.
|
||||
*
|
||||
* @details todo
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called.
|
||||
* @return todo */
|
||||
|
||||
static Z_INLINE zuint8 z80_in_cycle(Z80 *self)
|
||||
{
|
||||
return self->data.uint8_array[0] == 0xDB
|
||||
? /* in a,(BYTE) : 4+3 */
|
||||
7
|
||||
: /* in J,(c) / in (c) : 4+4 */
|
||||
8
|
||||
+ /* ini / ind / inir / indr : 4+5 */
|
||||
(self->data.uint8_array[1] >> 7);
|
||||
}
|
||||
|
||||
|
||||
/** @brief Computes the clock cycle, relative to the start of the instruction,
|
||||
* at which the I/O write M-cycle being executed by a Z80 emulator begins.
|
||||
*
|
||||
* @details todo
|
||||
*
|
||||
* @param self Pointer to the object on which the function is called.
|
||||
* @return todo */
|
||||
|
||||
static Z_INLINE zuint8 z80_out_cycle(Z80 *self)
|
||||
{
|
||||
return self->data.uint8_array[0] == 0xD3
|
||||
? /* out (BYTE),a : 4+3 */
|
||||
7
|
||||
: /* out (c),J / out (c),0 : 4+4 */
|
||||
8
|
||||
+ /* outi / outd / otir / otdr : 4+5+3 */
|
||||
((self->data.uint8_array[1] >> 7) << 2);
|
||||
}
|
||||
|
||||
|
||||
Z_EXTERN_C_END
|
||||
|
||||
#endif /* Z80_H */
|
||||
@@ -1,201 +0,0 @@
|
||||
/* ______ ______ ______
|
||||
/\___ \ /\ __ \/\ __ \
|
||||
\/__/ /_\ \ __ \ \ \/\ \
|
||||
/\_____\ \_____\ \_____\
|
||||
Zilog \/_____/\/_____/\/_____/ CPU Emulator ----------------------------------
|
||||
Copyright (C) 1999-2018 Manuel Sainz de Baranda y Goñi.
|
||||
|
||||
This emulator 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 emulator 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 emulator. If not, see <http://www.gnu.org/licenses/>.
|
||||
--------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef _emulation_CPU_Z80_H_
|
||||
#define _emulation_CPU_Z80_H_
|
||||
|
||||
#ifdef CPU_Z80_DEPENDENCIES_H
|
||||
# include CPU_Z80_DEPENDENCIES_H
|
||||
#else
|
||||
# include <Z/hardware/CPU/architecture/Z80.h>
|
||||
#endif
|
||||
|
||||
/** Z80 emulator instance.
|
||||
* @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 @c 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;
|
||||
|
||||
/** 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 needs to read one instruction from
|
||||
* the data bus to service a maskable interrupt (INT) in mode 0.
|
||||
* @param context The value of the member @c context.
|
||||
* @return A 32-bit value containing the bytes of one 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);
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Temporay IX/IY register for instructions with @c DDh/FDh prefix.
|
||||
* @details Since instructions with prefix @c DDh and @c FDh 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;
|
||||
|
||||
/** Temporary storage for opcode fetching.
|
||||
* @details This is an internal private variable. */
|
||||
|
||||
Z32Bit data;
|
||||
} 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.
|
||||
* @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 on the RESET line of a real Z80.
|
||||
* @param object A pointer to a Z80 emulator instance. */
|
||||
|
||||
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.
|
||||
* @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 (NMI).
|
||||
* @details This is equivalent to a pulse on the NMI line of a real Z80.
|
||||
* @param object A pointer to a Z80 emulator instance. */
|
||||
|
||||
CPU_Z80_API void z80_nmi(Z80 *object);
|
||||
|
||||
/** Changes the state of the maskable interrupt (INT).
|
||||
* @details This is equivalent to a change on the INT line of a real Z80.
|
||||
* @param object A pointer to a Z80 emulator instance.
|
||||
* @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_WITH_ABI
|
||||
|
||||
# ifndef CPU_Z80_DEPENDENCIES_H
|
||||
# include <Z/ABIs/generic/emulation.h>
|
||||
# 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_ */
|
||||
22
CITATION.cff
Normal file
22
CITATION.cff
Normal file
@@ -0,0 +1,22 @@
|
||||
abstract: "Zilog Z80 CPU emulator."
|
||||
authors:
|
||||
- family-names: "Sainz de Baranda y Goñi"
|
||||
given-names: "Manuel"
|
||||
orcid: "https://orcid.org/0000-0001-6326-3519"
|
||||
email: "manuel@zxe.io"
|
||||
website: "https://zxe.io"
|
||||
cff-version: 1.2.0
|
||||
date-released: "2022-05-29"
|
||||
keywords:
|
||||
- CPU
|
||||
- LLE
|
||||
- Z80
|
||||
- Zilog
|
||||
- emulator
|
||||
license: LGPL-3.0-or-later
|
||||
message: "If you use this software, please cite it using these metadata."
|
||||
repository-code: "https://github.com/redcode/Z80"
|
||||
title: "Z80"
|
||||
type: software
|
||||
version: 0.2
|
||||
url: "https://zxe.io/software/Z80"
|
||||
29
CMake/FindBreathe.cmake
Normal file
29
CMake/FindBreathe.cmake
Normal file
@@ -0,0 +1,29 @@
|
||||
# FindBreathe.cmake
|
||||
# Copyright (C) 2021 Manuel Sainz de Baranda y Goñi.
|
||||
# This "find module" is DISTRIBUTED AS PUBLIC DOMAIN. No restrictions apply.
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_program(
|
||||
BREATHE_APIDOC_EXECUTABLE
|
||||
NAMES breathe-apidoc
|
||||
DOC "Breathe extension for Sphinx")
|
||||
|
||||
if(BREATHE_APIDOC_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${BREATHE_APIDOC_EXECUTABLE} --version
|
||||
OUTPUT_VARIABLE _output)
|
||||
|
||||
if("${_output}" MATCHES ".* ([^\n]+)\n")
|
||||
set(BREATHE_APIDOC_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(
|
||||
Breathe
|
||||
REQUIRED_VARS BREATHE_APIDOC_EXECUTABLE
|
||||
VERSION_VAR BREATHE_APIDOC_VERSION)
|
||||
|
||||
mark_as_advanced(BREATHE_APIDOC_EXECUTABLE)
|
||||
|
||||
# FindBreathe.cmake EOF
|
||||
29
CMake/FindSphinx.cmake
Normal file
29
CMake/FindSphinx.cmake
Normal file
@@ -0,0 +1,29 @@
|
||||
# FindSphinx.cmake
|
||||
# Copyright (C) 2021 Manuel Sainz de Baranda y Goñi.
|
||||
# This "find module" is DISTRIBUTED AS PUBLIC DOMAIN. No restrictions apply.
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_program(
|
||||
SPHINX_BUILD_EXECUTABLE
|
||||
NAMES sphinx-build
|
||||
DOC "Sphinx Documentation Builder")
|
||||
|
||||
if(SPHINX_BUILD_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${SPHINX_BUILD_EXECUTABLE} --version
|
||||
OUTPUT_VARIABLE _output)
|
||||
|
||||
if("${_output}" MATCHES ".* ([^\n]+)\n")
|
||||
set(SPHINX_BUILD_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(
|
||||
Sphinx
|
||||
REQUIRED_VARS SPHINX_BUILD_EXECUTABLE
|
||||
VERSION_VAR SPHINX_BUILD_VERSION)
|
||||
|
||||
mark_as_advanced(SPHINX_BUILD_EXECUTABLE)
|
||||
|
||||
# FindSphinx.cmake EOF
|
||||
50
CMake/FindZ80.cmake
Normal file
50
CMake/FindZ80.cmake
Normal file
@@ -0,0 +1,50 @@
|
||||
# Z80 - FindZ80.cmake
|
||||
# ______ ______ ______
|
||||
# /\___ \/\ __ \\ __ \
|
||||
# \/__/ /\_\ __ \\ \/\ \
|
||||
# /\_____\\_____\\_____\
|
||||
# Zilog \/_____//_____//_____/ CPU Emulator
|
||||
# Copyright (C) 1999-2022 Manuel Sainz de Baranda y Goñi.
|
||||
# Released under the terms of the GNU Lesser General Public License v3.
|
||||
# This "find module" is DISTRIBUTED AS PUBLIC DOMAIN. No restrictions apply.
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_path(
|
||||
Z80_INCLUDE_DIR
|
||||
"Z80.h"
|
||||
HINTS ${PROJECT_BINARY_DIR}
|
||||
${PROJECT_SOURCE_DIR}
|
||||
PATH_SUFFIXES
|
||||
"deps/Z80/API"
|
||||
"dependencies/Z80/API"
|
||||
"extern/Z80/API"
|
||||
"external/Z80/API"
|
||||
"externals/Z80/API"
|
||||
"kits/Z80/API/"
|
||||
"Z80/API"
|
||||
"../Z80/API"
|
||||
)
|
||||
|
||||
if(Z80_INCLUDE_DIR)
|
||||
file(READ "${Z80_INCLUDE_DIR}/Z80.h" _h)
|
||||
|
||||
if(${_h} MATCHES ".*Z80_LIBRARY_VERSION_STRING \"([^\n]*)\".*")
|
||||
set(Z80_VERSION ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(
|
||||
Z80
|
||||
REQUIRED_VARS Z80_INCLUDE_DIR
|
||||
VERSION_VAR Z80_VERSION
|
||||
)
|
||||
|
||||
if(Z80_FOUND AND NOT TARGET Z80)
|
||||
add_library(Z80 IMPORTED)
|
||||
target_include_directories(Z80 INTERFACE ${Z80_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(Z80_INCLUDE_DIR)
|
||||
|
||||
# FindZ80.cmake EOF
|
||||
60
CMake/FindZeta.cmake
Normal file
60
CMake/FindZeta.cmake
Normal file
@@ -0,0 +1,60 @@
|
||||
# Zeta - FindZeta.cmake
|
||||
# ______ ____________ ___
|
||||
# |__ /| ___|__ __|/ \
|
||||
# / /_| __| | | / * \
|
||||
# /_____|_____| |__|/__/ \__\
|
||||
# Copyright (C) 2006-2022 Manuel Sainz de Baranda y Goñi.
|
||||
# # Released under the terms of the GNU Lesser General Public License v3.
|
||||
# This "find module" is DISTRIBUTED AS PUBLIC DOMAIN. No restrictions apply.
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_path(
|
||||
Zeta_INCLUDE_DIR "Z/version.h"
|
||||
PATHS "${PROJECT_BINARY_DIR}/Zeta/API"
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
"${PROJECT_SOURCE_DIR}/Zeta/API"
|
||||
"${PROJECT_SOURCE_DIR}"
|
||||
"${PROJECT_SOURCE_DIR}/dependencies/Zeta/API"
|
||||
"${PROJECT_SOURCE_DIR}/dependencies"
|
||||
"${PROJECT_SOURCE_DIR}/deps/Zeta/API"
|
||||
"${PROJECT_SOURCE_DIR}/deps"
|
||||
"${PROJECT_SOURCE_DIR}/extern/Zeta/API"
|
||||
"${PROJECT_SOURCE_DIR}/extern"
|
||||
"${PROJECT_SOURCE_DIR}/external/Zeta/API"
|
||||
"${PROJECT_SOURCE_DIR}/external"
|
||||
"${PROJECT_SOURCE_DIR}/externals/Zeta/API"
|
||||
"${PROJECT_SOURCE_DIR}/externals"
|
||||
"${PROJECT_SOURCE_DIR}/kits/Zeta/API"
|
||||
"${PROJECT_SOURCE_DIR}/kits"
|
||||
"${PROJECT_SOURCE_DIR}/../Zeta/API"
|
||||
"${PROJECT_SOURCE_DIR}/.."
|
||||
ENV CPATH
|
||||
ENV C_INCLUDE_PATH
|
||||
ENV CPLUS_INCLUDE_PATH
|
||||
ENV OBJC_INCLUDE_PATH)
|
||||
|
||||
if(Zeta_INCLUDE_DIR AND EXISTS "${Zeta_INCLUDE_DIR}/Z/version.h")
|
||||
file(READ "${Zeta_INCLUDE_DIR}/Z/version.h" _)
|
||||
|
||||
if(_ MATCHES ".*Z_LIBRARY_VERSION_STRING \"([^\n]*)\".*")
|
||||
set(Zeta_VERSION ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
|
||||
unset(_)
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(
|
||||
Zeta
|
||||
FOUND_VAR Zeta_FOUND
|
||||
REQUIRED_VARS Zeta_INCLUDE_DIR Zeta_VERSION
|
||||
VERSION_VAR Zeta_VERSION)
|
||||
|
||||
if(Zeta_FOUND AND NOT (TARGET Zeta))
|
||||
add_library(Zeta INTERFACE IMPORTED)
|
||||
target_include_directories(Zeta INTERFACE ${Zeta_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(Zeta_INCLUDE_DIR)
|
||||
|
||||
# FindZeta.cmake EOF
|
||||
373
CMakeLists.txt
Normal file
373
CMakeLists.txt
Normal file
@@ -0,0 +1,373 @@
|
||||
# Z80 - CMakeLists.txt
|
||||
# ______ ______ ______
|
||||
# /\___ \/\ __ \\ __ \
|
||||
# \/__/ /\_\ __ \\ \/\ \
|
||||
# /\_____\\_____\\_____\
|
||||
# Zilog \/_____//_____//_____/ CPU Emulator
|
||||
# Copyright (C) 1999-2022 Manuel Sainz de Baranda y Goñi.
|
||||
# Released under the terms of the GNU Lesser General Public License v3.
|
||||
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
if( CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR AND
|
||||
NOT CMAKE_BUILD_TYPE AND
|
||||
NOT CMAKE_CONFIGURATION_TYPES
|
||||
)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/API/Z80.h" _)
|
||||
string(REGEX MATCH ".*Z80_LIBRARY_VERSION_STRING \"([^\n]*)\".*" _ ${_})
|
||||
|
||||
project(Z80
|
||||
VERSION ${CMAKE_MATCH_1}
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Zilog Z80 CPU emulator")
|
||||
|
||||
unset(_)
|
||||
message("${PROJECT_NAME} v${PROJECT_VERSION}")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(DEFINED ${PROJECT_NAME}_SHARED_LIBS)
|
||||
set(BUILD_SHARED_LIBS "${${PROJECT_NAME}_SHARED_LIBS}")
|
||||
endif()
|
||||
|
||||
option(${PROJECT_NAME}_DOWNLOAD_TEST_FILES
|
||||
"Download the firmware and software used by the testing tool."
|
||||
NO)
|
||||
|
||||
set(${PROJECT_NAME}_INSTALL_CMAKEDIR
|
||||
"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE STRING
|
||||
"Specify the directory in which to install the CMake config-file package.")
|
||||
|
||||
set(${PROJECT_NAME}_INSTALL_PKGCONFIGDIR
|
||||
"${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE STRING
|
||||
"Specify the directory in which to install the pkg-config file.")
|
||||
|
||||
set(${PROJECT_NAME}_NOSTDLIB_FLAGS
|
||||
"Auto" CACHE STRING
|
||||
"Specify the linker flags used to avoid linking against system libraries.")
|
||||
|
||||
set(${PROJECT_NAME}_SPHINX_HTML_THEME
|
||||
"" CACHE STRING
|
||||
"Specify the Sphinx theme for the documentation in HTML format.")
|
||||
|
||||
option(${PROJECT_NAME}_WITH_CMAKE_SUPPORT
|
||||
"Generate and install the CMake config-file package."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_HTML_DOCUMENTATION
|
||||
"Build and install the documentation in HTML format."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_PDF_DOCUMENTATION
|
||||
"Build and install the documentation in PDF format."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_PKGCONFIG_SUPPORT
|
||||
"Generate and install the pkg-config file."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_STANDARD_DOCUMENTS
|
||||
"Install the standard text documents distributed with the package: \
|
||||
AUTHORS, COPYING, COPYING.LESSER, HISTORY, README and THANKS."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_TESTS
|
||||
"Build the testing tool."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_EXECUTE
|
||||
"Build the implementation of the z80_execute function."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_FULL_IM0
|
||||
"Build the full implementation of the interrupt mode 0 rather than the \
|
||||
reduced one."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_Q
|
||||
"Build the implementation of the Q \"register\"."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_RESET_SIGNAL
|
||||
"Build the implementation of the normal RESET signal."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_SPECIAL_RESET_SIGNAL
|
||||
"Build the implementation of the special RESET signal."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_UNOFFICIAL_RETI
|
||||
"Configure the ED5Dh, ED6Dh and ED7Dh undocumented instructions as \"reti\" \
|
||||
instead of \"retn\"."
|
||||
NO)
|
||||
|
||||
option(${PROJECT_NAME}_WITH_ZILOG_NMOS_LD_A_IR_BUG
|
||||
"Build the implementation of the bug affecting the Zilog Z80 NMOS, which \
|
||||
causes the P/V flag to be reset when a maskable interrupt is accepted \
|
||||
during the execution of the \"ld a,{i|r}\" instructions."
|
||||
NO)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
|
||||
find_package(Zeta REQUIRED)
|
||||
|
||||
add_library(
|
||||
${PROJECT_NAME}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/API/Z80.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/sources/Z80.c")
|
||||
|
||||
set_target_properties(
|
||||
${PROJECT_NAME} PROPERTIES
|
||||
C_STANDARD 99
|
||||
C_STANDARD_REQUIRED NO
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
DEBUG_POSTFIX "-debug"
|
||||
PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/API/Z80.h")
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Zeta)
|
||||
|
||||
target_include_directories(
|
||||
${PROJECT_NAME} PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/API>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(WIN32)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/sources/Z80.rc.in"
|
||||
"${PROJECT_BINARY_DIR}/Z80.rc"
|
||||
@ONLY)
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE "${PROJECT_BINARY_DIR}/Z80.rc")
|
||||
endif()
|
||||
|
||||
if (${PROJECT_NAME}_NOSTDLIB_FLAGS STREQUAL "Auto")
|
||||
if(MSVC)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE Z80_WITH_WINDOWS_DLL_MAIN)
|
||||
target_link_options(${PROJECT_NAME} PRIVATE "/NODEFAULTLIB")
|
||||
elseif(APPLE)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "^(AppleClang|Clang)$")
|
||||
target_link_options(${PROJECT_NAME} PRIVATE "LINKER:-dead_strip_dylibs")
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
target_link_options(${PROJECT_NAME} PRIVATE "LINKER:-dead_strip_dylibs;-nolibc")
|
||||
endif()
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "^(ARMClang|Clang|GNU|Intel|TinyCC|XL|XLClang)$")
|
||||
target_link_options(${PROJECT_NAME} PRIVATE "-nostdlib")
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "PGI")
|
||||
target_link_options(${PROJECT_NAME} PRIVATE "-Mnostdlib")
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro")
|
||||
target_link_options(${PROJECT_NAME} PRIVATE "-xnolib")
|
||||
endif()
|
||||
elseif(NOT ${PROJECT_NAME}_NOSTDLIB_FLAGS STREQUAL "")
|
||||
target_link_options(${PROJECT_NAME} PRIVATE ${${PROJECT_NAME}_NOSTDLIB_FLAGS})
|
||||
endif()
|
||||
else()
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC Z80_STATIC)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_EXECUTE)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE Z80_WITH_EXECUTE)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_FULL_IM0)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE Z80_WITH_FULL_IM0)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_Q)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE Z80_WITH_Q)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_RESET_SIGNAL)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE Z80_WITH_RESET_SIGNAL)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_SPECIAL_RESET_SIGNAL)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE Z80_WITH_SPECIAL_RESET_SIGNAL)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_UNOFFICIAL_RETI)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE Z80_WITH_UNOFFICIAL_RETI)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_ZILOG_NMOS_LD_A_IR_BUG)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE Z80_WITH_ZILOG_NMOS_LD_A_IR_BUG)
|
||||
endif()
|
||||
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
EXPORT "${PROJECT_NAME}_Targets"
|
||||
RUNTIME COMPONENT "${PROJECT_NAME}_Runtime"
|
||||
LIBRARY COMPONENT "${PROJECT_NAME}_Runtime"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
NAMELINK_COMPONENT "${PROJECT_NAME}_Development"
|
||||
ARCHIVE COMPONENT "${PROJECT_NAME}_Development"
|
||||
PUBLIC_HEADER
|
||||
COMPONENT "${PROJECT_NAME}_Development"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
|
||||
if(${PROJECT_NAME}_WITH_CMAKE_SUPPORT OR ${PROJECT_NAME}_WITH_PKGCONFIG_SUPPORT)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
if(${PROJECT_NAME}_WITH_CMAKE_SUPPORT)
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set(_type Shared)
|
||||
else()
|
||||
set(_type Static)
|
||||
endif()
|
||||
|
||||
install(EXPORT "${PROJECT_NAME}_Targets"
|
||||
DESTINATION ${${PROJECT_NAME}_INSTALL_CMAKEDIR}
|
||||
FILE ${PROJECT_NAME}${_type}Targets.cmake
|
||||
COMPONENT ${PROJECT_NAME}_Development)
|
||||
|
||||
unset(_type)
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
|
||||
configure_package_config_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/support/${PROJECT_NAME}Config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION ${${PROJECT_NAME}_INSTALL_CMAKEDIR})
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
DESTINATION ${${PROJECT_NAME}_INSTALL_CMAKEDIR}
|
||||
COMPONENT ${PROJECT_NAME}_Development)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_PKGCONFIG_SUPPORT)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/support/${PROJECT_NAME}.pc.in"
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||
@ONLY)
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||
DESTINATION ${${PROJECT_NAME}_INSTALL_PKGCONFIGDIR}
|
||||
COMPONENT ${PROJECT_NAME}_Development)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_STANDARD_DOCUMENTS)
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/AUTHORS"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/COPYING"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/COPYING.LESSER"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/HISTORY"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/README"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/THANKS"
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_HTML_DOCUMENTATION OR ${PROJECT_NAME}_WITH_PDF_DOCUMENTATION)
|
||||
add_subdirectory(documentation)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_TESTS)
|
||||
include(CTest)
|
||||
|
||||
find_package(ZLIB QUIET)
|
||||
find_package(libzip QUIET)
|
||||
|
||||
add_executable("test-${PROJECT_NAME}" "${CMAKE_CURRENT_SOURCE_DIR}/sources/test-Z80.c")
|
||||
target_link_libraries("test-${PROJECT_NAME}" PRIVATE ${PROJECT_NAME})
|
||||
|
||||
if(ZLIB_FOUND AND libzip_FOUND)
|
||||
target_link_libraries("test-${PROJECT_NAME}" PRIVATE z libzip::zip)
|
||||
target_compile_definitions("test-${PROJECT_NAME}" PRIVATE TEST_Z80_WITH_ARCHIVE_EXTRACTION)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_EXECUTE)
|
||||
target_compile_definitions("test-${PROJECT_NAME}" PRIVATE TEST_Z80_WITH_EXECUTE)
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_DOWNLOAD_TEST_FILES)
|
||||
function(_download_files sha512sum_file base_url downloads_dir)
|
||||
file(STRINGS "${sha512sum_file}" _lines)
|
||||
|
||||
foreach(_line ${_lines})
|
||||
string(STRIP ${_line} _line)
|
||||
string(SUBSTRING ${_line} 0 128 _sha512)
|
||||
string(SUBSTRING ${_line} 130 -1 _file_path)
|
||||
get_filename_component(_file_full_name ${_file_path} NAME)
|
||||
|
||||
set(_file_url "${base_url}/${_file_path}")
|
||||
message(STATUS "Downloading \"${_file_full_name}\"")
|
||||
string(REPLACE " " "%20" _file_url ${_file_url})
|
||||
string(REPLACE "!" "%21" _file_url ${_file_url})
|
||||
string(REPLACE "(" "%28" _file_url ${_file_url})
|
||||
string(REPLACE ")" "%29" _file_url ${_file_url})
|
||||
string(REPLACE "[" "%5B" _file_url ${_file_url})
|
||||
string(REPLACE "]" "%5D" _file_url ${_file_url})
|
||||
|
||||
file( DOWNLOAD
|
||||
"${_file_url}"
|
||||
"${downloads_dir}/${_file_path}"
|
||||
EXPECTED_HASH SHA512=${_sha512})
|
||||
|
||||
if ( NOT "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 3.18 AND
|
||||
(NOT ZLIB_FOUND OR NOT libzip_FOUND)
|
||||
)
|
||||
get_filename_component(_file_extension ${_file_full_name} LAST_EXT)
|
||||
|
||||
if(_file_extension STREQUAL ".gz" OR _file_extension STREQUAL ".zip")
|
||||
get_filename_component(_subdirectory ${_file_path} DIRECTORY)
|
||||
|
||||
if(_file_extension STREQUAL ".gz")
|
||||
set(_extract_pattern "*zex*.com")
|
||||
else()
|
||||
set(_extract_pattern "*.tap")
|
||||
endif()
|
||||
|
||||
file( ARCHIVE_EXTRACT
|
||||
INPUT "${downloads_dir}/${_file_path}"
|
||||
DESTINATION "${downloads_dir}/${_subdirectory}"
|
||||
PATTERNS ${_extract_pattern}
|
||||
VERBOSE)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
_download_files(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/support/firmware.sha512sum"
|
||||
"http://zxe.io/downloads/support/firmware"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/downloads/firmware")
|
||||
|
||||
_download_files(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/support/software.sha512sum"
|
||||
"http://zxe.io/downloads/support/software"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/downloads/software")
|
||||
|
||||
if ( "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 3.18 AND
|
||||
(NOT ZLIB_FOUND OR NOT libzip_FOUND)
|
||||
)
|
||||
message(WARNING
|
||||
"libzip or zlib was not found on your system, which will cause the "
|
||||
"test-Z80 tool to be built without archive extraction support. When "
|
||||
"this happens, the build script extracts those downloaded tests that "
|
||||
"are compressed so that test-Z80 can use them later, but this has "
|
||||
"failed because the version of CMake you are using is too old and "
|
||||
"does not support archive extraction either.\n"
|
||||
"To fix this, extract all files with \".tar.gz\" or \".zip\" "
|
||||
"extension located in "
|
||||
"\"${CMAKE_CURRENT_BINARY_DIR}/downloads/software/**\" "
|
||||
"to the same directory.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_test(
|
||||
NAME "test-${PROJECT_NAME}"
|
||||
COMMAND "test-${PROJECT_NAME}"
|
||||
--path "${CMAKE_CURRENT_BINARY_DIR}/downloads/firmware"
|
||||
--path "${CMAKE_CURRENT_BINARY_DIR}/downloads/software/POSIX"
|
||||
--path "${CMAKE_CURRENT_BINARY_DIR}/downloads/software/ZX Spectrum"
|
||||
--all
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
# CMakeLists.txt EOF
|
||||
165
COPYING.LESSER
Normal file
165
COPYING.LESSER
Normal file
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
101
HISTORY
101
HISTORY
@@ -1,3 +1,100 @@
|
||||
Z80 v0.1 (2018-11-10)
|
||||
Z80 v0.2 (2022-XX-XX)
|
||||
=====================
|
||||
|
||||
+ Initial release.
|
||||
This is an important update that addresses a number of issues and also includes
|
||||
new features. Please note that the changes introduced in this release break the
|
||||
binary compatibility with the previous version.
|
||||
|
||||
Changes:
|
||||
1. Changed the license from GPL to LGPL (by popular request).
|
||||
2. Moved the public header from <emulation/CPU/Z80.h> to <Z80.h>.
|
||||
3. Removed the Xcode project.
|
||||
4. Switched the build system from Premake to CMake.
|
||||
5. Switched to Zeta v0.1.
|
||||
6. Added pkg-config support.
|
||||
7. Added the .vimrc dotfile.
|
||||
8. Added the CITATION.cff file.
|
||||
9. Added the file_id.diz file.
|
||||
10. Added the THANKS file.
|
||||
11. Added detailed documentation.
|
||||
12. Added tests.
|
||||
13. Added public macros for checking the library version.
|
||||
14. Added public macros with bit masks for working with flags.
|
||||
15. Added public macros for accessing the 16-bit registers.
|
||||
16. Added the z80_execute function to run a simplified emulation without RESET
|
||||
and interrupts.
|
||||
17. Added the z80_refresh_address function to get the refresh address of the
|
||||
current M1 cycle.
|
||||
18. Added the z80_in_cycle and z80_out_cycle functions to get the clock cycle on
|
||||
which the I/O M-cycle occurs, relative to the start of the instruction.
|
||||
19. Fixed a bug in the "sll" instruction.
|
||||
20. Fixed a bug in the INX and OUTX macros affecting the S and N flags.
|
||||
21. Fixed a bug in the OUTX macro affecting the MSByte of the port number.
|
||||
22. Fixed the clock cycles of the "dec XY" and "in (c)" instructions.
|
||||
23. Fixed the read_16 function so that the order in which the compiler evaluates
|
||||
expressions does not affect the order of the memory read operations.
|
||||
24. Fixed the order in which the memory write operations are performed when the
|
||||
SP register is involved. This affects the NMI response, the INT response in
|
||||
modes 1 and 2, and the following instructions: "ex (sp),{hl|XY}", "push TT",
|
||||
"push XY", "call WORD", "call Z,WORD" and "rst N".
|
||||
25. Fixed the handling of illegal instructions to avoid stack overflows in long
|
||||
sequences of DDh/FDh prefixes.
|
||||
26. Fixed several implicit conversions to avoid warnings about loss of sign and
|
||||
precision.
|
||||
27. Fixed some bitwise operations to avoid undefined behavior and arithmetic
|
||||
right shifts on signed integers.
|
||||
28. Fixed violations of the C standard in several identifiers.
|
||||
29. Renamed the 8-bit register lists: X/Y to J/K; J/K and P/Q to O/P.
|
||||
30. Replaced all P/V overflow computation functions with a single, faster macro.
|
||||
31. Replaced all register resolution functions with macros.
|
||||
32. Replaced all "ld {J,K|O,P}" instructions that have the same destination and
|
||||
source register with NOPs.
|
||||
33. Reimplemented the HALT state. The emulation should now be fully accurate.
|
||||
HALTskip is also supported.
|
||||
34. Added optional emulation of the normal and special RESET signals, along with
|
||||
the new z80_reset and z80_special_reset functions to emit them. The old
|
||||
z80_reset function is now called z80_instant_reset.
|
||||
35. Added emulation of the NMI acknowledge M-cycle through the new Z80::nmia
|
||||
callback.
|
||||
36. Added emulation of the INT acknowledge M-cycle through the new Z80::inta
|
||||
callback, which replaces Z80::int_data.
|
||||
37. Added optional full emulation of the interrupt mode 0, along with the new
|
||||
Z80::int_fetch callback to perform bus read operations on instruction data.
|
||||
If not enabled at compile-time, the old simplified emulation is built, which
|
||||
supports only the most typical instructions.
|
||||
38. Added accurate flag behavior in the following instructions: "ldir", "lddr",
|
||||
"cpir", "cpdr", "inir", "indr", "otir" and "otdr".
|
||||
39. Added emulation of the interrupt acceptance deferral that occurs during the
|
||||
"reti" and "retn" instructions.
|
||||
40. Added MEMPTR emulation. The "bit N,(hl)" instruction now produces a correct
|
||||
value of F.
|
||||
41. Added optional emulation of the Q "register". If enabled at compile-time,
|
||||
the "ccf" and "scf" instructions produce a correct value of F.
|
||||
42. Added emulation options that can be configured at runtime.
|
||||
43. Added emulation of the "out (c),255" instruction (Zilog Z80 CMOS).
|
||||
44. Added optional emulation of the bug affecting the "ld a,{i|r}" instructions
|
||||
(Zilog Z80 NMOS). If enabled at compile-time, the P/V flag is reset when an
|
||||
INT is accepted during the execution of these instructions.
|
||||
45. Added the Z80::fetch_opcode and Z80::fetch callbacks to perform opcode fetch
|
||||
operations and memory read operations on instruction data respectively.
|
||||
46. Added hooking functionality through the "ld h,h" instruction and the new
|
||||
Z80::hook callback.
|
||||
47. Added the Z80::nop callback to perform disregarded opcode fetch operations
|
||||
during internal NOP M-cycles.
|
||||
48. Added four callbacks to notify the execution of important instructions:
|
||||
Z80::ld_i_a, Z80::ld_r_a, Z80::reti and Z80::retn.
|
||||
49. Removed Z80::state. Replaced with individual members for the registers, the
|
||||
interrupt enable flip-flops and the interrupt mode.
|
||||
50. Removed the superfluous EI flag. The previous opcode is checked instead,
|
||||
which is faster and makes the Z80 object smaller.
|
||||
51. Removed all module-related stuff.
|
||||
52. Optimizations in flag computation and condition evaluation.
|
||||
53. New source code comments and improvements to existing ones.
|
||||
54. Improved code aesthetics.
|
||||
55. Other improvements, optimizations and minor changes.
|
||||
|
||||
|
||||
Z80 v0.1 (2018-11-10)
|
||||
=====================
|
||||
|
||||
Initial public release.
|
||||
|
||||
377
README
377
README
@@ -1,84 +1,319 @@
|
||||
______ ______ ______
|
||||
/\___ \ /\ __ \/\ __ \
|
||||
\/__/ /_\ \ __ \ \ \/\ \
|
||||
/\_____\ \_____\ \_____\
|
||||
Zilog \/_____/\/_____/\/_____/ CPU Emulator v0.1
|
||||
Copyright (C) 1999-2018 Manuel Sainz de Baranda y Goñi <manuel@zxe.io>
|
||||
|
||||
This is a Zilog Z80 CPU emulator that I wrote many years ago. It is fast, small,
|
||||
easy to understand, and the code is profusely commented.
|
||||
________________ ________________ _________________
|
||||
| /\ | || |
|
||||
|_______ / / | ____ || ____ |
|
||||
\_____/ / / | |____| || |___/| |
|
||||
/ / / | || | | | |
|
||||
/ / / | ____ || | | | |
|
||||
/ /_/_____| |____| || |__|_| |
|
||||
/ || || |
|
||||
/_______________||________________||________________|
|
||||
\________________\\______________//________________/
|
||||
|
||||
______________________________________________________________________________
|
||||
| |
|
||||
| Zilog Z80 CPU Emulator |
|
||||
| version 0.2 |
|
||||
| |
|
||||
| Copyright (C) 1999-2022 Manuel Sainz de Baranda y Goñi |
|
||||
| Released under the terms of the GNU Lesser General Public License v3 |
|
||||
| |
|
||||
| https://zxe.io/software/Z80 |
|
||||
| |
|
||||
'=============================================================================='
|
||||
|
||||
|
||||
Building
|
||||
========
|
||||
1. Introduction
|
||||
================
|
||||
|
||||
You must first install Z <http://zeta.st>, a header-only library that provides
|
||||
types and macros. This is the only dependency, the emulator does not use the C
|
||||
standard library or its headers. Then add Z80.h and Z80.c to your project and
|
||||
configure its build system so that CPU_Z80_STATIC and CPU_Z80_USE_LOCAL_HEADER
|
||||
are predefined when compiling the sources.
|
||||
The Z80 library implements a fast, small and accurate emulator of the Zilog Z80.
|
||||
It emulates all that is known to date about this CPU, including the undocumented
|
||||
behaviour, MEMPTR, Q and the special RESET. It also has the honor of having been
|
||||
the first open source project to provide full emulation of the interrupt mode 0.
|
||||
|
||||
If you preffer to build the emulator as a library, you can use premake4:
|
||||
|
||||
$ cd building
|
||||
$ premake4 gmake # generate Makefile
|
||||
$ make help # list available targets
|
||||
$ make [config=<configuration>] [target] # build the emulator
|
||||
|
||||
There is also an Xcode project in "development/Xcode" with several targets:
|
||||
|
||||
Z80 (dynamic)
|
||||
Shared library.
|
||||
|
||||
Z80 (dynamic module)
|
||||
Shared library with a generic module ABI to be used in modular multi-machine
|
||||
emulators.
|
||||
|
||||
Z80 (static)
|
||||
Static library.
|
||||
|
||||
Z80 (static module)
|
||||
Static library with a generic CPU emulator ABI to be used in monolithic
|
||||
multi-machine emulators.
|
||||
The source code is written in ANSI C for maximum portability and is extensively
|
||||
commented. The aim has been to write a well-structured, easy to understand piece
|
||||
of software; something solid and elegant that can stand the test of time with no
|
||||
need for major changes.
|
||||
|
||||
|
||||
Code configuration
|
||||
==================
|
||||
2. Emulation accuracy
|
||||
======================
|
||||
|
||||
There are some predefined macros that control the compilation:
|
||||
The Zilog Z80 emulator has a classic design with instruction-level granularity.
|
||||
This provides the best performance when speed is a critical factor, while still
|
||||
offering a reasonable flexibility to achieve precision down to the T-state level
|
||||
when accuracy is imperative.
|
||||
|
||||
CPU_Z80_DEPENDENCIES_H
|
||||
If defined, it replaces the inclusion of any external header with this one.
|
||||
If you don't want to use Z, you can provide your own header with the types
|
||||
and macros used by the emulator.
|
||||
Instruction-level granularity implies that, except in a few well-defined cases,
|
||||
the execution of a given instruction cannot stop until all its internal M-cycles
|
||||
are completed. This kind of emulation is also carried out in an efficient way:
|
||||
the pertinent registers are modified only once per instruction and the T-state
|
||||
counter is updated only after a whole instruction is executed.
|
||||
|
||||
CPU_Z80_HIDE_ABI
|
||||
Makes the generic CPU emulator ABI private.
|
||||
|
||||
CPU_Z80_HIDE_API
|
||||
Makes the public functions private.
|
||||
|
||||
CPU_Z80_STATIC
|
||||
You need to define this to compile or use the emulator as a static library
|
||||
or if you have added Z80.h and Z80.c to your project.
|
||||
|
||||
CPU_Z80_USE_LOCAL_HEADER
|
||||
Use this if you have imported Z80.h and Z80.c to your project. Z80.c will
|
||||
#include "Z80.h" instead of <emulation/CPU/Z80.h>.
|
||||
|
||||
CPU_Z80_WITH_ABI
|
||||
Builds the generic CPU emulator ABI and declares its prototype in Z80.h.
|
||||
|
||||
CPU_Z80_WITH_MODULE_ABI
|
||||
Builds the generic module ABI. This macro also enables CPU_Z80_WITH_ABI, so
|
||||
the generic CPU emulator ABI will be built too. This option is intended to
|
||||
be used when building a true module loadable at runtime with dlopen(),
|
||||
LoadLibrary() or similar. The ABI module can be accessed via the weak symbol
|
||||
__module_abi__.
|
||||
That said, instructions, flags, memory accesses, interrupt and reset responses,
|
||||
clock cycles, etc. are accurately emulated as far as is known, according to the
|
||||
technical documentation available, the findings made after decades of research
|
||||
on the Z80 and electronic simulations. And, of course, the emulator passes the
|
||||
most exhaustive tests written to date such as Patrik Rak's "Zilog Z80 CPU Test
|
||||
Suite", Frank D. Cringle's "Z80 Instruction Set Exerciser", Mark Woodmass' "Z80
|
||||
Test Suite" and Peter Helcmanovsky's "Z80 Block Flags Test", to name a few.
|
||||
|
||||
|
||||
Use in Proprietary Software
|
||||
===========================
|
||||
3. Installation
|
||||
================
|
||||
|
||||
This library is released under the terms of the GNU General Public License v3,
|
||||
but I can license it for non-free/propietary projects if you contact me.
|
||||
You will need CMake v3.14 or later to build the package and, optionally, recent
|
||||
versions of Doxygen, Sphinx and Breathe to compile the documentation. Also make
|
||||
sure you have LaTeX with PDF support installed on your system in case you want
|
||||
to generate the documentation in PDF format.
|
||||
|
||||
The emulator requires some types and macros included in Zeta (https://zeta.st),
|
||||
a dependency-free, header-only library used to retain compatibility with most C
|
||||
compilers. Install Zeta or extract its official source code package to the same
|
||||
directory of this README or its parent directory. Zeta is the sole dependency;
|
||||
the emulator is a freestanding implementation and as such does not depend on the
|
||||
C standard library.
|
||||
|
||||
Once all requirements are met, create a directory and run cmake from there to
|
||||
prepare the build system:
|
||||
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake <directory of this README> [options]
|
||||
|
||||
The resulting build files can be configured by passing options to cmake. To show
|
||||
a complete list of those available along with their current settings, type the
|
||||
following:
|
||||
|
||||
$ cmake -LAH
|
||||
|
||||
If in doubt, read the CMake documentation for more information on configuration
|
||||
options. The following are some of the most relevant standard options of CMake:
|
||||
|
||||
-DBUILD_SHARED_LIBS=(YES|NO)
|
||||
Build the project as a shared library rather than a static one.
|
||||
The default is NO.
|
||||
|
||||
-DCMAKE_BUILD_TYPE=(Debug|Release|RelWithDebInfo)
|
||||
Choose the type of build (configuration) to generate.
|
||||
The default is Release.
|
||||
|
||||
-DCMAKE_INSTALL_PREFIX="<path>"
|
||||
Specify the installation prefix on UNIX and UNIX-like operating systems.
|
||||
The default is "/usr/local".
|
||||
|
||||
Package-specific options are prefixed with "Z80_" and can be divided into two
|
||||
groups. The first one controls aspects not related to the source code of the
|
||||
library:
|
||||
|
||||
-DZ80_DOWNLOAD_TEST_FILES=(YES|NO)
|
||||
Download the firmware and software used by the testing tool.
|
||||
The default is NO.
|
||||
|
||||
-DZ80_INSTALL_CMAKEDIR="<path>"
|
||||
Specify the directory in which to install the CMake config-file package.
|
||||
The default is "${CMAKE_INSTALL_LIBDIR}/cmake/Z80".
|
||||
|
||||
-DZ80_INSTALL_PKGCONFIGDIR="<path>"
|
||||
Specify the directory in which to install the pkg-config file.
|
||||
The default is "${CMAKE_INSTALL_LIBDIR}/pkgconfig".
|
||||
|
||||
-DZ80_NOSTDLIB_FLAGS=(Auto|[<flag>[;<flag>...]])
|
||||
Specify the linker flags used to avoid linking against system libraries.
|
||||
The default is Auto (autoconfigure flags). If you get linker errors, set
|
||||
this option to "".
|
||||
|
||||
-DZ80_SHARED_LIBS=(YES|NO)
|
||||
Build the project as a shared library rather than a static one.
|
||||
This option takes precedence over "BUILD_SHARED_LIBS".
|
||||
Not defined by default.
|
||||
|
||||
-DZ80_SPHINX_HTML_THEME="[<name>]"
|
||||
Specify the Sphinx theme for the documentation in HTML format.
|
||||
The default is "" (use the default theme).
|
||||
|
||||
-DZ80_WITH_CMAKE_SUPPORT=(YES|NO)
|
||||
Generate and install the CMake config-file package.
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_HTML_DOCUMENTATION=(YES|NO)
|
||||
Build and install the documentation in HTML format.
|
||||
It requires Doxygen, Sphinx and Breathe.
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_PDF_DOCUMENTATION=(YES|NO)
|
||||
Build and install the documentation in PDF format.
|
||||
It requires Doxygen, Sphinx, Breathe and LaTeX with PDF support.
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_PKGCONFIG_SUPPORT=(YES|NO)
|
||||
Generate and install the pkg-config file.
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_STANDARD_DOCUMENTS=(YES|NO)
|
||||
Install the standard text documents distributed with the package:
|
||||
AUTHORS, COPYING, COPYING.LESSER, HISTORY, README and THANKS.
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_TESTS=(YES|NO)
|
||||
Build the testing tool.
|
||||
The default is NO.
|
||||
|
||||
The second group of package-specific options configures the source code of the
|
||||
library by predefining macros that enable optional implementations:
|
||||
|
||||
-DZ80_WITH_EXECUTE=(YES|NO)
|
||||
Build the implementation of the z80_execute function.
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_FULL_IM0=(YES|NO)
|
||||
Build the full implementation of the interrupt mode 0 rather than the
|
||||
reduced one.
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_Q=(YES|NO)
|
||||
Build the implementation of the Q "register".
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_RESET_SIGNAL=(YES|NO)
|
||||
Build the implementation of the normal RESET signal.
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_SPECIAL_RESET_SIGNAL=(YES|NO)
|
||||
Build the implementation of the special RESET signal.
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_UNOFFICIAL_RETI=(YES|NO)
|
||||
Configure the ED5Dh, ED6Dh and ED7Dh undocumented instructions as "reti"
|
||||
instead of "retn".
|
||||
The default is NO.
|
||||
|
||||
-DZ80_WITH_ZILOG_NMOS_LD_A_IR_BUG=(YES|NO)
|
||||
Build the implementation of the bug affecting the Zilog Z80 NMOS, which
|
||||
causes the P/V flag to be reset when a maskable interrupt is accepted
|
||||
during the execution of the "ld a,{i|r}" instructions.
|
||||
The default is NO.
|
||||
|
||||
Package maintainers should use at least the following options for both shared and
|
||||
static library targets:
|
||||
|
||||
-DZ80_WITH_EXECUTE=YES
|
||||
-DZ80_WITH_FULL_IM0=YES
|
||||
-DZ80_WITH_Q=YES
|
||||
-DZ80_WITH_RESET_SIGNAL=YES
|
||||
-DZ80_WITH_ZILOG_NMOS_LD_A_IR_BUG=YES
|
||||
|
||||
Finally, once the build system is configured according to your needs, build and
|
||||
install the package:
|
||||
|
||||
$ make
|
||||
# make install/strip
|
||||
|
||||
|
||||
4. Integration
|
||||
===============
|
||||
|
||||
4.1. As an external dependency in CMake-based projects
|
||||
|
||||
The Z80 library includes find-modules and a config-file package for integration
|
||||
into CMake-based projects. It is recommended to always copy the FindZ80.cmake
|
||||
and FindZeta.cmake files into the CMake modules directory of projects that use
|
||||
the library as an external dependency. This will allow CMake to find the library
|
||||
if the necessary config-file packages are not installed on the system.
|
||||
|
||||
Both the config-file package and the find-module support dual installations of
|
||||
the shared and static versions of the Z80 library. You can specify the linking
|
||||
method by using the component mechanism of "find_package".
|
||||
|
||||
Example:
|
||||
|
||||
find_package(Z80 REQUIRED [Shared|Static])
|
||||
target_link_libraries(your-target Z80)
|
||||
|
||||
Omitting the linking method will select the "Shared" version of the library or,
|
||||
if not installed, the "Static" version instead.
|
||||
|
||||
4.2. As a CMake subproject
|
||||
|
||||
To embed the library as a CMake subproject, just place its entire source tree
|
||||
into a subdirectory of your project.
|
||||
|
||||
It is advisable to configure the library in the CMakeLists.txt of your project.
|
||||
This will prevent the user from having to specify configuration options of the
|
||||
Z80 subproject through the CMake command line when building the main project.
|
||||
As noted in the "Installation" section of this document, all package-specific
|
||||
options are prefixed with "Z80_", so, in a normal scenario, there should be no
|
||||
risk of name collision with the options and variables of the parent project.
|
||||
|
||||
Example:
|
||||
|
||||
set(Z80_SHARED_LIBS NO CACHE BOOL "")
|
||||
set(Z80_WITH_Q YES CACHE BOOL "")
|
||||
set(Z80_WITH_ZILOG_NMOS_LD_A_IR_BUG YES CACHE BOOL "")
|
||||
|
||||
add_subdirectory(dependencies/Z80)
|
||||
target_link_libraries(your-target Z80)
|
||||
|
||||
It is important to set the "Z80_SHARED_LIBS" option. Otherwise CMake will build
|
||||
the library type indicated by "BUILD_SHARED_LIBS", which may not be the desired
|
||||
one.
|
||||
|
||||
4.3. Manual integration
|
||||
|
||||
There are several macros that can be used to configure the source code of the
|
||||
library. You can define those you need in your build system or at the beginning
|
||||
of the Z80.c file. The following ones allow you to configure the integration of
|
||||
Z80.h and Z80.c into the project:
|
||||
|
||||
#define Z80_DEPENDENCIES_HEADER "header name.h"
|
||||
Specifies the only external header to #include, replacing those of Zeta.
|
||||
If used, it must also be defined before including the Z80.h header.
|
||||
|
||||
#define Z80_STATIC
|
||||
Needed for compiling and/or using the emulator as a static library or as
|
||||
an internal part of other project.
|
||||
If used, it must also be defined before including the Z80.h header.
|
||||
|
||||
#define Z80_WITH_LOCAL_HEADER
|
||||
Tells Z80.c to #include "Z80.h" instead of <Z80.h>.
|
||||
|
||||
The second group of package-specific options, explained in the "Installation"
|
||||
section of this document, activates various optional implementations in the
|
||||
source code by predefining the following macros:
|
||||
|
||||
#define Z80_WITH_EXECUTE
|
||||
#define Z80_WITH_FULL_IM0
|
||||
#define Z80_WITH_Q
|
||||
#define Z80_WITH_RESET_SIGNAL
|
||||
#define Z80_WITH_SPECIAL_RESET_SIGNAL
|
||||
#define Z80_WITH_UNOFFICIAL_RETI
|
||||
#define Z80_WITH_ZILOG_NMOS_LD_A_IR_BUG
|
||||
|
||||
Please note that the activation of some these optional implementations affects
|
||||
the speed of the emulator due to various factors (read the documentation for
|
||||
more details).
|
||||
|
||||
As a final note, except for "Z80_DEPENDENCIES_HEADER", the above macros do not
|
||||
need to be set to a particular token when used, as the source code only checks
|
||||
whether or not they are defined.
|
||||
|
||||
|
||||
5. License
|
||||
===========
|
||||
|
||||
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 this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Last update: 2022-05-16 README EOF
|
||||
|
||||
790
README.md
790
README.md
@@ -1,229 +1,633 @@
|
||||

|
||||
<h1 align="center">
|
||||
<img src="http://zxe.io/software/Z80/images/Z80.svg"><br>
|
||||
<b>Zilog Z80 CPU Emulator</b>
|
||||
</h1>
|
||||
<p align="center">
|
||||
<a href="https://github.com/redcode/Z80-mainline/actions/workflows/library-ci.yml">
|
||||
<img src="https://github.com/redcode/Z80-mainline/actions/workflows/library-ci.yml/badge.svg">
|
||||
</a>
|
||||
<a href="https://github.com/redcode/Z80-mainline/actions/workflows/documentation-ci.yml">
|
||||
<img src="https://github.com/redcode/Z80-mainline/actions/workflows/documentation-ci.yml/badge.svg">
|
||||
</a>
|
||||
<a href="https://discord.gg/zU4dkzp8Mv"><img alt="Discord" src="https://img.shields.io/discord/848534208129138738?color=5865F2&label=Discord&logo=discord&logoColor=white"/></a>
|
||||
</p>
|
||||
|
||||
<br>
|
||||
# Introduction
|
||||
|
||||
# Zilog Z80 CPU Emulator
|
||||
Copyright © 1999-2018 Manuel Sainz de Baranda y Goñi.
|
||||
Released under the terms of the [GNU General Public License v3](http://www.gnu.org/copyleft/gpl.html).
|
||||
The [Z80 library](https://zxe.io/software/Z80) implements a fast, small and accurate [emulator](https://en.wikipedia.org/wiki/Emulator) of the [Zilog Z80](https://en.wikipedia.org/wiki/Zilog_Z80). It emulates all that is known to date about this CPU, including the undocumented behaviour, [MEMPTR](https://zxpress.ru/zxnet/zxnet.pc/5909), [Q](https://worldofspectrum.org/forums/discussion/41704) and the [special RESET](http://www.primrosebank.net/computers/z80/z80_special_reset.htm). It also has the honor of having been the first open source project to provide full emulation of the interrupt mode 0.
|
||||
|
||||
This is a very accurate [Z80](http://en.wikipedia.org/wiki/Zilog_Z80) [emulator](http://en.wikipedia.org/wiki/Emulator) I wrote many years ago. It has been used in several machine emulators by other people and it has been extensivelly tested. It is fast, small (33 KB when compiled as a x86-64 dynamic library), easy to understand, and **the code is profusely commented**.
|
||||
The source code is written in [ANSI C](https://en.wikipedia.org/wiki/ANSI_C) for maximum portability and is extensively commented. The aim has been to write a well-structured, easy to understand piece of software; something solid and elegant that can stand the test of time with no need for major changes.
|
||||
|
||||
If you are looking for a Zilog Z80 CPU emulator for your project maybe you have found the correct one. I use this core in the [ZX Spectrum emulator](http://github.com/redcode/MicroZX) I started as hobby.
|
||||
|
||||
<br>
|
||||
# Emulation Accuracy
|
||||
|
||||
## Building
|
||||
The Zilog Z80 emulator has a classic design with instruction-level granularity. This provides the best performance when speed is a critical factor, while still offering a reasonable flexibility to achieve precision down to the T-state level when accuracy is imperative.
|
||||
|
||||
You must first install [Z](http://zeta.st), a **header-only** library that provides types and macros. This is the only dependency, the emulator does not use the C standard library or its headers. Then add `Z80.h` and `Z80.c` to your project and configure its build system so that `CPU_Z80_STATIC` and `CPU_Z80_USE_LOCAL_HEADER` are predefined when compiling the sources.
|
||||
Instruction-level granularity implies that, except in a few well-defined cases, the execution of a given instruction cannot stop until all its internal M-cycles are completed. This kind of emulation is also carried out in an efficient way: the pertinent registers are modified only once per instruction and the T-state counter is updated only after a whole instruction is executed.
|
||||
|
||||
If you preffer to build the emulator as a library, you can use [premake4](http://premake.github.io):
|
||||
```console
|
||||
$ cd building
|
||||
$ premake4 gmake # generate Makefile
|
||||
$ make help # list available targets
|
||||
$ make [config=<configuration>] [target] # build the emulator
|
||||
That said, instructions, flags, memory accesses, interrupt and reset responses, clock cycles, etc. are accurately emulated as far as is known, according to the technical documentation available, the findings made after decades of research on the Z80 and electronic simulations. And, of course, the emulator passes the most exhaustive tests written to date:
|
||||
|
||||
|
||||
### Zilog Z80 CPU Test Suite, by [Patrik Rak](https://github.com/raxoft)
|
||||
|
||||
[This set of programs](https://github.com/raxoft/z80test) is intended to help the emulator authors to reach the desired level of the CPU emulation authenticity. Each of the included programs performs an exhaustive computation using each of the tested Z80 instructions, compares the results with values obtained from a real [Sinclair ZX Spectrum 48K](https://en.wikipedia.org/wiki/ZX_Spectrum) with Zilog Z80 CPU, and reports any deviations detected.
|
||||
|
||||
<details>
|
||||
<summary>Results</summary>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center" valign="top" align="center">
|
||||
<a href="http://zxds.raxoft.cz/taps/misc/z80test-1.0.zip">
|
||||
<img src="http://zxe.io/software/Z80/images/TAP.png"/>
|
||||
<br>
|
||||
<b>z80full.tap</b>
|
||||
</a>
|
||||
<br>
|
||||
Tests all flags and registers.
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="http://zxds.raxoft.cz/taps/misc/z80test-1.0.zip">
|
||||
<img src="http://zxe.io/software/Z80/images/TAP.png"/>
|
||||
<br>
|
||||
<b>z80doc.tap</b>
|
||||
</a>
|
||||
<br>
|
||||
Tests all registers, but only officially documented flags.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/z80full.gif"/>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/z80doc.gif"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<a href="http://zxds.raxoft.cz/taps/misc/z80test-1.0.zip">
|
||||
<img src="http://zxe.io/software/Z80/images/TAP.png"/>
|
||||
<br>
|
||||
<b>z80flags.tap</b>
|
||||
</a>
|
||||
<br>
|
||||
Tests all flags, ignores registers.
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="http://zxds.raxoft.cz/taps/misc/z80test-1.0.zip">
|
||||
<img src="http://zxe.io/software/Z80/images/TAP.png"/>
|
||||
<br>
|
||||
<b>z80docflags.tap</b>
|
||||
</a>
|
||||
<br>
|
||||
Tests documented flags only, ignores registers.
|
||||
</td>
|
||||
</tr>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/z80flags.gif"/>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/z80docflags.gif"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<a href="http://zxds.raxoft.cz/taps/misc/z80test-1.0.zip">
|
||||
<img src="http://zxe.io/software/Z80/images/TAP.png"/>
|
||||
<br>
|
||||
<b>z80ccf.tap</b>
|
||||
</a>
|
||||
<br>
|
||||
Tests all flags after executing <code>ccf</code> after each instruction tested.
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="http://zxds.raxoft.cz/taps/misc/z80test-1.0.zip">
|
||||
<img src="http://zxe.io/software/Z80/images/TAP.png"/>
|
||||
<br>
|
||||
<b>z80memptr.tap</b>
|
||||
</a>
|
||||
<br>
|
||||
Tests all flags after executing <code>bit n,(hl)</code> after each instruction tested.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/z80ccf.gif"/>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/z80memptr.gif"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
### Z80 Test Suite, by Mark Woodmass
|
||||
|
||||
This suite performs a series of tests to verify the MEMPTR documents _([English](http://zx.pk.ru/attachment.php?attachmentid=2989), [Russian](http://zx.pk.ru/attachment.php?attachmentid=2984))_, which are spot on, as well as a brief run through several of the `CBh`/`DDh`/`FDh` opcode ranges. The test results in the program are compared against those from a [NEC D780C-1](https://www.cpu-world.com/CPUs/Z80/NEC-D780C-1.html) CPU, but Simon Conway kindly tested several other Z80 clones, confirming the same results.
|
||||
|
||||
<details>
|
||||
<summary>Results</summary>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center" valign="top" colspan="2">
|
||||
<a href="https://web.archive.org/web/20130511214919if_/http://homepage.ntlworld.com/mark.woodmass/z80tests.tap">
|
||||
<img src="http://zxe.io/software/Z80/images/TAP.png"/>
|
||||
<br>
|
||||
<b>z80tests.tap</b>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/z80tests-flags.gif"/>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/z80tests-memptr.gif"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
### Z80 Instruction Set Exerciser, by Frank D. Cringle
|
||||
|
||||
Frank Cringle's _Z80 Instruction Set Exerciser_ attempts to execute every Z80 opcode, putting them through a cycle of tests and comparing the results to actual results from running the code on a real Z80. The exerciser is supplied with Frank's [YAZE](ftp://ftp.ping.de/pub/misc/emulators/yaze-1.10.tar.gz) (Yet Another Z80 Emulator). It is often difficult to track down, so [Jonathan Graham Harston](http://mdfs.net/User/JGH/) put it together [here](http://mdfs.net/Software/Z80/Exerciser/), as well as [some conversions](http://mdfs.net/Software/Z80/Exerciser/Spectrum/). The latest release of YAZE is available at [Andreas Gerlich's website](http://www.mathematik.uni-ulm.de/users/ag/yaze-ag/).
|
||||
|
||||
<details>
|
||||
<summary>Results</summary>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<a href="http://mdfs.net/Software/Z80/Exerciser/Spectrum/zexdoc.tap">
|
||||
<img src="http://zxe.io/software/Z80/images/TAP.png"/>
|
||||
<br>
|
||||
<b>zexdoc.tap</b>
|
||||
</a>
|
||||
<br>
|
||||
Tests officially documented flag effects.
|
||||
</td>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="http://mdfs.net/Software/Z80/Exerciser/Spectrum/zexall.tap">
|
||||
<img src="http://zxe.io/software/Z80/images/TAP.png"/>
|
||||
<br>
|
||||
<b>zexall.tap</b>
|
||||
</a>
|
||||
<br>
|
||||
Tests all flags changes.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/zexdoc.gif"/>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/zexall.gif"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<a href="http://zxds.raxoft.cz/taps/misc/zexall2.zip">
|
||||
<img src="http://zxe.io/software/Z80/images/TAP.png"/>
|
||||
<br>
|
||||
<b>zexall2.tap</b>
|
||||
</a>
|
||||
<br>
|
||||
Patrik Rak's modification with MEMPTR testing.
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<img src="http://zxe.io/software/Z80/images/tests/zexall2.gif"/>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
|
||||
# Installation
|
||||
|
||||
You will need [CMake](https://cmake.org) v3.14 or later to build the package and, optionally, recent versions of [Doxygen](https://www.doxygen.nl), [Sphinx](https://www.sphinx-doc.org) and [Breathe](https://github.com/michaeljones/breathe) to compile the documentation. Also make sure you have [LaTeX](https://www.latex-project.org) with PDF support installed on your system in case you want to generate the documentation in PDF format.
|
||||
|
||||
The emulator requires some types and macros included in [Zeta](https://github.com/redcode/Zeta), a dependency-free, [header-only](https://en.wikipedia.org/wiki/Header-only) library used to retain compatibility with most C compilers. Install Zeta or extract its official source code package to the same directory of this `README.md` or its parent directory. Zeta is the sole dependency; the emulator is a freestanding implementation and as such does not depend on the [C standard library](https://en.wikipedia.org/wiki/C_standard_library).
|
||||
|
||||
Once all requirements are met, create a directory and run `cmake` from there to prepare the build system:
|
||||
|
||||
```shell
|
||||
mkdir build
|
||||
cd build
|
||||
cmake <directory of this README.md> [options]
|
||||
```
|
||||
|
||||
There is also an Xcode project in `development/Xcode` with several targets:
|
||||
The resulting build files can be configured by passing options to `cmake`. To show a complete list of those available along with their current settings, type the following:
|
||||
|
||||
Target | Description
|
||||
--- | ---
|
||||
Z80 (dynamic) | Shared library.
|
||||
Z80 (dynamic module) | Shared library with a generic module ABI to be used in modular multi-machine emulators.
|
||||
Z80 (static) | Static library.
|
||||
Z80 (static module) | Static library with a generic CPU emulator ABI to be used in monolithic multi-machine emulators.
|
||||
|
||||
<br>
|
||||
|
||||
## Code configuration
|
||||
|
||||
There are some predefined macros that control the compilation:
|
||||
|
||||
Name | Description
|
||||
--- | ---
|
||||
`CPU_Z80_DEPENDENCIES_H` | If defined, it replaces the inclusion of any external header with this one. If you don't want to use Z, you can provide your own header with the types and macros used by the emulator.
|
||||
`CPU_Z80_HIDE_ABI` | Makes the generic CPU emulator ABI private.
|
||||
`CPU_Z80_HIDE_API` | Makes the public functions private.
|
||||
`CPU_Z80_STATIC` | You need to define this to compile or use the emulator as a static library or if you have added `Z80.h` and `Z80.c` to your project.
|
||||
`CPU_Z80_USE_LOCAL_HEADER` | Use this if you have imported `Z80.h` and `Z80.c` to your project. `Z80.c` will `#include "Z80.h"` instead of `<emulation/CPU/Z80.h>`.
|
||||
`CPU_Z80_WITH_ABI` | Builds the generic CPU emulator ABI and declares its prototype in `Z80.h`.
|
||||
`CPU_Z80_WITH_MODULE_ABI` | Builds the generic module ABI. This macro also enables `CPU_Z80_WITH_ABI`, so the generic CPU emulator ABI will be built too. This option is intended to be used when building a true module loadable at runtime with `dlopen()`, `LoadLibrary()` or similar. The ABI module can be accessed via the [weak symbol](http://en.wikipedia.org/wiki/Weak_symbol) `__module_abi__`.
|
||||
|
||||
<br>
|
||||
|
||||
## API: `Z80` emulator instance
|
||||
|
||||
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: `context`, `read`, `write`, `in`, `out`, `int_data` and `halt`.
|
||||
|
||||
```C
|
||||
zusize cycles;
|
||||
```shell
|
||||
cmake -LAH
|
||||
```
|
||||
**Description**
|
||||
Number of cycles executed in the current call to `z80_run`.
|
||||
**Details**
|
||||
`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.
|
||||
|
||||
```C
|
||||
void *context;
|
||||
If in doubt, read the [CMake documentation](https://cmake.org/documentation/) for more information on configuration options. The following are some of the most relevant standard options of CMake:
|
||||
|
||||
* **`-DBUILD_SHARED_LIBS=(YES|NO)`**
|
||||
Build the project as a shared library rather than a static one.
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DCMAKE_BUILD_TYPE=(Debug|Release|RelWithDebInfo)`**
|
||||
Choose the type of build (configuration) to generate.
|
||||
The default is `Release`.
|
||||
|
||||
* **`-DCMAKE_INSTALL_PREFIX="<path>"`**
|
||||
Specify the installation prefix on [UNIX](https://en.wikipedia.org/wiki/Unix) and [UNIX-like](https://en.wikipedia.org/wiki/Unix-like) operating systems.
|
||||
The default is `"/usr/local"`.
|
||||
|
||||
Package-specific options are prefixed with `Z80_` and can be divided into two groups. The first one controls aspects not related to the source code of the library:
|
||||
|
||||
* **`-DZ80_DOWNLOAD_TEST_FILES=(YES|NO)`**
|
||||
Download the firmware and software used by the testing tool.
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_INSTALL_CMAKEDIR="<path>"`**
|
||||
Specify the directory in which to install the CMake [config-file package](https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#config-file-packages).
|
||||
The default is `"${CMAKE_INSTALL_LIBDIR}/cmake/Z80"`.
|
||||
|
||||
* **`-DZ80_INSTALL_PKGCONFIGDIR="<path>"`**
|
||||
Specify the directory in which to install the [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config) [file](https://people.freedesktop.org/~dbn/pkg-config-guide.html).
|
||||
The default is `"${CMAKE_INSTALL_LIBDIR}/pkgconfig"`.
|
||||
|
||||
* **`-DZ80_NOSTDLIB_FLAGS=(Auto|[<flag>[;<flag>...]])`**
|
||||
Specify the linker flags used to avoid linking against system libraries.
|
||||
The default is `Auto` (autoconfigure flags). If you get linker errors, set this option to `""`.
|
||||
|
||||
* **`-DZ80_SHARED_LIBS=(YES|NO)`**
|
||||
Build the project as a shared library rather than a static one.
|
||||
This option takes precedence over `BUILD_SHARED_LIBS`.
|
||||
Not defined by default.
|
||||
|
||||
* **`-DZ80_SPHINX_HTML_THEME="[<name>]"`**
|
||||
Specify the Sphinx theme for the documentation in HTML format.
|
||||
The default is `""` (use the default theme).
|
||||
|
||||
* **`-DZ80_WITH_CMAKE_SUPPORT=(YES|NO)`**
|
||||
Generate and install the CMake [config-file package](https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#config-file-packages).
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_HTML_DOCUMENTATION=(YES|NO)`**
|
||||
Build and install the documentation in HTML format.
|
||||
It requires Doxygen, Sphinx and Breathe.
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_PDF_DOCUMENTATION=(YES|NO)`**
|
||||
Build and install the documentation in PDF format.
|
||||
It requires Doxygen, Sphinx, Breathe and LaTeX with PDF support.
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_PKGCONFIG_SUPPORT=(YES|NO)`**
|
||||
Generate and install the [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config) [file](https://people.freedesktop.org/~dbn/pkg-config-guide.html).
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_STANDARD_DOCUMENTS=(YES|NO)`**
|
||||
Install the standard text documents distributed with the package: `AUTHORS`, `COPYING`, `COPYING.LESSER`, `HISTORY`, `README` and `THANKS`.
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_TESTS=(YES|NO)`**
|
||||
Build the testing tool.
|
||||
The default is `NO`.
|
||||
|
||||
The second group of package-specific options configures the source code of the library by predefining macros that enable optional implementations:
|
||||
|
||||
* **`-DZ80_WITH_EXECUTE=(YES|NO)`**
|
||||
Build the implementation of the `z80_execute` function.
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_FULL_IM0=(YES|NO)`**
|
||||
Build the full implementation of the interrupt mode 0 rather than the reduced one.
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_Q=(YES|NO)`**
|
||||
Build the implementation of the [Q "register"](https://worldofspectrum.org/forums/discussion/41704).
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_RESET_SIGNAL=(YES|NO)`**
|
||||
Build the implementation of the normal RESET signal.
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_SPECIAL_RESET_SIGNAL=(YES|NO)`**
|
||||
Build the implementation of the [special RESET](http://www.primrosebank.net/computers/z80/z80_special_reset.htm) signal.
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_UNOFFICIAL_RETI=(YES|NO)`**
|
||||
Configure the `ED5Dh`, `ED6Dh` and `ED7Dh` undocumented instructions as `reti` instead of `retn`.
|
||||
The default is `NO`.
|
||||
|
||||
* **`-DZ80_WITH_ZILOG_NMOS_LD_A_IR_BUG=(YES|NO)`**
|
||||
Build the implementation of the bug affecting the Zilog Z80 NMOS, which causes the P/V flag to be reset when a maskable interrupt is accepted during the execution of the `ld a,{i|r}` instructions.
|
||||
The default is `NO`.
|
||||
|
||||
Package maintainers should use at least the following options for both shared and static library targets:
|
||||
|
||||
```shell
|
||||
-DZ80_WITH_EXECUTE=YES
|
||||
-DZ80_WITH_FULL_IM0=YES
|
||||
-DZ80_WITH_Q=YES
|
||||
-DZ80_WITH_RESET_SIGNAL=YES
|
||||
-DZ80_WITH_ZILOG_NMOS_LD_A_IR_BUG=YES
|
||||
```
|
||||
**Description**
|
||||
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.
|
||||
|
||||
```C
|
||||
zuint8 (* read)(void *context, zuint16 address);
|
||||
Finally, once the build system is configured according to your needs, build and install the package:
|
||||
|
||||
```shell
|
||||
make
|
||||
make install/strip
|
||||
```
|
||||
**Description**
|
||||
Callback: Called when the CPU needs to read 8 bits from memory.
|
||||
**Parameters**
|
||||
`context` → The value of the member `context`.
|
||||
`address` → The memory address to read from.
|
||||
**Returns**
|
||||
The 8 bits read from memory.
|
||||
|
||||
```C
|
||||
void (* write)(void *context, zuint16 address, zuint8 value);
|
||||
# Integration
|
||||
|
||||
### As an external dependency in CMake-based projects
|
||||
|
||||
The Z80 library includes find-modules and a config-file package for integration into CMake-based projects. It is recommended to always copy the `FindZ80.cmake` and `FindZeta.cmake` files into the CMake modules directory of projects that use the library as an external dependency. This will allow CMake to find the library if the necessary config-file packages are not installed on the system.
|
||||
|
||||
Both the config-file package and the find-module support dual installations of the shared and static versions of the Z80 library. You can specify the linking method by using the component mechanism of `find_package`.
|
||||
|
||||
Example:
|
||||
|
||||
```cmake
|
||||
find_package(Z80 REQUIRED [Shared|Static])
|
||||
target_link_libraries(your-target Z80)
|
||||
```
|
||||
**Description**
|
||||
Callback: Called when the CPU needs to write 8 bits to memory.
|
||||
**Parameters**
|
||||
`context` → The value of the member `context`.
|
||||
`address` → The memory address to write to.
|
||||
`value` → The value to write.
|
||||
|
||||
```C
|
||||
zuint8 (* in)(void *context, zuint16 port);
|
||||
Omitting the linking method will select the `Shared` version of the library or, if not installed, the `Static` version instead.
|
||||
|
||||
### As a CMake subproject
|
||||
|
||||
To embed the library as a CMake subproject, just place its entire source tree into a subdirectory of your project.
|
||||
|
||||
It is advisable to configure the library in the CMakeLists.txt of your project. This will prevent the user from having to specify configuration options of the Z80 subproject through the CMake command line when building the main project. As noted in the "Installation" section of this document, all package-specific options are prefixed with `Z80_`, so, in a normal scenario, there should be no risk of name collision with the options and variables of the parent project.
|
||||
|
||||
Example:
|
||||
|
||||
```cmake
|
||||
set(Z80_SHARED_LIBS NO CACHE BOOL "")
|
||||
set(Z80_WITH_Q YES CACHE BOOL "")
|
||||
set(Z80_WITH_ZILOG_NMOS_LD_A_IR_BUG YES CACHE BOOL "")
|
||||
|
||||
add_subdirectory(dependencies/Z80)
|
||||
target_link_libraries(your-target Z80)
|
||||
```
|
||||
**Description**
|
||||
Callback: Called when the CPU needs to read 8 bits from an I/O port.
|
||||
**Parameters**
|
||||
`context` → The value of the member `context`.
|
||||
`port` → The number of the I/O port to read from.
|
||||
**Returns**
|
||||
The 8 bits read from the I/O port.
|
||||
|
||||
```C
|
||||
void (* out)(void *context, zuint16 port, zuint8 value);
|
||||
```
|
||||
**Description**
|
||||
Callback: Called when the CPU needs to write 8 bits to an I/O port.
|
||||
**Parameters**
|
||||
`context` → The value of the member `context`.
|
||||
`port` → The number of the I/O port to write to.
|
||||
`value` → The value to write.
|
||||
It is important to set the `Z80_SHARED_LIBS` option. Otherwise CMake will build the library type indicated by `BUILD_SHARED_LIBS`, which may not be the desired one.
|
||||
|
||||
```C
|
||||
zuint32 (* int_data)(void *context);
|
||||
```
|
||||
**Description**
|
||||
Callback: Called when the CPU needs to read one instruction from the data bus to service a maskable interrupt (`INT`) in mode 0.
|
||||
**Parameters**
|
||||
`context` → The value of the member `context`.
|
||||
**Returns**
|
||||
A 32-bit value containing the bytes of an instruction. The instruction must begin at the most significant byte (big endian).
|
||||
### Manual integration
|
||||
|
||||
```C
|
||||
void (* halt)(void *context, zboolean state);
|
||||
```
|
||||
**Description**
|
||||
Callback: Called when the CPU enters or exits the halt state.
|
||||
**Note**
|
||||
This callback is **optional** and must be set to `NULL` if not used.
|
||||
**Parameters**
|
||||
`context` → The value of the member `context`.
|
||||
`state` → `TRUE` if halted; `FALSE` otherwise.
|
||||
There are several macros that can be used to configure the source code of the library. You can define those you need in your build system or at the beginning of the `Z80.c` file. The following ones allow you to configure the integration of `Z80.h` and `Z80.c` into the project:
|
||||
|
||||
```C
|
||||
ZZ80State state;
|
||||
```
|
||||
**Description**
|
||||
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 data source.
|
||||
* **`#define Z80_DEPENDENCIES_HEADER "header name.h"`**
|
||||
Specifies the only external header to `#include`, replacing those of Zeta.
|
||||
If used, it must also be defined before including the `Z80.h` header.
|
||||
|
||||
```C
|
||||
zuint8 r7;
|
||||
```
|
||||
**Description**
|
||||
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 `z80_run` and restored before returning. If an instruction directly affects the R register, this variable is also updated accordingly.
|
||||
* **`#define Z80_STATIC`**
|
||||
Needed for compiling and/or using the emulator as a static library or as an internal part of other project.
|
||||
If used, it must also be defined before including the `Z80.h` header.
|
||||
|
||||
```C
|
||||
Z16Bit xy;
|
||||
```
|
||||
**Description**
|
||||
Temporay IX/IY register for instructions with `DDh`/`FDh` prefix.
|
||||
**Details**
|
||||
Since instructions with prefix `DDh` and `FDh` 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.
|
||||
* **`#define Z80_WITH_LOCAL_HEADER`**
|
||||
Tells `Z80.c` to `#include "Z80.h"` instead of `<Z80.h>`.
|
||||
|
||||
```C
|
||||
Z32Bit data;
|
||||
```
|
||||
**Description**
|
||||
Temporary storage for opcode fetching.
|
||||
**Details**
|
||||
This is an internal private variable.
|
||||
The second group of package-specific options, explained in the "Installation" section of this document, activates various optional implementations in the source code by predefining the following macros:
|
||||
|
||||
<br>
|
||||
* **`#define Z80_WITH_EXECUTE`**
|
||||
* **`#define Z80_WITH_FULL_IM0`**
|
||||
* **`#define Z80_WITH_Q`**
|
||||
* **`#define Z80_WITH_RESET_SIGNAL`**
|
||||
* **`#define Z80_WITH_SPECIAL_RESET_SIGNAL`**
|
||||
* **`#define Z80_WITH_UNOFFICIAL_RETI`**
|
||||
* **`#define Z80_WITH_ZILOG_NMOS_LD_A_IR_BUG`**
|
||||
|
||||
## API: Public Functions
|
||||
Please note that the activation of some these optional implementations affects the speed of the emulator due to various factors (read the documentation for more details).
|
||||
|
||||
```C
|
||||
void z80_power(Z80 *object, zboolean state);
|
||||
```
|
||||
**Description**
|
||||
Changes the CPU power status.
|
||||
**Parameters**
|
||||
`object` → A pointer to a Z80 emulator instance.
|
||||
`state` → `TRUE` = power ON; `FALSE` = power OFF.
|
||||
As a final note, except for `Z80_DEPENDENCIES_HEADER`, the above macros do not need to be set to a particular token when used, as the source code only checks whether or not they are defined.
|
||||
|
||||
```C
|
||||
void z80_reset(Z80 *object);
|
||||
```
|
||||
**Description**
|
||||
Resets the CPU.
|
||||
**Details**
|
||||
This is equivalent to a pulse on the `RESET` line of a real Z80.
|
||||
**Parameters**
|
||||
`object` → A pointer to a Z80 emulator instance.
|
||||
# Showcase
|
||||
|
||||
```C
|
||||
zusize z80_run(Z80 *object, zusize cycles);
|
||||
```
|
||||
**Description**
|
||||
Runs the CPU for a given number of `cycles`.
|
||||
**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 `cycles` specfified.
|
||||
**Parameters**
|
||||
`object` → A pointer to a Z80 emulator instance.
|
||||
`cycles` → The number of cycles to be executed.
|
||||
**Returns**
|
||||
The number of cycles executed.
|
||||
This emulator has been used by the following projects (listed in alphabetical order):
|
||||
|
||||
```C
|
||||
void z80_nmi(Z80 *object);
|
||||
```
|
||||
**Description**
|
||||
Performs a non-maskable interrupt (NMI).
|
||||
**Details**
|
||||
This is equivalent to a pulse on the `NMI` line of a real Z80.
|
||||
**Parameters**
|
||||
`object` → A pointer to a Z80 emulator instance.
|
||||
* [Augmentinel](https://simonowen.com/spectrum/augmentinel/), _by [Simon Owen](https://simonowen.com/)_ - [GitHub](https://github.com/simonowen/augmentinel)
|
||||
* CPM-Emulator, _by [Marc Sibert](https://github.com/Marcussacapuces91)_ - [GitHub](https://github.com/Marcussacapuces91/CPM-Emulator)
|
||||
* [tihle: a unique TI calculator emulator](https://www.taricorp.net/2020/introducing-tihle/), _by [Peter Marheine](https://www.taricorp.net/about/)_ - [GitHub](https://github.com/tari/tihle), [GitLab](https://gitlab.com/taricorp/tihle)
|
||||
* [TileMap](https://simonowen.com/spectrum/tilemap/), _by [Simon Owen](https://simonowen.com/)_ - [GitHub](https://github.com/simonowen/tilemap)
|
||||
* [Zemu](https://github.com/jayvalentine/zemu), _by [Jay Valentine](https://jayvalentine.github.io/)_ - [GitHub](https://github.com/jayvalentine/zemu), [RubyGems](https://rubygems.org/gems/zemu)
|
||||
* Others...
|
||||
|
||||
```C
|
||||
void z80_int(Z80 *object, zboolean state);
|
||||
```
|
||||
**Description**
|
||||
Changes the state of the maskable interrupt (INT).
|
||||
**Details**
|
||||
This is equivalent to a change on the `INT` line of a real Z80.
|
||||
**Parameters**
|
||||
`object` → A pointer to a Z80 emulator instance.
|
||||
`state` → `TRUE` = line high; `FALSE` = line low.
|
||||
# Thanks
|
||||
|
||||
<br>
|
||||
Many thanks to the following individuals (in alphabetical order):
|
||||
|
||||
## Use in Proprietary Software
|
||||
This library is released under the terms of the [GNU General Public License v3](http://www.gnu.org/copyleft/gpl.html), but I can license it for non-free/propietary projects if you contact [me](mailto:contact@zxe.io?subject=Z80%20non-free%20licensing).
|
||||
* **Akimov, Vadim (lvd)**
|
||||
* For testing the library on many different platforms and CPU architectures.
|
||||
* **azesmbog**
|
||||
1. For validating tests on real hardware <sup>[[1](#r1)]</sup>.
|
||||
2. For his research on the unstable flag behavior of the `ccf/scf` instructions.
|
||||
3. For his invaluable help.
|
||||
* **Banks, David (hoglet)**
|
||||
1. For cracking the flag behavior of the block instructions <sup>[[2](#r2), [3](#r3)]</sup>.
|
||||
2. For his research on the flag behavior of the `ccf/scf` instructions <sup>[[3](#r3)]</sup>.
|
||||
* **Beliansky, Anatoly (Tolik_Trek)**
|
||||
* For validating tests on real hardware <sup>[[4](#r4)]</sup>.
|
||||
* **Bobrowski, Jan**
|
||||
* For fixing the _"Z80 Full Instruction Set Exerciser for Spectrum"_ <sup>[[5](#r5)]</sup>.
|
||||
* **boo_boo**
|
||||
* For cracking the behavior of the MEMPTR register <sup>[[6](#r6), [7](#r7), [8](#r8), [9](#r9)]</sup>.
|
||||
* **Brady, Stuart**
|
||||
* For his research on the flag behavior of the `ccf/scf` instructions <sup>[[10](#r10)]</sup>.
|
||||
* **Brewer, Tony**
|
||||
1. For his research on the special RESET <sup>[[11](#r11)]</sup>.
|
||||
2. For sharing information about the RESET signal <sup>[[12](#r12)]</sup>.
|
||||
3. For helping to crack the flag behavior of the block instructions <sup>[[2](#r2)]</sup>.
|
||||
4. For performing low-level tests on real hardware <sup>[[2](#r2)]</sup>.
|
||||
5. For helping me to test different undocumented behaviors of the Zilog Z80.
|
||||
* **Bystrov, Dmitry (Alone Coder)**
|
||||
* For validating tests on real hardware <sup>[[4](#r4)]</sup>.
|
||||
* **Chunin, Roman (CHRV)**
|
||||
* For testing the behavior of the MEMPTR register on real Z80 chips <sup>[[6](#r6), [7](#r7), [8](#r8), [9](#r9)]</sup>.
|
||||
* **Conway, Simon (BadBeard)**
|
||||
* For validating the _"Z80 Test Suite"_ on several Z80 clones <sup>[[13](#r13)]</sup>.
|
||||
* **Cooke, Simon**
|
||||
* For finding out how the `out (c),0` instruction behaves on the Zilog Z80 CMOS <sup>[[14](#r14)]</sup>.
|
||||
* **Cringle, Frank D.**
|
||||
* For writing the _"Z80 Instruction Set Exerciser"_ <sup>[[15](#r15)]</sup>.
|
||||
* **Devic, Goran**
|
||||
* For his research on undocumented behaviors of the Z80 CPU <sup>[[16](#r16)]</sup>.
|
||||
* **Flammenkamp, Achim**
|
||||
* For his article on Z80 interrupts <sup>[[17](#r17)]</sup>.
|
||||
* **Gimeno Fortea, Pedro**
|
||||
1. For his research work <sup>[[18](#r18)]</sup>.
|
||||
2. For writing the first-ever ZX Spectrum emulator <sup>[[19](#r19), [20](#r20)]</sup>.
|
||||
* **goodboy**
|
||||
* For testing the behavior of the MEMPTR register on real Z80 chips <sup>[[6](#r6), [7](#r7), [8](#r8), [9](#r9)]</sup>.
|
||||
* **Greenway, Ian**
|
||||
* For testing the flag behavior of the `ccf/scf` instructions on real hardware <sup>[[10](#r10), [21](#r21)]</sup>.
|
||||
* **Harston, Jonathan Graham**
|
||||
1. For his technical documents about the Zilog Z80 <sup>[[22](#r22), [23](#r23), [24](#r24)]</sup>.
|
||||
2. For porting the _"Z80 Instruction Set Exerciser"_ to the ZX Spectrum <sup>[[25](#r25)]</sup>.
|
||||
* **Helcmanovsky, Peter (Ped7g)**
|
||||
1. For helping me to write the _"IN-MEMPTR"_ test.
|
||||
2. For writing the _"Z80 Block Flags Test"_ <sup>[[26](#r26), [27](#r27)]</sup>.
|
||||
3. For writing the _"Z80 CCF SCF Outcome Stability"_ test <sup>[[27](#r27)]</sup>.
|
||||
4. For writing the _"Z80 INT Skip"_ test <sup>[[27](#r27)]</sup>.
|
||||
5. For his research on the unstable flag behavior of the `ccf/scf` instructions.
|
||||
6. For his invaluable help.
|
||||
* **icebear**
|
||||
* For testing the behavior of the MEMPTR register on real Z80 chips <sup>[[6](#r6), [7](#r7), [8](#r8), [9](#r9)]</sup>.
|
||||
* **Kladov, Vladimir**
|
||||
* For cracking the behavior of the MEMPTR register <sup>[[6](#r6), [7](#r7), [8](#r8), [9](#r9)]</sup>.
|
||||
* **Krook, Magnus**
|
||||
* For validating tests on real hardware <sup>[[28](#r28)]</sup>.
|
||||
* **London, Matthew**
|
||||
* For validating tests on real hardware.
|
||||
* **Molodtsov, Aleksandr**
|
||||
* For testing the behavior of the MEMPTR register on real Z80 chips <sup>[[6](#r6), [7](#r7), [8](#r8), [9](#r9)]</sup>.
|
||||
* **Nair, Arjun**
|
||||
* For validating tests on real hardware <sup>[[26](#r26)]</sup>.
|
||||
* **Nicolás-González, César**
|
||||
* For helping me to research the unstable flag behavior of the `ccf/scf` instructions.
|
||||
* **Ortega Sosa, Sofía**
|
||||
* For her support.
|
||||
* **Owen, Simon**
|
||||
* For the idea of the hooking method used in this emulator.
|
||||
* **Rak, Patrik**
|
||||
1. For improving the _"Z80 Instruction Set Exerciser for Spectrum"_ <sup>[[29](#r29)]</sup>.
|
||||
2. For cracking the flag behavior of the `ccf/scf` instructions <sup>[[13](#r13), [29](#r29)]</sup>.
|
||||
3. For writing the _"Zilog Z80 CPU Test Suite"_ <sup>[[29](#r29), [30](#r30)]</sup>.
|
||||
4. For his research on the unstable flag behavior of the `ccf/scf` instructions.
|
||||
* **Rodríguez Jódar, Miguel Ángel (mcleod_ideafix)**
|
||||
* For his reseach on the state of the registers after POWER/RESET <sup>[[31](#r31)]</sup>.
|
||||
* **Rodríguez Palomino, Mario (r-lyeh)**
|
||||
* For teaching me how emulators work.
|
||||
* **Sainz de Baranda y Romero, Manuel**
|
||||
* For teaching me programming and giving me my first computer.
|
||||
* **Sánchez Ordiñana, José Ismael (Vaporatorius)**
|
||||
* For validating tests on real hardware <sup>[[32](#r32), [33](#r33)]</sup>.
|
||||
* **Stevenson, Dave**
|
||||
1. For testing the special RESET on real hardware <sup>[[11](#r11)]</sup>.
|
||||
2. For performing low-level tests on real hardware <sup>[[34](#r34)]</sup>.
|
||||
* **Weissflog, Andre (Floh)**
|
||||
1. For finding out that the "reti/retn" instructions defer the acceptance of the maskable interrupt <sup>[[35](#r35)]</sup>.
|
||||
2. For writing the "Visual Z80 Remix" simulator <sup>[[36](#r36)]</sup>.
|
||||
* **Wilkinson, Oli (evolutional)**
|
||||
* For validating tests on real hardware <sup>[[26](#r26)]</sup>.
|
||||
* **Wlodek**
|
||||
* For testing the behavior of the MEMPTR register on real Z80 chips <sup>[[6](#r6), [7](#r7), [8](#r8), [9](#r9)]</sup>.
|
||||
* **Woodmass, Mark (Woody)**
|
||||
1. For his invaluable contributions to the emuscene.
|
||||
2. For writing the _"Z80 Test Suite"_ <sup>[[13](#r13)]</sup>.
|
||||
3. For his research on the flag behavior of the `ccf/scf` instructions <sup>[[37](#r37)]</sup>.
|
||||
4. For writing the _"HALT2INT"_ test.
|
||||
5. For writing the _"EIHALT"_ test.
|
||||
* **Young, Sean**
|
||||
1. For his research work.
|
||||
2. For his technical documents about the Zilog Z80 <sup>[[18](#r18), [38](#r38)]</sup>.
|
||||
* **ZXGuesser**
|
||||
* For validating tests on real hardware.
|
||||
|
||||
### References
|
||||
|
||||
1. <span id="r1">https://spectrumcomputing.co.uk/forums/viewtopic.php?p=83384#p83384</span>
|
||||
2. <span id="r2">https://stardot.org.uk/forums/viewtopic.php?t=15464</span>
|
||||
* https://stardot.org.uk/forums/viewtopic.php?p=211042#p211042
|
||||
* https://stardot.org.uk/forums/viewtopic.php?p=212021#p212021
|
||||
3. <span id="r3">Banks, David (2018-08-21). _"Undocumented Z80 Flags"_.</span>
|
||||
* https://github.com/hoglet67/Z80Decoder/wiki/Undocumented-Flags
|
||||
* https://stardot.org.uk/forums/download/file.php?id=39831
|
||||
4. <span id="r4">https://spectrumcomputing.co.uk/forums/viewtopic.php?p=83041#p83041</span>
|
||||
5. <span id="r5">http://wizard.ae.krakow.pl/~jb/qaop/tests.html</span>
|
||||
6. <span id="r6">https://zxpress.ru/zxnet/zxnet.pc/5909</span>
|
||||
7. <span id="r7">https://zx-pk.ru/threads/2506-komanda-bit-n-(hl).html</span>
|
||||
8. <span id="r8">https://zx-pk.ru/threads/2586-prosba-realshchikam-ot-emulyatorshchikov.html</span>
|
||||
9. <span id="r9">boo_boo; Kladov, Vladimir (2006-03-29). _"MEMPTR: esoteric register of the Zilog Z80 CPU"_.</span>
|
||||
* http://zx.pk.ru/showpost.php?p=43688
|
||||
* http://zx.pk.ru/attachment.php?attachmentid=2984
|
||||
* http://zx.pk.ru/showpost.php?p=43800
|
||||
* http://zx.pk.ru/attachment.php?attachmentid=2989
|
||||
10. <span id="r10">https://sourceforge.net/p/fuse-emulator/mailman/message/6929573</span>
|
||||
11. <span id="r11">Brewer, Tony (2014-12). _"Z80 Special Reset"_.</span>
|
||||
* http://primrosebank.net/computers/z80/z80_special_reset.htm
|
||||
12. <span id="r12">https://mtxworld.dk/memorum/viewtopic.php?p=1352#p1352</span>
|
||||
13. <span id="r13">https://worldofspectrum.org/forums/discussion/20345</span>
|
||||
14. <span id="r14">https://groups.google.com/g/comp.os.cpm/c/HfSTFpaIkuU/m/KotvMWu3bZoJ</span>
|
||||
15. <span id="r15">Cringle, Frank D. (1998-01-28). _"Yaze - Yet Another Z80 Emulator"_ v1.10.</span>
|
||||
* ftp://ftp.ping.de/pub/misc/emulators/yaze-1.10.tar.gz
|
||||
16. <span id="r16">https://baltazarstudios.com/zilog-z80-undocumented-behavior</span>
|
||||
17. <span id="r17">Flammenkamp, Achim. _"Interrupt Behaviour of the Z80 CPU"_.</span>
|
||||
* http://z80.info/interrup.htm
|
||||
18. <span id="r18">Young, Sean (1998-10). _"Z80 Undocumented Features (in Software Behaviour)"_.</span>
|
||||
19. <span id="r19">https://elmundodelspectrum.com/desenterrando-el-primer-emulador-de-spectrum</span>
|
||||
20. <span id="r20">https://elmundodelspectrum.com/con-vosotros-el-emulador-de-pedro-gimeno-1989</span>
|
||||
21. <span id="r21">https://sourceforge.net/p/fuse-emulator/mailman/message/4502844</span>
|
||||
22. <span id="r22">Harston, Jonathan Graham (1997-09-09). _"Z80 Opcode Map"_.</span>
|
||||
* https://mdfs.net/Docs/Comp/Z80/OpCodeMap
|
||||
23. <span id="r23">Harston, Jonathan Graham (1997-12-18). _"Z80 Microprocessor Undocumented Instructions"_.</span>
|
||||
* https://mdfs.net/Docs/Comp/Z80/UnDocOps
|
||||
24. <span id="r24">Harston, Jonathan Graham (1998-04-15). _"Full Z80 Opcode List Including Undocumented Opcodes"_.</span>
|
||||
* https://mdfs.net/Docs/Comp/Z80/OpList
|
||||
25. <span id="r25">https://mdfs.net/Software/Z80/Exerciser/Spectrum</span>
|
||||
26. <span id="r26">https://spectrumcomputing.co.uk/forums/viewtopic.php?t=6102</span>
|
||||
27. <span id="r27">https://github.com/MrKWatkins/ZXSpectrumNextTests</span>
|
||||
28. <span id="r28">https://spectrumcomputing.co.uk/forums/viewtopic.php?p=83157#p83157</span>
|
||||
29. <span id="r29">https://worldofspectrum.org/forums/discussion/41704</span>
|
||||
* http://zxds.raxoft.cz/taps/misc/zexall2.zip
|
||||
30. <span id="r30">https://worldofspectrum.org/forums/discussion/41834</span>
|
||||
* http://zxds.raxoft.cz/taps/misc/z80test-1.0.zip
|
||||
* https://github.com/raxoft/z80test
|
||||
31. <span id="r31">https://worldofspectrum.org/forums/discussion/34574</span>
|
||||
32. <span id="r32">https://worldofspectrum.org/forums/discussion/comment/668760/#Comment_668760</span>
|
||||
33. <span id="r33">https://jisanchez.com/test-a-dos-placas-de-zx-spectrum</span>
|
||||
34. <span id="r34">https://stardot.org.uk/forums/viewtopic.php?p=212360#p212360</span>
|
||||
35. <span id="r35">https://floooh.github.io/2021/12/17/cycle-stepped-z80.html</span>
|
||||
36. <span id="r36">https://github.com/floooh/v6502r</span>
|
||||
37. <span id="r37">http://groups.google.co.uk/group/comp.sys.sinclair/msg/56dd1fd4ccb5fb3b</span>
|
||||
38. <span id="r38">Young, Sean (2005-09-18). _"Undocumented Z80 Documented, The"_.</span>
|
||||
* http://www.myquest.nl/z80undocumented
|
||||
* http://www.myquest.nl/z80undocumented/z80-documented-v0.91.pdf
|
||||
|
||||
# Thanks
|
||||
|
||||
Alexander Molodtsov,
|
||||
boo_boo,
|
||||
CHRV,
|
||||
Dave Stevenson,
|
||||
Frank D. Cringle,
|
||||
goodboy,
|
||||
Goran Devic,
|
||||
[Ian Greenway](http://www.lasernet.plus.com),
|
||||
icebear,
|
||||
Manuel Sainz de Baranda y Romero,
|
||||
[Mario Rodríguez Palomino](https://github.com/r-lyeh),
|
||||
Mark Woodmass,
|
||||
[Miguel Ángel Rodríguez Jódar](https://github.com/mcleod-ideafix),
|
||||
[Patrik Rak](https://github.com/raxoft),
|
||||
[Pedro Gimeno Fortea](http://www.formauri.es/personal/pgimeno/),
|
||||
Sean Young,
|
||||
Simon Conway,
|
||||
Simon Cooke,
|
||||
Simon Owen,
|
||||
[Sofía Ortega Sosa](https://github.com/agaxia),
|
||||
Stuart Brady,
|
||||
Tony Brewer,
|
||||
Vladimir Kladov,
|
||||
Wlodek
|
||||
|
||||
Read the [THANKS](THANKS) file for details.
|
||||
|
||||
# License
|
||||
|
||||
Copyright © 1999-2022 Manuel Sainz de Baranda y Goñi.
|
||||
|
||||
<img src="http://zxe.io/software/Z80/images/lgplv3-147x51.png" align="right">
|
||||
|
||||
This emulator is [free software](https://www.gnu.org/philosophy/free-sw.html): you can redistribute it and/or modify it under the terms of the **[GNU Lesser General Public License](https://www.gnu.org/licenses/lgpl-3.0.en.html)** as published by the [Free Software Foundation](https://www.fsf.org), either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This emulator 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](COPYING.LESSER) of the GNU Lesser General Public License along with this emulator. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# Special licensing
|
||||
|
||||
Projects where the terms of the GNU Lesser General Public License prevent the use of this library, or require unwanted publication of the source code of commercial products, may [apply for a special license](mailto:manuel@zxe.io?subject=Z80).
|
||||
|
||||
180
THANKS
Normal file
180
THANKS
Normal file
@@ -0,0 +1,180 @@
|
||||
Many thanks to the following individuals (in alphabetical order):
|
||||
|
||||
* Akimov, Vadim (lvd)
|
||||
For testing the library on many different platforms and CPU architectures.
|
||||
* azesmbog
|
||||
1. For validating tests on real hardware [1].
|
||||
2. For his research on the unstable flag behavior of the "ccf/scf"
|
||||
instructions.
|
||||
3. For his invaluable help.
|
||||
* Banks, David (hoglet)
|
||||
1. For cracking the flag behavior of the block instructions [2,3].
|
||||
2. For his research on the flag behavior of the "ccf/scf" instructions [3].
|
||||
* Beliansky, Anatoly (Tolik_Trek)
|
||||
For validating tests on real hardware [4].
|
||||
* Bobrowski, Jan
|
||||
For fixing the "Z80 Full Instruction Set Exerciser for Spectrum" [5].
|
||||
* boo_boo
|
||||
For cracking the behavior of the MEMPTR register [6,7,8,9].
|
||||
* Brady, Stuart
|
||||
For his research on the flag behavior of the "ccf/scf" instructions [10].
|
||||
* Brewer, Tony
|
||||
1. For his research on the special RESET [11].
|
||||
2. For sharing information about the RESET signal [12].
|
||||
3. For helping to crack the flag behavior of the block instructions [2].
|
||||
4. For performing low-level tests on real hardware [2].
|
||||
5. For helping me to test different undocumented behaviors of the Zilog Z80.
|
||||
* Bystrov, Dmitry (Alone Coder)
|
||||
For validating tests on real hardware [4].
|
||||
* Chunin, Roman (CHRV)
|
||||
For testing the behavior of the MEMPTR register on real Z80 chips [6,7,8,9].
|
||||
* Conway, Simon (BadBeard)
|
||||
For validating the "Z80 Test Suite" on several Z80 clones [13].
|
||||
* Cooke, Simon
|
||||
For finding out how the "out (c),0" instruction behaves on the Zilog Z80
|
||||
CMOS [14].
|
||||
* Cringle, Frank D.
|
||||
For writing the "Z80 Instruction Set Exerciser" [15].
|
||||
* Devic, Goran
|
||||
For his research on undocumented behaviors of the Z80 CPU [16].
|
||||
* Flammenkamp, Achim
|
||||
* For his article on Z80 interrupts [17].
|
||||
* Gimeno Fortea, Pedro
|
||||
1. For his research work [18].
|
||||
2. For writing the first-ever ZX Spectrum emulator [19,20].
|
||||
* goodboy
|
||||
For testing the behavior of the MEMPTR register on real Z80 chips [6,7,8,9].
|
||||
* Greenway, Ian
|
||||
For testing the flag behavior of the "ccf/scf" instructions on real hardware
|
||||
[10,21].
|
||||
* Harston, Jonathan Graham
|
||||
1. For his technical documents about the Zilog Z80 [22,23,24].
|
||||
2. For porting the "Z80 Instruction Set Exerciser" to the ZX Spectrum [25].
|
||||
* Helcmanovsky, Peter (Ped7g)
|
||||
1. For helping me to write the "IN-MEMPTR" test.
|
||||
2. For writing the "Z80 Block Flags Test" [26,27].
|
||||
3. For writing the "Z80 CCF SCF Outcome Stability" test [27].
|
||||
4. For writing the "Z80 INT Skip" test [27].
|
||||
5. For his research on the unstable flag behavior of the "ccf/scf"
|
||||
instructions.
|
||||
6. For his invaluable help.
|
||||
* icebear
|
||||
For testing the behavior of the MEMPTR register on real Z80 chips [6,7,8,9].
|
||||
* Kladov, Vladimir
|
||||
For cracking the behavior of the MEMPTR register [6,7,8,9].
|
||||
* Krook, Magnus
|
||||
For validating tests on real hardware [28].
|
||||
* London, Matthew
|
||||
For validating tests on real hardware.
|
||||
* Molodtsov, Aleksandr
|
||||
For testing the behavior of the MEMPTR register on real Z80 chips [6,7,8,9].
|
||||
* Nair, Arjun
|
||||
For validating tests on real hardware [26].
|
||||
* Nicolás-González, César
|
||||
For helping me to research the unstable flag behavior of the "ccf/scf"
|
||||
instructions.
|
||||
* Ortega Sosa, Sofía
|
||||
For her support.
|
||||
* Owen, Simon
|
||||
For the idea of the hooking method used in this emulator.
|
||||
* Rak, Patrik
|
||||
1. For improving the "Z80 Instruction Set Exerciser for Spectrum" [29].
|
||||
2. For cracking the flag behavior of the "ccf/scf" instructions [13,29].
|
||||
3. For writing the "Zilog Z80 CPU Test Suite" [29,30].
|
||||
4. For his research on the unstable flag behavior of the "ccf/scf"
|
||||
instructions.
|
||||
* Rodríguez Jódar, Miguel Ángel (mcleod_ideafix)
|
||||
For his reseach on the state of the registers after POWER/RESET [31].
|
||||
* Rodríguez Palomino, Mario (r-lyeh)
|
||||
For teaching me how emulators work.
|
||||
* Sainz de Baranda y Romero, Manuel
|
||||
For teaching me programming and giving me my first computer.
|
||||
* Sánchez Ordiñana, José Ismael (Vaporatorius)
|
||||
For validating tests on real hardware [32,33].
|
||||
* Stevenson, Dave
|
||||
1. For testing the special RESET on real hardware [11].
|
||||
2. For performing low-level tests on real hardware [34].
|
||||
* Weissflog, Andre (Floh)
|
||||
1. For finding out that the "reti/retn" instructions defer the acceptance of
|
||||
the maskable interrupt [35].
|
||||
2. For writing the "Visual Z80 Remix" simulator [36].
|
||||
* Wilkinson, Oli (evolutional)
|
||||
For validating tests on real hardware [26].
|
||||
* Wlodek
|
||||
For testing the behavior of the MEMPTR register on real Z80 chips [6,7,8,9].
|
||||
* Woodmass, Mark (Woody)
|
||||
1. For his invaluable contributions to the emuscene.
|
||||
2. For writing the "Z80 Test Suite" [13].
|
||||
3. For his research on the flag behavior of the "ccf/scf" instructions [37].
|
||||
4. For writing the "HALT2INT" test.
|
||||
5. For writing the "EIHALT" test.
|
||||
* Young, Sean
|
||||
1. For his research work.
|
||||
2. For his technical documents about the Zilog Z80 [18,38].
|
||||
* ZXGuesser
|
||||
For validating tests on real hardware.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
1. https://spectrumcomputing.co.uk/forums/viewtopic.php?p=83384#p83384
|
||||
2. https://stardot.org.uk/forums/viewtopic.php?t=15464
|
||||
* https://stardot.org.uk/forums/viewtopic.php?p=211042#p211042
|
||||
* https://stardot.org.uk/forums/viewtopic.php?p=212021#p212021
|
||||
3. Banks, David (2018-08-21). "Undocumented Z80 Flags".
|
||||
* https://github.com/hoglet67/Z80Decoder/wiki/Undocumented-Flags
|
||||
* https://stardot.org.uk/forums/download/file.php?id=39831
|
||||
4. https://spectrumcomputing.co.uk/forums/viewtopic.php?p=83041#p83041
|
||||
5. http://wizard.ae.krakow.pl/~jb/qaop/tests.html
|
||||
6. https://zxpress.ru/zxnet/zxnet.pc/5909
|
||||
7. https://zx-pk.ru/threads/2506-komanda-bit-n-(hl).html
|
||||
8. https://zx-pk.ru/threads/2586-prosba-realshchikam-ot-emulyatorshchikov.html
|
||||
9. boo_boo; Kladov, Vladimir (2006-03-29). "MEMPTR: esoteric register of the
|
||||
Zilog Z80 CPU".
|
||||
* http://zx.pk.ru/showpost.php?p=43688
|
||||
* http://zx.pk.ru/attachment.php?attachmentid=2984
|
||||
* http://zx.pk.ru/showpost.php?p=43800
|
||||
* http://zx.pk.ru/attachment.php?attachmentid=2989
|
||||
10. https://sourceforge.net/p/fuse-emulator/mailman/message/6929573
|
||||
11. Brewer, Tony (2014-12). "Z80 Special Reset".
|
||||
* http://primrosebank.net/computers/z80/z80_special_reset.htm
|
||||
12. https://mtxworld.dk/memorum/viewtopic.php?p=1352#p1352
|
||||
13. https://worldofspectrum.org/forums/discussion/20345
|
||||
14. https://groups.google.com/g/comp.os.cpm/c/HfSTFpaIkuU/m/KotvMWu3bZoJ
|
||||
15. Cringle, Frank D. (1998-01-28). "Yaze - Yet Another Z80 Emulator" v1.10.
|
||||
* ftp://ftp.ping.de/pub/misc/emulators/yaze-1.10.tar.gz
|
||||
16. https://baltazarstudios.com/zilog-z80-undocumented-behavior
|
||||
17. Flammenkamp, Achim. "Interrupt Behaviour of the Z80 CPU".
|
||||
* http://z80.info/interrup.htm
|
||||
18. Young, Sean (1998-10). "Z80 Undocumented Features (in Software Behaviour)".
|
||||
19. https://elmundodelspectrum.com/desenterrando-el-primer-emulador-de-spectrum
|
||||
20. https://elmundodelspectrum.com/con-vosotros-el-emulador-de-pedro-gimeno-1989
|
||||
21. https://sourceforge.net/p/fuse-emulator/mailman/message/4502844
|
||||
22. Harston, Jonathan Graham (1997-09-09). "Z80 Opcode Map".
|
||||
* https://mdfs.net/Docs/Comp/Z80/OpCodeMap
|
||||
23. Harston, Jonathan Graham (1997-12-18). "Z80 Microprocessor Undocumented
|
||||
Instructions".
|
||||
* https://mdfs.net/Docs/Comp/Z80/UnDocOps
|
||||
24. Harston, Jonathan Graham (1998-04-15). "Full Z80 Opcode List Including
|
||||
Undocumented Opcodes".
|
||||
* https://mdfs.net/Docs/Comp/Z80/OpList
|
||||
25. https://mdfs.net/Software/Z80/Exerciser/Spectrum
|
||||
26. https://spectrumcomputing.co.uk/forums/viewtopic.php?t=6102
|
||||
27. https://github.com/MrKWatkins/ZXSpectrumNextTests
|
||||
28. https://spectrumcomputing.co.uk/forums/viewtopic.php?p=83157#p83157
|
||||
29. https://worldofspectrum.org/forums/discussion/41704
|
||||
* http://zxds.raxoft.cz/taps/misc/zexall2.zip
|
||||
30. https://worldofspectrum.org/forums/discussion/41834
|
||||
* http://zxds.raxoft.cz/taps/misc/z80test-1.0.zip
|
||||
* https://github.com/raxoft/z80test
|
||||
31. https://worldofspectrum.org/forums/discussion/34574
|
||||
32. https://worldofspectrum.org/forums/discussion/comment/668760/#Comment_668760
|
||||
33. https://jisanchez.com/test-a-dos-placas-de-zx-spectrum
|
||||
34. https://stardot.org.uk/forums/viewtopic.php?p=212360#p212360
|
||||
35. https://floooh.github.io/2021/12/17/cycle-stepped-z80.html
|
||||
36. https://github.com/floooh/v6502r
|
||||
37. http://groups.google.co.uk/group/comp.sys.sinclair/msg/56dd1fd4ccb5fb3b
|
||||
38. Young, Sean (2005-09-18). "Undocumented Z80 Documented, The".
|
||||
* http://www.myquest.nl/z80undocumented
|
||||
* http://www.myquest.nl/z80undocumented/z80-documented-v0.91.pdf
|
||||
4
building/.gitignore
vendored
4
building/.gitignore
vendored
@@ -1,4 +0,0 @@
|
||||
**
|
||||
!.gitignore
|
||||
!premake4.lua
|
||||
!premake5.lua
|
||||
@@ -1,33 +0,0 @@
|
||||
solution "Z80"
|
||||
configurations {
|
||||
"release-dynamic", "release-dynamic-module", "release-static", "release-static-module",
|
||||
"debug-dynamic", "debug-dynamic-module", "debug-static", "debug-static-module"
|
||||
}
|
||||
|
||||
project "Z80"
|
||||
language "C"
|
||||
flags {"ExtraWarnings"}
|
||||
files {"../sources/**.c"}
|
||||
includedirs {"../API"}
|
||||
--buildoptions {"-std=c89 -pedantic -Wall -Weverything"}
|
||||
|
||||
configuration "release*"
|
||||
targetdir "lib/release"
|
||||
flags {"Optimize"}
|
||||
|
||||
configuration "debug*"
|
||||
targetdir "lib/debug"
|
||||
flags {"Symbols"}
|
||||
|
||||
configuration "*dynamic*"
|
||||
kind "SharedLib"
|
||||
|
||||
configuration "*dynamic-module"
|
||||
defines {"CPU_Z80_WITH_MODULE_ABI"}
|
||||
|
||||
configuration "*static*"
|
||||
kind "StaticLib"
|
||||
defines {"CPU_Z80_STATIC"}
|
||||
|
||||
configuration "*static-module"
|
||||
defines {"CPU_Z80_WITH_ABI"}
|
||||
3
development/Xcode/Z80.xcodeproj/.gitignore
vendored
3
development/Xcode/Z80.xcodeproj/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
**
|
||||
!.gitignore
|
||||
!project.pbxproj
|
||||
@@ -1,520 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
6428A5751AAFC6DF00634F5D /* Z80.h in Headers */ = {isa = PBXBuildFile; fileRef = 6428A5741AAFC6DF00634F5D /* Z80.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6428A5771AAFC72900634F5D /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; };
|
||||
6428A5801AAFEF1D00634F5D /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; settings = {COMPILER_FLAGS = "-DCPU_Z80_STATIC"; }; };
|
||||
648C13AF1CCDFA8D00C8DCE1 /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; settings = {COMPILER_FLAGS = "-DCPU_Z80_WITH_MODULE_ABI"; }; };
|
||||
648C13B21CCDFA8D00C8DCE1 /* Z80.h in Headers */ = {isa = PBXBuildFile; fileRef = 6428A5741AAFC6DF00634F5D /* Z80.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
648C13C31CCDFBEF00C8DCE1 /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; settings = {COMPILER_FLAGS = "-DCPU_Z80_STATIC -DCPU_Z80_WITH_ABI"; }; };
|
||||
64F8E3361CD656DA0083A613 /* Z80.h in Headers */ = {isa = PBXBuildFile; fileRef = 6428A5741AAFC6DF00634F5D /* Z80.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
64F8E3371CD656DB0083A613 /* Z80.h in Headers */ = {isa = PBXBuildFile; fileRef = 6428A5741AAFC6DF00634F5D /* Z80.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
6428A5691AAFC68700634F5D /* libZ80.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libZ80.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6428A5741AAFC6DF00634F5D /* Z80.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Z80.h; sourceTree = "<group>"; };
|
||||
6428A5761AAFC72900634F5D /* Z80.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Z80.c; sourceTree = "<group>"; };
|
||||
6428A57C1AAFEDED00634F5D /* libZ80.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libZ80.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
648C13B61CCDFA8D00C8DCE1 /* libZ80.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libZ80.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
648C13C91CCDFBEF00C8DCE1 /* libZ80.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libZ80.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
6428A5661AAFC68700634F5D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6428A5791AAFEDED00634F5D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
648C13B01CCDFA8D00C8DCE1 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
648C13C41CCDFBEF00C8DCE1 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
6428A5601AAFC68700634F5D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6428A5711AAFC69A00634F5D /* API */,
|
||||
6428A5701AAFC69100634F5D /* Sources */,
|
||||
6428A56A1AAFC68700634F5D /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6428A56A1AAFC68700634F5D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6428A5691AAFC68700634F5D /* libZ80.dylib */,
|
||||
6428A57C1AAFEDED00634F5D /* libZ80.a */,
|
||||
648C13B61CCDFA8D00C8DCE1 /* libZ80.dylib */,
|
||||
648C13C91CCDFBEF00C8DCE1 /* libZ80.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6428A5701AAFC69100634F5D /* Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6428A5761AAFC72900634F5D /* Z80.c */,
|
||||
);
|
||||
name = Sources;
|
||||
path = ../../sources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6428A5711AAFC69A00634F5D /* API */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6428A5741AAFC6DF00634F5D /* Z80.h */,
|
||||
);
|
||||
name = API;
|
||||
path = ../../API/emulation/CPU;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
6428A5671AAFC68700634F5D /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6428A5751AAFC6DF00634F5D /* Z80.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6428A57A1AAFEDED00634F5D /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
64F8E3361CD656DA0083A613 /* Z80.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
648C13B11CCDFA8D00C8DCE1 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
648C13B21CCDFA8D00C8DCE1 /* Z80.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
648C13C51CCDFBEF00C8DCE1 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
64F8E3371CD656DB0083A613 /* Z80.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
6428A5681AAFC68700634F5D /* Z80 (dynamic) */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6428A56D1AAFC68700634F5D /* Build configuration list for PBXNativeTarget "Z80 (dynamic)" */;
|
||||
buildPhases = (
|
||||
6428A5651AAFC68700634F5D /* Sources */,
|
||||
6428A5661AAFC68700634F5D /* Frameworks */,
|
||||
6428A5671AAFC68700634F5D /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Z80 (dynamic)";
|
||||
productName = Z80;
|
||||
productReference = 6428A5691AAFC68700634F5D /* libZ80.dylib */;
|
||||
productType = "com.apple.product-type.library.dynamic";
|
||||
};
|
||||
6428A57B1AAFEDED00634F5D /* Z80 (static) */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6428A57D1AAFEDED00634F5D /* Build configuration list for PBXNativeTarget "Z80 (static)" */;
|
||||
buildPhases = (
|
||||
6428A5781AAFEDED00634F5D /* Sources */,
|
||||
6428A5791AAFEDED00634F5D /* Frameworks */,
|
||||
6428A57A1AAFEDED00634F5D /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Z80 (static)";
|
||||
productName = "Z80-Static";
|
||||
productReference = 6428A57C1AAFEDED00634F5D /* libZ80.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
648C13AD1CCDFA8D00C8DCE1 /* Z80 (dynamic module) */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 648C13B31CCDFA8D00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (dynamic module)" */;
|
||||
buildPhases = (
|
||||
648C13AE1CCDFA8D00C8DCE1 /* Sources */,
|
||||
648C13B01CCDFA8D00C8DCE1 /* Frameworks */,
|
||||
648C13B11CCDFA8D00C8DCE1 /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Z80 (dynamic module)";
|
||||
productName = Z80;
|
||||
productReference = 648C13B61CCDFA8D00C8DCE1 /* libZ80.dylib */;
|
||||
productType = "com.apple.product-type.library.dynamic";
|
||||
};
|
||||
648C13C11CCDFBEF00C8DCE1 /* Z80 (static module) */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 648C13C61CCDFBEF00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (static module)" */;
|
||||
buildPhases = (
|
||||
648C13C21CCDFBEF00C8DCE1 /* Sources */,
|
||||
648C13C41CCDFBEF00C8DCE1 /* Frameworks */,
|
||||
648C13C51CCDFBEF00C8DCE1 /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Z80 (static module)";
|
||||
productName = "Z80-Static";
|
||||
productReference = 648C13C91CCDFBEF00C8DCE1 /* libZ80.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
6428A5611AAFC68700634F5D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = "Manuel Sainz de Baranda y Goñi";
|
||||
TargetAttributes = {
|
||||
6428A5681AAFC68700634F5D = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
6428A57B1AAFEDED00634F5D = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 6428A5641AAFC68700634F5D /* Build configuration list for PBXProject "Z80" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 6428A5601AAFC68700634F5D;
|
||||
productRefGroup = 6428A56A1AAFC68700634F5D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
6428A5681AAFC68700634F5D /* Z80 (dynamic) */,
|
||||
648C13AD1CCDFA8D00C8DCE1 /* Z80 (dynamic module) */,
|
||||
6428A57B1AAFEDED00634F5D /* Z80 (static) */,
|
||||
648C13C11CCDFBEF00C8DCE1 /* Z80 (static module) */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
6428A5651AAFC68700634F5D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6428A5771AAFC72900634F5D /* Z80.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6428A5781AAFEDED00634F5D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6428A5801AAFEF1D00634F5D /* Z80.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
648C13AE1CCDFA8D00C8DCE1 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
648C13AF1CCDFA8D00C8DCE1 /* Z80.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
648C13C21CCDFBEF00C8DCE1 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
648C13C31CCDFBEF00C8DCE1 /* Z80.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
6428A56B1AAFC68700634F5D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_ASSIGN_ENUM = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_FLOAT_CONVERSION = YES;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_BUILTIN_FUNCTIONS = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
|
||||
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
|
||||
GCC_WARN_SHADOW = YES;
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_LABEL = YES;
|
||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/local/include,
|
||||
../../API,
|
||||
);
|
||||
LINK_WITH_STANDARD_LIBRARIES = NO;
|
||||
LLVM_LTO = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
STRIP_STYLE = "non-global";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6428A56C1AAFC68700634F5D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_ASSIGN_ENUM = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_FLOAT_CONVERSION = YES;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_ENABLE_BUILTIN_FUNCTIONS = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
|
||||
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
|
||||
GCC_WARN_SHADOW = YES;
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_LABEL = YES;
|
||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/local/include,
|
||||
../../API,
|
||||
);
|
||||
LINK_WITH_STANDARD_LIBRARIES = NO;
|
||||
LLVM_LTO = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
STRIP_STYLE = "non-global";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
6428A56E1AAFC68700634F5D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DYLIB_COMPATIBILITY_VERSION = 0;
|
||||
DYLIB_CURRENT_VERSION = 0.1.0;
|
||||
EXECUTABLE_PREFIX = lib;
|
||||
PRODUCT_NAME = Z80;
|
||||
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/emulation/CPU;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6428A56F1AAFC68700634F5D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DYLIB_COMPATIBILITY_VERSION = 0;
|
||||
DYLIB_CURRENT_VERSION = 0.1.0;
|
||||
EXECUTABLE_PREFIX = lib;
|
||||
PRODUCT_NAME = Z80;
|
||||
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/emulation/CPU;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
6428A57E1AAFEDED00634F5D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = Z80;
|
||||
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/emulation/CPU;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6428A57F1AAFEDED00634F5D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = Z80;
|
||||
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/emulation/CPU;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
648C13B41CCDFA8D00C8DCE1 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DYLIB_COMPATIBILITY_VERSION = 0;
|
||||
DYLIB_CURRENT_VERSION = 0.1.0;
|
||||
EXECUTABLE_PREFIX = lib;
|
||||
PRODUCT_NAME = Z80;
|
||||
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/emulation/CPU;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
648C13B51CCDFA8D00C8DCE1 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DYLIB_COMPATIBILITY_VERSION = 0;
|
||||
DYLIB_CURRENT_VERSION = 0.1.0;
|
||||
EXECUTABLE_PREFIX = lib;
|
||||
PRODUCT_NAME = Z80;
|
||||
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/emulation/CPU;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
648C13C71CCDFBEF00C8DCE1 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = Z80;
|
||||
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/emulation/CPU;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
648C13C81CCDFBEF00C8DCE1 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = Z80;
|
||||
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/emulation/CPU;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
6428A5641AAFC68700634F5D /* Build configuration list for PBXProject "Z80" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6428A56B1AAFC68700634F5D /* Debug */,
|
||||
6428A56C1AAFC68700634F5D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
6428A56D1AAFC68700634F5D /* Build configuration list for PBXNativeTarget "Z80 (dynamic)" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6428A56E1AAFC68700634F5D /* Debug */,
|
||||
6428A56F1AAFC68700634F5D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
6428A57D1AAFEDED00634F5D /* Build configuration list for PBXNativeTarget "Z80 (static)" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6428A57E1AAFEDED00634F5D /* Debug */,
|
||||
6428A57F1AAFEDED00634F5D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
648C13B31CCDFA8D00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (dynamic module)" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
648C13B41CCDFA8D00C8DCE1 /* Debug */,
|
||||
648C13B51CCDFA8D00C8DCE1 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
648C13C61CCDFBEF00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (static module)" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
648C13C71CCDFBEF00C8DCE1 /* Debug */,
|
||||
648C13C81CCDFBEF00C8DCE1 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 6428A5611AAFC68700634F5D /* Project object */;
|
||||
}
|
||||
54
documentation/APIReference.rst
Normal file
54
documentation/APIReference.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
=============
|
||||
API reference
|
||||
=============
|
||||
|
||||
Macros
|
||||
------
|
||||
|
||||
.. doxygendefine:: Z80_LIBRARY_VERSION_MAJOR
|
||||
.. doxygendefine:: Z80_LIBRARY_VERSION_MINOR
|
||||
.. doxygendefine:: Z80_LIBRARY_VERSION_MICRO
|
||||
.. doxygendefine:: Z80_LIBRARY_VERSION_STRING
|
||||
.. doxygendefine:: Z80_CYCLE_LIMIT
|
||||
.. doxygendefine:: Z80_HOOK
|
||||
|
||||
.. doxygendefine:: Z80_MODEL_ZILOG_NMOS
|
||||
.. doxygendefine:: Z80_MODEL_ZILOG_CMOS
|
||||
|
||||
.. doxygendefine:: Z80_REQUEST_SPECIAL_RESET
|
||||
.. doxygendefine:: Z80_REQUEST_RESET
|
||||
.. doxygendefine:: Z80_REQUEST_NMI
|
||||
.. doxygendefine:: Z80_REQUEST_INT
|
||||
|
||||
.. doxygendefine:: Z80_RESUME_HALT
|
||||
.. doxygendefine:: Z80_RESUME_XY
|
||||
.. doxygendefine:: Z80_RESUME_IM0_XY
|
||||
|
||||
Callback Types
|
||||
--------------
|
||||
|
||||
.. doxygentypedef:: Z80Read
|
||||
.. doxygentypedef:: Z80Write
|
||||
.. doxygentypedef:: Z80HALT
|
||||
.. doxygentypedef:: Z80Notify
|
||||
|
||||
Objects
|
||||
-------
|
||||
|
||||
.. doxygenstruct:: Z80
|
||||
:members:
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. doxygenfunction:: z80_in_offset
|
||||
.. doxygenfunction:: z80_instant_reset
|
||||
.. doxygenfunction:: z80_out_offset
|
||||
.. doxygenfunction:: z80_execute
|
||||
.. doxygenfunction:: z80_int
|
||||
.. doxygenfunction:: z80_nmi
|
||||
.. doxygenfunction:: z80_normal_reset
|
||||
.. doxygenfunction:: z80_power
|
||||
.. doxygenfunction:: z80_refresh_address
|
||||
.. doxygenfunction:: z80_run
|
||||
.. doxygenfunction:: z80_special_reset
|
||||
100
documentation/CMakeLists.txt
Normal file
100
documentation/CMakeLists.txt
Normal file
@@ -0,0 +1,100 @@
|
||||
# Z80 - documentation/CMakeLists.txt
|
||||
# ______ ______ ______
|
||||
# /\___ \/\ __ \\ __ \
|
||||
# \/__/ /\_\ __ \\ \/\ \
|
||||
# /\_____\\_____\\_____\
|
||||
# Zilog \/_____//_____//_____/ CPU Emulator
|
||||
# Copyright (C) 1999-2022 Manuel Sainz de Baranda y Goñi.
|
||||
# Released under the terms of the GNU Lesser General Public License v3.
|
||||
|
||||
find_package(Doxygen REQUIRED)
|
||||
find_package(Sphinx REQUIRED)
|
||||
find_package(Breathe REQUIRED)
|
||||
|
||||
set(DOXYGEN_INPUT_DIR "${PROJECT_SOURCE_DIR}/API" )
|
||||
set(DOXYGEN_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}" )
|
||||
set(DOXYGEN_XML_OUTPUT "API-XML" )
|
||||
set(_doxyfile_in "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in")
|
||||
set(_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile" )
|
||||
|
||||
get_target_property(DOXYGEN_INCLUDE_PATH Zeta INTERFACE_INCLUDE_DIRECTORIES)
|
||||
configure_file(${_doxyfile_in} ${_doxyfile} @ONLY)
|
||||
|
||||
file(GLOB_RECURSE _public_headers ${DOXYGEN_INPUT_DIR}/*.h)
|
||||
set(_api_xml_output "${DOXYGEN_OUTPUT_DIR}/${DOXYGEN_XML_OUTPUT}")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_api_xml_output}
|
||||
DEPENDS ${_public_headers}
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${_doxyfile}
|
||||
MAIN_DEPENDENCY ${_doxyfile}
|
||||
COMMENT "Extracting API reference")
|
||||
|
||||
add_custom_target(API-XML ALL DEPENDS ${_api_xml_output})
|
||||
|
||||
if(${PROJECT_NAME}_WITH_HTML_DOCUMENTATION)
|
||||
set(_html_documentation_output "${CMAKE_CURRENT_BINARY_DIR}/HTML")
|
||||
|
||||
if(${PROJECT_NAME}_SPHINX_HTML_THEME STREQUAL "")
|
||||
set(_html_theme_option "")
|
||||
else()
|
||||
set(_html_theme_option "-Dhtml_theme=${${PROJECT_NAME}_SPHINX_HTML_THEME}")
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_html_documentation_output}
|
||||
COMMAND ${SPHINX_BUILD_EXECUTABLE}
|
||||
-b html
|
||||
${_html_theme_option}
|
||||
"-Dbreathe_projects.${PROJECT_NAME}=${_api_xml_output}"
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${_html_documentation_output}
|
||||
MAIN_DEPENDENCY ${_api_xml_output}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating documentation in HTML format")
|
||||
|
||||
add_custom_target(Documentation-HTML ALL DEPENDS ${_html_documentation_output})
|
||||
add_dependencies(Documentation-HTML API-XML)
|
||||
|
||||
install(DIRECTORY "${_html_documentation_output}/"
|
||||
DESTINATION "${CMAKE_INSTALL_DOCDIR}/documentation")
|
||||
endif()
|
||||
|
||||
if(${PROJECT_NAME}_WITH_PDF_DOCUMENTATION)
|
||||
find_package(LATEX REQUIRED COMPONENTS PDFLATEX)
|
||||
|
||||
set(_latex_documentation_output "${CMAKE_CURRENT_BINARY_DIR}/LaTeX")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_latex_documentation_output}
|
||||
COMMAND ${SPHINX_BUILD_EXECUTABLE}
|
||||
-b latex
|
||||
"-Dbreathe_projects.${PROJECT_NAME}=${_api_xml_output}"
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${_latex_documentation_output}
|
||||
MAIN_DEPENDENCY ${_api_xml_output}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating documentation in LaTeX format")
|
||||
|
||||
add_custom_target(Documentation-LaTeX ALL DEPENDS ${_latex_documentation_output})
|
||||
add_dependencies(Documentation-LaTeX API-XML)
|
||||
|
||||
string(TOLOWER ${PROJECT_NAME} _pdf_documentation_output)
|
||||
set(_pdf_documentation_output "${_latex_documentation_output}/${_pdf_documentation_output}.pdf")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_pdf_documentation_output}
|
||||
COMMAND make
|
||||
MAIN_DEPENDENCY ${_latex_documentation_output}
|
||||
WORKING_DIRECTORY ${_latex_documentation_output}
|
||||
COMMENT "Converting documentation to PDF format")
|
||||
|
||||
add_custom_target(Documentation-PDF ALL DEPENDS ${_pdf_documentation_output})
|
||||
add_dependencies(Documentation-PDF Documentation-LaTeX)
|
||||
|
||||
install(FILES ${_pdf_documentation_output}
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||
RENAME "${PROJECT_NAME} v${PROJECT_VERSION}.pdf")
|
||||
endif()
|
||||
|
||||
# documentation/CMakeLists.txt EOF
|
||||
376
documentation/Doxyfile.in
Normal file
376
documentation/Doxyfile.in
Normal file
@@ -0,0 +1,376 @@
|
||||
# Doxyfile 1.8.15
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "@PROJECT_NAME@"
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = "@DOXYGEN_OUTPUT_DIR@"
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
OUTPUT_TEXT_DIRECTION = None
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH = "@DOXYGEN_INPUT_DIR@"
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 8
|
||||
ALIASES = "overline="
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
OPTIMIZE_OUTPUT_SLICE = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
AUTOLINK_SUPPORT = NO
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
GROUP_NESTED_COMPOUNDS = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_AS_ERROR = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The INPUT tag is used to specify the files and/or directories that contain
|
||||
# documented source files. You may enter file names like myfile.cpp or
|
||||
# directories like /usr/src/myproject. Separate the files or directories with
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = "@DOXYGEN_INPUT_DIR@"
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.h
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
GENERATE_HTML = NO
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = NO
|
||||
HTML_DYNAMIC_MENUS = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = YES
|
||||
DOCSET_FEEDNAME = "Zilog Z80 CPU Emulator"
|
||||
DOCSET_BUNDLE_ID = com.redcode.Z80
|
||||
DOCSET_PUBLISHER_ID = com.redcode
|
||||
DOCSET_PUBLISHER_NAME = "Manuel Sainz de Baranda y Goñi"
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME =
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
LATEX_MAKEINDEX_CMD = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
LATEX_EXTRA_STYLESHEET =
|
||||
LATEX_EXTRA_FILES =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_TIMESTAMP = NO
|
||||
LATEX_EMOJI_DIRECTORY =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_SOURCE_CODE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_SUBDIR =
|
||||
MAN_LINKS = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
GENERATE_XML = YES
|
||||
XML_OUTPUT = "@DOXYGEN_XML_OUTPUT@"
|
||||
XML_PROGRAMLISTING = YES
|
||||
XML_NS_MEMB_FILE_SCOPE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH = "@DOXYGEN_INCLUDE_PATH@"
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED = Z80_API=
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
CLASS_DIAGRAMS = YES
|
||||
MSCGEN_PATH =
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = NO
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
PLANTUML_JAR_PATH =
|
||||
PLANTUML_CFG_FILE =
|
||||
PLANTUML_INCLUDE_PATH =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
3
documentation/EmulationAccuracy.rst
Normal file
3
documentation/EmulationAccuracy.rst
Normal file
@@ -0,0 +1,3 @@
|
||||
==================
|
||||
Emulation accuracy
|
||||
==================
|
||||
170
documentation/Installation.rst
Normal file
170
documentation/Installation.rst
Normal file
@@ -0,0 +1,170 @@
|
||||
============
|
||||
Installation
|
||||
============
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. |br| raw:: html
|
||||
|
||||
<br />
|
||||
|
||||
.. only:: latex
|
||||
|
||||
.. |nl| raw:: latex
|
||||
|
||||
\newline
|
||||
|
||||
You will need `CMake <https://cmake.org>`_ v3.14 or later to build the package and, optionally, recent versions of `Doxygen <https://www.doxygen.nl>`_, `Sphinx <https://www.sphinx-doc.org>`_ and `Breathe <https://github.com/michaeljones/breathe>`_ to compile the documentation. Also make sure you have `LaTeX <https://www.latex-project.org>`_ with PDF support installed on your system in case you want to generate the documentation in PDF format.
|
||||
|
||||
The emulator requires some types and macros included in `Zeta <https://zeta.st>`_, a dependency-free, `header-only <https://en.wikipedia.org/wiki/Header-only>`_ library used to retain compatibility with most C compilers. Install Zeta or extract its official source code package to the directory of the Z80 project or its parent directory. Zeta is the sole dependency; the emulator is a freestanding implementation and as such does not depend on the
|
||||
`C standard library <https://en.wikipedia.org/wiki/C_standard_library>`_.
|
||||
|
||||
Once all requirements are met, create a directory and run ``cmake`` from there to prepare the build system:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake <path to the Z80 project> [options]
|
||||
|
||||
The resulting build files can be configured by passing options to ``cmake``. To show a complete list of those available along with their current settings, type the following:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
cmake -LAH
|
||||
|
||||
If in doubt, read the `CMake documentation <https://cmake.org/documentation/>`_ for more information on configuration options. The following are some of the most relevant standard options of CMake:
|
||||
|
||||
.. option:: -DBUILD_SHARED_LIBS=(YES|NO)
|
||||
|
||||
Build the project as a shared library rather than a static one. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DCMAKE_BUILD_TYPE=(Debug|Release|RelWithDebInfo)
|
||||
|
||||
Choose the type of build (configuration) to generate. |br| |nl|
|
||||
The default is ``Release``.
|
||||
|
||||
.. option:: -DCMAKE_INSTALL_PREFIX="<path>"
|
||||
|
||||
Specify the installation prefix on `UNIX <https://en.wikipedia.org/wiki/Unix>`_ and `UNIX-like <https://en.wikipedia.org/wiki/Unix-like>`_ operating systems. |br| |nl|
|
||||
The default is ``"/usr/local"``.
|
||||
|
||||
Package-specific options are prefixed with ``Z80_`` and can be divided into two groups. The first one controls aspects not related to the source code of the library:
|
||||
|
||||
.. option:: -DZ80_DOWNLOAD_TEST_FILES=(YES|NO)
|
||||
|
||||
Download the firmware and software used by the testing tool. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_INSTALL_CMAKEDIR="<path>"
|
||||
|
||||
Specify the directory in which to install the CMake `config-file package <https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#config-file-packages>`_. |br| |nl|
|
||||
The default is ``"${CMAKE_INSTALL_LIBDIR}/cmake/Z80"``.
|
||||
|
||||
.. option:: -DZ80_INSTALL_PKGCONFIGDIR="<path>"
|
||||
|
||||
Specify the directory in which to install the `pkg-config <https://www.freedesktop.org/wiki/Software/pkg-config>`_ `file <https://people.freedesktop.org/~dbn/pkg-config-guide.html>`_. |br| |nl|
|
||||
The default is ``"${CMAKE_INSTALL_LIBDIR}/pkgconfig"``.
|
||||
|
||||
.. option:: -DZ80_NOSTDLIB_FLAGS=(Auto|[<flag>[;<flag>...]])
|
||||
|
||||
Specify the linker flags used to avoid linking against system libraries. |br| |nl|
|
||||
The default is ``Auto`` (autoconfigure flags). If you get linker errors, set this option to ``""``.
|
||||
|
||||
.. option:: -DZ80_SHARED_LIBS=(YES|NO)
|
||||
|
||||
Build the project as a shared library rather than a static one. |br| |nl|
|
||||
This option takes precedence over ``BUILD_SHARED_LIBS``. |br| |nl|
|
||||
Not defined by default.
|
||||
|
||||
.. option:: -DZ80_SPHINX_HTML_THEME="[<name>]"
|
||||
|
||||
Specify the Sphinx theme for the documentation in HTML format. |br| |nl|
|
||||
The default is ``""`` (use the default theme).
|
||||
|
||||
.. option:: -DZ80_WITH_CMAKE_SUPPORT=(YES|NO)
|
||||
|
||||
Generate and install the CMake `config-file package <https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#config-file-packages>`_. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_HTML_DOCUMENTATION=(YES|NO)
|
||||
|
||||
Build and install the documentation in HTML format. |br| |nl|
|
||||
It requires Doxygen, Sphinx and Breathe. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_PDF_DOCUMENTATION=(YES|NO)
|
||||
|
||||
Build and install the documentation in PDF format. |br| |nl|
|
||||
It requires Doxygen, Sphinx, Breathe and LaTeX with PDF support. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_PKGCONFIG_SUPPORT=(YES|NO)
|
||||
|
||||
Generate and install the `pkg-config <https://www.freedesktop.org/wiki/Software/pkg-config>`_ `file <https://people.freedesktop.org/~dbn/pkg-config-guide.html>`_. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_STANDARD_DOCUMENTS=(YES|NO)
|
||||
|
||||
Install the standard text documents distributed with the package: ``AUTHORS``, ``COPYING``, ``COPYING.LESSER``, ``HISTORY``, ``README`` and ``THANKS``. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_TESTS=(YES|NO)
|
||||
|
||||
Build the testing tool. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
The second group of package-specific options configures the source code of the library by predefining macros that enable optional implementations:
|
||||
|
||||
.. option:: -DZ80_WITH_EXECUTE=(YES|NO)
|
||||
|
||||
Build the implementation of the ``z80_execute`` function. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_FULL_IM0=(YES|NO)
|
||||
|
||||
Build the full implementation of the interrupt mode 0 rather than the reduced one. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_Q=(YES|NO)
|
||||
|
||||
Build the implementation of the `Q "register" <https://worldofspectrum.org/forums/discussion/41704>`_. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_RESET_SIGNAL=(YES|NO)
|
||||
|
||||
Build the implementation of the normal RESET signal. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_SPECIAL_RESET_SIGNAL=(YES|NO)
|
||||
|
||||
Build the implementation of the `special RESET <http://www.primrosebank.net/computers/z80/z80_special_reset.htm>`_ signal. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_UNOFFICIAL_RETI=(YES|NO)
|
||||
|
||||
Configure the ``ED5Dh``, ``ED6Dh`` and ``ED7Dh`` undocumented instructions as ``reti`` instead of ``retn``. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
.. option:: -DZ80_WITH_ZILOG_NMOS_LD_A_IR_BUG=(YES|NO)
|
||||
|
||||
Build the implementation of the bug affecting the Zilog Z80 NMOS, which causes the P/V flag to be reset when a maskable interrupt is accepted during the execution of the ``ld a,{i|r}`` instructions. |br| |nl|
|
||||
The default is ``NO``.
|
||||
|
||||
Package maintainers should use at least the following options for both shared and static library targets:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
-DZ80_WITH_EXECUTE=YES
|
||||
-DZ80_WITH_FULL_IM0=YES
|
||||
-DZ80_WITH_Q=YES
|
||||
-DZ80_WITH_RESET_SIGNAL=YES
|
||||
-DZ80_WITH_ZILOG_NMOS_LD_A_IR_BUG=YES
|
||||
|
||||
Finally, once the build system is configured according to your needs, build and install the package:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
make
|
||||
make install/strip
|
||||
82
documentation/Integration.rst
Normal file
82
documentation/Integration.rst
Normal file
@@ -0,0 +1,82 @@
|
||||
===========
|
||||
Integration
|
||||
===========
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. |br| raw:: html
|
||||
|
||||
<br />
|
||||
|
||||
.. only:: latex
|
||||
|
||||
.. |nl| raw:: latex
|
||||
|
||||
\newline
|
||||
|
||||
As an external dependency in CMake-based projects
|
||||
-------------------------------------------------
|
||||
|
||||
The Z80 library includes find-modules and a config-file package for integration into CMake-based projects. It is recommended to always copy the ``FindZ80.cmake`` and ``FindZeta.cmake`` files into the CMake modules directory of projects that use the library as an external dependency. This will allow CMake to find the library if the necessary config-file packages are not installed on the system.
|
||||
|
||||
Both the config-file package and the find-module support dual installations of the shared and static versions of the Z80 library. You can specify the linking method by using the component mechanism of ``find_package``.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
find_package(Z80 REQUIRED [Shared|Static])
|
||||
target_link_libraries(your-target Z80)
|
||||
|
||||
Omitting the linking method will select the ``Shared`` version of the library or, if not installed, the ``Static`` version instead.
|
||||
|
||||
As a CMake subproject
|
||||
---------------------
|
||||
|
||||
To embed the library as a CMake subproject, just place its entire source tree into a subdirectory of your project.
|
||||
|
||||
It is advisable to configure the library in the ``CMakeLists.txt`` of your project. This will prevent the user from having to specify configuration options of the Z80 subproject through the CMake command line when building the main project. As noted in the Installation section of this document, all package-specific options are prefixed with ``Z80_``, so, in a normal scenario, there should be no risk of name collision with the options and variables of the parent project.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set(Z80_SHARED_LIBS NO CACHE BOOL "")
|
||||
set(Z80_WITH_Q YES CACHE BOOL "")
|
||||
set(Z80_WITH_ZILOG_NMOS_LD_A_IR_BUG YES CACHE BOOL "")
|
||||
|
||||
add_subdirectory(dependencies/Z80)
|
||||
target_link_libraries(your-target Z80)
|
||||
|
||||
It is important to set the ``Z80_SHARED_LIBS`` option. Otherwise CMake will build the library type indicated by ``BUILD_SHARED_LIBS``, which may not be the desired one.
|
||||
|
||||
Manual integration
|
||||
------------------
|
||||
|
||||
There are several macros that can be used to configure the source code of the library. You can define those you need in your build system or at the beginning of the ``Z80.c`` file. The following ones allow you to configure the integration of ``Z80.h`` and ``Z80.c`` into the project:
|
||||
|
||||
.. c:macro:: Z80_DEPENDENCIES_HEADER
|
||||
|
||||
Specifies the only external header to ``#include``, replacing those of Zeta. |br| |nl|
|
||||
If used, it must also be defined before including the ``Z80.h`` header.
|
||||
|
||||
.. c:macro:: Z80_STATIC
|
||||
|
||||
Needed for compiling and/or using the emulator as a static library or as an internal part of other project. |br| |nl|
|
||||
If used, it must also be defined before including the ``Z80.h`` header.
|
||||
|
||||
.. c:macro:: Z80_WITH_LOCAL_HEADER
|
||||
|
||||
Tells ``Z80.c`` to ``#include Z80.h`` instead of ``<Z80.h>``.
|
||||
|
||||
The second group of package-specific options, explained in the "Installation" section of this document, activates various optional implementations in the source code by predefining the following macros:
|
||||
|
||||
.. c:macro:: Z80_WITH_EXECUTE
|
||||
.. c:macro:: Z80_WITH_FULL_IM0
|
||||
.. c:macro:: Z80_WITH_Q
|
||||
.. c:macro:: Z80_WITH_RESET_SIGNAL
|
||||
.. c:macro:: Z80_WITH_SPECIAL_RESET_SIGNAL
|
||||
.. c:macro:: Z80_WITH_UNOFFICIAL_RETI
|
||||
.. c:macro:: Z80_WITH_ZILOG_NMOS_LD_A_IR_BUG
|
||||
|
||||
Except for ``Z80_DEPENDENCIES_HEADER``, the above macros do not need to be set to a particular token when used, as the source code only checks whether or not they are defined.
|
||||
9
documentation/License.rst
Normal file
9
documentation/License.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
=======
|
||||
License
|
||||
=======
|
||||
|
||||
This emulator is `free software <https://www.gnu.org/philosophy/free-sw.html>`_: you can redistribute it and/or modify it under the terms of the `GNU Lesser General Public License <https://www.gnu.org/licenses/lgpl-3.0.en.html>`_ as published by the `Free Software Foundation <https://www.fsf.org>`_, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This emulator 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 this emulator. If not, see <https://www.gnu.org/licenses/>.
|
||||
20
documentation/Makefile
Normal file
20
documentation/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
2
documentation/TODO.txt
Normal file
2
documentation/TODO.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
ST CMOS Z80 no se comporta igual en los flags de las instrucciones de bloque?
|
||||
https://stardot.org.uk/forums/viewtopic.php?p=212100#p212100
|
||||
3
documentation/Testing.rst
Normal file
3
documentation/Testing.rst
Normal file
@@ -0,0 +1,3 @@
|
||||
=======
|
||||
Testing
|
||||
=======
|
||||
214
documentation/Thanks.rst
Normal file
214
documentation/Thanks.rst
Normal file
@@ -0,0 +1,214 @@
|
||||
======
|
||||
Thanks
|
||||
======
|
||||
|
||||
Many thanks to the following individuals (in alphabetical order):
|
||||
|
||||
Akimov, Vadim (lvd)
|
||||
For testing the library on many different platforms and CPU architectures.
|
||||
|
||||
azesmbog
|
||||
1. For validating tests on real hardware [1].
|
||||
2. For his research on the unstable flag behavior of the "ccf/scf" instructions.
|
||||
3. For his invaluable help.
|
||||
|
||||
Banks, David (hoglet)
|
||||
1. For cracking the flag behavior of the block instructions [2,3].
|
||||
2. For his research on the flag behavior of the "ccf/scf" instructions [3].
|
||||
|
||||
Beliansky, Anatoly (Tolik_Trek)
|
||||
For validating tests on real hardware [4].
|
||||
|
||||
Bobrowski, Jan
|
||||
For fixing the "Z80 Full Instruction Set Exerciser for Spectrum" [5].
|
||||
|
||||
boo_boo
|
||||
For cracking the behavior of the MEMPTR register [6,7,8,9].
|
||||
|
||||
Brady, Stuart
|
||||
For his research on the flag behavior of the "ccf/scf" instructions [10].
|
||||
|
||||
Brewer, Tony
|
||||
1. For his research on the special RESET [11].
|
||||
2. For sharing information about the RESET signal [12].
|
||||
3. For helping to crack the flag behavior of the block instructions [2].
|
||||
4. For performing low-level tests on real hardware [2].
|
||||
5. For helping me to test different undocumented behaviors of the Zilog Z80.
|
||||
|
||||
Bystrov, Dmitry (Alone Coder)
|
||||
For validating tests on real hardware [4].
|
||||
|
||||
Chunin, Roman (CHRV)
|
||||
For testing the behavior of the MEMPTR register on real Z80 chips [6,7,8,9].
|
||||
|
||||
Conway, Simon (BadBeard)
|
||||
For validating the "Z80 Test Suite" on several Z80 clones [13].
|
||||
|
||||
Cooke, Simon
|
||||
For finding out how the "out (c),0" instruction behaves on the Zilog Z80 CMOS [14].
|
||||
|
||||
Cringle, Frank D.
|
||||
For writing the "Z80 Instruction Set Exerciser" [15].
|
||||
|
||||
Devic, Goran
|
||||
For his research on undocumented behaviors of the Z80 CPU [16].
|
||||
|
||||
Flammenkamp, Achim
|
||||
For his article on Z80 interrupts [17].
|
||||
|
||||
Gimeno Fortea, Pedro
|
||||
1. For his research work [18].
|
||||
2. For writing the first-ever ZX Spectrum emulator [19,20].
|
||||
|
||||
goodboy
|
||||
For testing the behavior of the MEMPTR register on real Z80 chips [6,7,8,9].
|
||||
|
||||
Greenway, Ian
|
||||
For testing the flag behavior of the "ccf/scf" instructions on real hardware [10,21].
|
||||
|
||||
Harston, Jonathan Graham
|
||||
1. For his technical documents about the Zilog Z80 [22,23,24].
|
||||
2. For porting the "Z80 Instruction Set Exerciser" to the ZX Spectrum [25].
|
||||
|
||||
Helcmanovsky, Peter (Ped7g)
|
||||
1. For helping me to write the "IN-MEMPTR" test.
|
||||
2. For writing the "Z80 Block Flags Test" [26,27].
|
||||
3. For writing the "Z80 CCF SCF Outcome Stability" test [27].
|
||||
4. For writing the "Z80 INT Skip" test [27].
|
||||
5. For his research on the unstable flag behavior of the "ccf/scf" instructions.
|
||||
6. For his invaluable help.
|
||||
|
||||
icebear
|
||||
For testing the behavior of the MEMPTR register on real Z80 chips [6,7,8,9].
|
||||
|
||||
Kladov, Vladimir
|
||||
For cracking the behavior of the MEMPTR register [6,7,8,9].
|
||||
|
||||
Krook, Magnus
|
||||
For validating tests on real hardware [28].
|
||||
|
||||
London, Matthew
|
||||
For validating tests on real hardware.
|
||||
|
||||
Molodtsov, Aleksandr
|
||||
For testing the behavior of the MEMPTR register on real Z80 chips [6,7,8,9].
|
||||
|
||||
Nair, Arjun
|
||||
For validating tests on real hardware [26].
|
||||
|
||||
Nicolás-González, César
|
||||
For helping me to research the unstable flag behavior of the "ccf/scf" instructions.
|
||||
|
||||
Ortega Sosa, Sofía
|
||||
For her support.
|
||||
|
||||
Owen, Simon
|
||||
For the idea of the hooking method used in this emulator.
|
||||
|
||||
Rak, Patrik
|
||||
1. For improving the "Z80 Instruction Set Exerciser for Spectrum" [29].
|
||||
2. For cracking the flag behavior of the "ccf/scf" instructions [13,29].
|
||||
3. For writing the "Zilog Z80 CPU Test Suite" [29,30].
|
||||
4. For his research on the unstable flag behavior of the "ccf/scf" instructions.
|
||||
|
||||
Rodríguez Jódar, Miguel Ángel (mcleod_ideafix)
|
||||
For his reseach on the state of the registers after POWER/RESET [31].
|
||||
|
||||
Rodríguez Palomino, Mario (r-lyeh)
|
||||
For teaching me how emulators work.
|
||||
|
||||
Sainz de Baranda y Romero, Manuel
|
||||
For teaching me programming and giving me my first computer.
|
||||
|
||||
Sánchez Ordiñana, José Ismael (Vaporatorius)
|
||||
For validating tests on real hardware [32,33].
|
||||
|
||||
Stevenson, Dave
|
||||
1. For testing the special RESET on real hardware [11].
|
||||
2. For performing low-level tests on real hardware [34].
|
||||
|
||||
Weissflog, Andre (Floh)
|
||||
1. For finding out that the "reti/retn" instructions defer the acceptance of the maskable interrupt [35].
|
||||
2. For writing the "Visual Z80 Remix" simulator [36].
|
||||
|
||||
Wilkinson, Oli (evolutional)
|
||||
For validating tests on real hardware [26].
|
||||
|
||||
Wlodek
|
||||
For testing the behavior of the MEMPTR register on real Z80 chips [6,7,8,9].
|
||||
|
||||
Woodmass, Mark (Woody)
|
||||
1. For his invaluable contributions to the emuscene.
|
||||
2. For writing the "Z80 Test Suite" [13].
|
||||
3. For his research on the flag behavior of the "ccf/scf" instructions [37].
|
||||
4. For writing the "HALT2INT" test.
|
||||
5. For writing the "EIHALT" test.
|
||||
|
||||
Young, Sean
|
||||
1. For his research work.
|
||||
2. For his technical documents about the Zilog Z80 [18,38].
|
||||
|
||||
ZXGuesser
|
||||
For validating tests on real hardware.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
1. https://spectrumcomputing.co.uk/forums/viewtopic.php?p=83384#p83384
|
||||
2. https://stardot.org.uk/forums/viewtopic.php?t=15464
|
||||
* https://stardot.org.uk/forums/viewtopic.php?p=211042#p211042
|
||||
* https://stardot.org.uk/forums/viewtopic.php?p=212021#p212021
|
||||
3. Banks, David (2018-08-21). "Undocumented Z80 Flags".
|
||||
* https://github.com/hoglet67/Z80Decoder/wiki/Undocumented-Flags
|
||||
* https://stardot.org.uk/forums/download/file.php?id=39831
|
||||
4. https://spectrumcomputing.co.uk/forums/viewtopic.php?p=83041#p83041
|
||||
5. http://wizard.ae.krakow.pl/~jb/qaop/tests.html
|
||||
6. https://zxpress.ru/zxnet/zxnet.pc/5909
|
||||
7. https://zx-pk.ru/threads/2506-komanda-bit-n-(hl).html
|
||||
8. https://zx-pk.ru/threads/2586-prosba-realshchikam-ot-emulyatorshchikov.html
|
||||
9. boo_boo; Kladov, Vladimir (2006-03-29). "MEMPTR: esoteric register of the Zilog Z80 CPU".
|
||||
* http://zx.pk.ru/showpost.php?p=43688
|
||||
* http://zx.pk.ru/attachment.php?attachmentid=2984
|
||||
* http://zx.pk.ru/showpost.php?p=43800
|
||||
* http://zx.pk.ru/attachment.php?attachmentid=2989
|
||||
10. https://sourceforge.net/p/fuse-emulator/mailman/message/6929573
|
||||
11. Brewer, Tony (2014-12). "Z80 Special Reset".
|
||||
* http://primrosebank.net/computers/z80/z80_special_reset.htm
|
||||
12. https://mtxworld.dk/memorum/viewtopic.php?p=1352#p1352
|
||||
13. https://worldofspectrum.org/forums/discussion/20345
|
||||
14. https://groups.google.com/g/comp.os.cpm/c/HfSTFpaIkuU/m/KotvMWu3bZoJ
|
||||
15. Cringle, Frank D. (1998-01-28). "Yaze - Yet Another Z80 Emulator" v1.10.
|
||||
* ftp://ftp.ping.de/pub/misc/emulators/yaze-1.10.tar.gz
|
||||
16. https://baltazarstudios.com/zilog-z80-undocumented-behavior
|
||||
17. Flammenkamp, Achim. "Interrupt Behaviour of the Z80 CPU".
|
||||
* http://z80.info/interrup.htm
|
||||
18. Young, Sean (1998-10). "Z80 Undocumented Features (in Software Behaviour)".
|
||||
19. https://elmundodelspectrum.com/desenterrando-el-primer-emulador-de-spectrum
|
||||
20. https://elmundodelspectrum.com/con-vosotros-el-emulador-de-pedro-gimeno-1989
|
||||
21. https://sourceforge.net/p/fuse-emulator/mailman/message/4502844
|
||||
22. Harston, Jonathan Graham (1997-09-09). "Z80 Opcode Map".
|
||||
* https://mdfs.net/Docs/Comp/Z80/OpCodeMap
|
||||
23. Harston, Jonathan Graham (1997-12-18). "Z80 Microprocessor Undocumented Instructions".
|
||||
* https://mdfs.net/Docs/Comp/Z80/UnDocOps
|
||||
24. Harston, Jonathan Graham (1998-04-15). "Full Z80 Opcode List Including Undocumented Opcodes".
|
||||
* https://mdfs.net/Docs/Comp/Z80/OpList
|
||||
25. https://mdfs.net/Software/Z80/Exerciser/Spectrum
|
||||
26. https://spectrumcomputing.co.uk/forums/viewtopic.php?t=6102
|
||||
27. https://github.com/MrKWatkins/ZXSpectrumNextTests
|
||||
28. https://spectrumcomputing.co.uk/forums/viewtopic.php?p=83157#p83157
|
||||
29. https://worldofspectrum.org/forums/discussion/41704
|
||||
* http://zxds.raxoft.cz/taps/misc/zexall2.zip
|
||||
30. https://worldofspectrum.org/forums/discussion/41834
|
||||
* http://zxds.raxoft.cz/taps/misc/z80test-1.0.zip
|
||||
* https://github.com/raxoft/z80test
|
||||
31. https://worldofspectrum.org/forums/discussion/34574
|
||||
32. https://worldofspectrum.org/forums/discussion/comment/668760/#Comment_668760
|
||||
33. https://jisanchez.com/test-a-dos-placas-de-zx-spectrum
|
||||
34. https://stardot.org.uk/forums/viewtopic.php?p=212360#p212360
|
||||
35. https://floooh.github.io/2021/12/17/cycle-stepped-z80.html
|
||||
36. https://github.com/floooh/v6502r
|
||||
37. http://groups.google.co.uk/group/comp.sys.sinclair/msg/56dd1fd4ccb5fb3b
|
||||
38. Young, Sean (2005-09-18). "Undocumented Z80 Documented, The".
|
||||
* http://www.myquest.nl/z80undocumented
|
||||
* http://www.myquest.nl/z80undocumented/z80-documented-v0.91.pdf
|
||||
71
documentation/VersionHistory.rst
Normal file
71
documentation/VersionHistory.rst
Normal file
@@ -0,0 +1,71 @@
|
||||
===============
|
||||
Version History
|
||||
===============
|
||||
|
||||
v0.2 (2022-XX-XX)
|
||||
=================
|
||||
|
||||
This is an important update that addresses a number of issues and also includes new features. Please note that the changes introduced in this release break the binary compatibility with the previous version.
|
||||
|
||||
Changes:
|
||||
|
||||
1. Changed the license from GPL to LGPL (by popular request).
|
||||
2. Moved the public header from ``<emulation/CPU/Z80.h>`` to ``<Z80.h>``.
|
||||
3. Removed the Xcode project.
|
||||
4. Switched the build system from Premake to CMake.
|
||||
5. Switched to Zeta v0.1.
|
||||
6. Added pkg-config support.
|
||||
7. Added the ``.vimrc`` dotfile.
|
||||
8. Added the ``CITATION.cff`` file.
|
||||
9. Added the ``file_id.diz`` file.
|
||||
10. Added the ``THANKS`` file.
|
||||
11. Added detailed documentation.
|
||||
12. Added tests.
|
||||
13. Added public macros for checking the library version.
|
||||
14. Added public macros with bit masks for working with flags.
|
||||
15. Added public macros for accessing the 16-bit registers.
|
||||
16. Added the ``z80_execute`` function to run a simplified emulation without RESET and interrupts.
|
||||
17. Added the ``z80_refresh_address`` function to get the refresh address of the current M1 cycle.
|
||||
18. Added the ``z80_in_cycle`` and ``z80_out_cycle`` functions to get the clock cycle on which the I/O M-cycle occurs, relative to the start of the instruction.
|
||||
19. Fixed a bug in the ``sll`` instruction.
|
||||
20. Fixed a bug in the ``INX`` and ``OUTX`` macros affecting the S and N flags.
|
||||
21. Fixed a bug in the ``OUTX`` macro affecting the MSByte of the port number.
|
||||
22. Fixed the clock cycles of the ``dec XY`` and ``in (c)`` instructions.
|
||||
23. Fixed the ``read_16`` function so that the order in which the compiler evaluates expressions does not affect the order of the memory read operations.
|
||||
24. Fixed the order in which the memory write operations are performed when the SP register is involved. This affects the NMI response, the INT response in modes 1 and 2, and the following instructions: ``ex (sp),{hl|XY}``, ``push TT``, ``push XY``, ``call WORD``, ``call Z,WORD`` and ``rst N``.
|
||||
25. Fixed the handling of illegal instructions to avoid stack overflows in long sequences of ``DDh`` / ``FDh`` prefixes.
|
||||
26. Fixed several implicit conversions to avoid warnings about loss of sign and precision.
|
||||
27. Fixed some bitwise operations to avoid undefined behavior and arithmetic right shifts on signed integers.
|
||||
28. Fixed violations of the C standard in several identifiers.
|
||||
29. Renamed the 8-bit register lists: ``X/Y`` to ``J/K``; ``J/K`` and ``P/Q`` to ``O/P``.
|
||||
30. Replaced all P/V overflow computation functions with a single, faster macro.
|
||||
31. Replaced all register resolution functions with macros.
|
||||
32. Replaced all ``ld {J,K|O,P}`` instructions that have the same destination and source register with NOPs.
|
||||
33. Reimplemented the HALT state. The emulation should now be fully accurate. HALTskip is also supported.
|
||||
34. Added optional emulation of the normal and special RESET signals, along with the new ``z80_reset`` and ``z80_special_reset`` functions to emit them. The old ``z80_reset`` function is now called ``z80_instant_reset``.
|
||||
35. Added emulation of the NMI acknowledge M-cycle through the new ``Z80::nmia`` callback.
|
||||
36. Added emulation of the INT acknowledge M-cycle through the new ``Z80::inta`` callback, which replaces ``Z80::int_data``.
|
||||
37. Added optional full emulation of the interrupt mode 0, along with the new ``Z80::int_fetch`` callback to perform bus read operations on instruction data. If not enabled at compile-time, the old simplified emulation is built, which supports only the most typical instructions.
|
||||
38. Added accurate flag behavior in the following instructions: ``ldir``, ``lddr``, ``cpir``, ``cpdr``, ``inir``, ``indr``, ``otir`` and ``otdr``.
|
||||
39. Added emulation of the interrupt acceptance deferral that occurs during the ``reti`` and ``retn`` instructions.
|
||||
40. Added MEMPTR emulation. The ``bit N,(hl)`` instruction now produces a correct value of F.
|
||||
41. Added optional emulation of the Q "register". If enabled at compile-time, the ``ccf`` and ``scf`` instructions produce a correct value of F.
|
||||
42. Added emulation options that can be configured at runtime.
|
||||
43. Added emulation of the ``out (c),255`` instruction (Zilog Z80 CMOS).
|
||||
44. Added optional emulation of the bug affecting the ``ld a,{i|r}`` instructions (Zilog Z80 NMOS). If enabled at compile-time, the P/V flag is reset when an INT is accepted during the execution of these instructions.
|
||||
45. Added the ``Z80::fetch_opcode`` and ``Z80::fetch`` callbacks to perform opcode fetch operations and memory read operations on instruction data respectively.
|
||||
46. Added hooking functionality through the ``ld h,h`` instruction and the new ``Z80::hook`` callback.
|
||||
47. Added the ``Z80::nop`` callback to perform disregarded opcode fetch operations during internal NOP M-cycles.
|
||||
48. Added four callbacks to notify the execution of important instructions: ``Z80::ld_i_a``, ``Z80::ld_r_a``, ``Z80::reti`` and ``Z80::retn``.
|
||||
49. Removed ``Z80::state``. Replaced with individual members for the registers, the interrupt enable flip-flops and the interrupt mode.
|
||||
50. Removed the superfluous EI flag. The previous opcode is checked instead, which is faster and makes the ``Z80`` object smaller.
|
||||
51. Removed all module-related stuff.
|
||||
52. Optimizations in flag computation and condition evaluation.
|
||||
53. New source code comments and improvements to existing ones.
|
||||
54. Improved code aesthetics.
|
||||
55. Other improvements, optimizations and minor changes.
|
||||
|
||||
v0.1 (2018-11-10)
|
||||
=================
|
||||
|
||||
Initial public release.
|
||||
55
documentation/conf.py
Normal file
55
documentation/conf.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Z80'
|
||||
copyright = '1999-2022 Manuel Sainz de Baranda y Goñi'
|
||||
author = 'Manuel Sainz de Baranda y Goñi'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = ['breathe']
|
||||
|
||||
# Breathe Configuration.
|
||||
breathe_default_project = 'Z80'
|
||||
breathe_domain_by_extension = {"h": "c"}
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
#html_theme = 'haiku'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
27
documentation/index.rst
Normal file
27
documentation/index.rst
Normal file
@@ -0,0 +1,27 @@
|
||||
.. Z80 documentation master file, created by
|
||||
sphinx-quickstart on Wed Feb 24 06:49:20 2021.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Zilog Z80 CPU Emulator
|
||||
======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
EmulationAccuracy
|
||||
Installation
|
||||
Integration
|
||||
APIReference
|
||||
Testing
|
||||
Thanks
|
||||
VersionHistory
|
||||
License
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`search`
|
||||
|
||||
35
documentation/make.bat
Normal file
35
documentation/make.bat
Normal file
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
||||
5
file_id.diz
Normal file
5
file_id.diz
Normal file
@@ -0,0 +1,5 @@
|
||||
Z80 v0.2 - Fast, small and accurate emulator
|
||||
of the Zilog Z80. Version 0.2 implements all
|
||||
that is known to date about this CPU, passes
|
||||
all test suites and is carefully designed to
|
||||
fit most use cases.
|
||||
3591
sources/Z80.c
3591
sources/Z80.c
File diff suppressed because it is too large
Load Diff
32
sources/Z80.rc.in
Normal file
32
sources/Z80.rc.in
Normal file
@@ -0,0 +1,32 @@
|
||||
1 VERSIONINFO
|
||||
FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,0,0
|
||||
PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,0,0
|
||||
FILEFLAGSMASK 0x3FL
|
||||
#ifdef NDEBUG
|
||||
FILEFLAGS 0x0L
|
||||
#else
|
||||
FILEFLAGS 0x1L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Manuel Sainz de Baranda y Goñi"
|
||||
VALUE "FileDescription", "@PROJECT_DESCRIPTION@"
|
||||
VALUE "FileVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@"
|
||||
VALUE "InternalName", "@PROJECT_NAME@"
|
||||
VALUE "LegalCopyright", "Copyright © 1999-2022 Manuel Sainz de Baranda y Goñi"
|
||||
VALUE "OriginalFilename", "@PROJECT_NAME@.dll"
|
||||
VALUE "ProductName", "@PROJECT_NAME@"
|
||||
VALUE "ProductVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
812
sources/test-Z80.c
Normal file
812
sources/test-Z80.c
Normal file
@@ -0,0 +1,812 @@
|
||||
/* test-Z80
|
||||
______ ______ ______
|
||||
/\___ \/\ __ \\ __ \
|
||||
____ \/__/ /\_\ __ \\ \/\ \ ________________________________________________
|
||||
| /\_____\\_____\\_____\ |
|
||||
| Zilog \/_____//_____//_____/ CPU Emulator Test |
|
||||
| Copyright (C) 2021-2022 Manuel Sainz de Baranda y Goñi. |
|
||||
| |
|
||||
| This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. |
|
||||
| |
|
||||
'=============================================================================*/
|
||||
|
||||
#ifdef TEST_Z80_WITH_ARCHIVE_EXTRACTION
|
||||
# include <zip.h>
|
||||
# include <zlib.h>
|
||||
|
||||
/*-----------------------------------------.
|
||||
| Z_NULL is also defined by Zeta, so it is |
|
||||
| undefined to avoid conflicts with zlib. |
|
||||
'=========================================*/
|
||||
# ifdef Z_NULL
|
||||
# undef Z_NULL
|
||||
# endif
|
||||
|
||||
# include <Z/formats/archive/TAR.h>
|
||||
#endif
|
||||
|
||||
#include <Z/constants/pointer.h>
|
||||
#include <Z/macros/aggregate.h>
|
||||
#include <Z80.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* MARK: - Constants */
|
||||
|
||||
#define OPCODE_NOP 0x00
|
||||
#define OPCODE_RET 0xC9
|
||||
#define OPCODE_HALT 0x76
|
||||
#define OPCODE_CALL_WORD 0xCD
|
||||
#define OPCODE_JP_WORD 0xC3
|
||||
|
||||
|
||||
/* MARK: - Types */
|
||||
|
||||
typedef struct {
|
||||
/* Name of the archive if the test is compressed; Z_NULL otherwise. */
|
||||
char const* archive_name;
|
||||
|
||||
/* Name of the test program file, or the path to the file inside the
|
||||
* archive if the file is compressed. */
|
||||
char const* file_path;
|
||||
|
||||
/* Size of the program file. */
|
||||
zuint16 file_size;
|
||||
|
||||
/* Offset of the program code inside the file. */
|
||||
zuint16 code_offset;
|
||||
|
||||
/* Size of the program code. */
|
||||
zuint16 code_size;
|
||||
|
||||
/* Memory address where to jump to start executing the test code. */
|
||||
zuint16 start_address; /* */
|
||||
|
||||
/* Value of the PC register once the test ends. */
|
||||
zuint16 exit_address;
|
||||
|
||||
/* Format of the program file. */
|
||||
zuint8 format;
|
||||
|
||||
/* Total number of lines printed by the test when it passes. */
|
||||
zuint8 lines_expected;
|
||||
} Test;
|
||||
|
||||
/* CP/M program in COM format. */
|
||||
#define TEST_FORMAT_CPM 0
|
||||
|
||||
/* ZX Spectrum TAP image. Different versions of the Z80 Instruction Set
|
||||
* Exerciser adapted and improved by Jonathan Graham Harston and others. */
|
||||
#define TEST_FORMAT_HARSTON 1
|
||||
|
||||
/* ZX Spectrum TAP image. Tapes of the Zilog Z80 CPU Test Suite written by
|
||||
* Patrik Rak. */
|
||||
#define TEST_FORMAT_RAK 2
|
||||
|
||||
/* ZX Spectrum TAP image. Z80 Test Suite, written by Mark Woodmass. */
|
||||
#define TEST_FORMAT_WOODMASS 3
|
||||
|
||||
|
||||
/* MARK: - Global Variables */
|
||||
|
||||
static Test const tests[22] = {
|
||||
{"Yaze v1.14 (2004-04-23)(Cringle, Frank D.)(Sources)[!].tar.gz", "yaze-1.14/test/zexdoc.com", 8704, 0, 8704, 0x0100, 0, TEST_FORMAT_CPM, 68},
|
||||
{Z_NULL, "Z80 Documented Instruction Set Exerciser for Spectrum (2018)(Harston, Jonathan Graham)[!].tap", 8716, 91, 8624, 0x8000, 0x803D, TEST_FORMAT_HARSTON, 69},
|
||||
{"Yaze v1.14 (2004-04-23)(Cringle, Frank D.)(Sources)[!].tar.gz", "yaze-1.14/test/zexall.com", 8704, 0, 8704, 0x0100, 0, TEST_FORMAT_CPM, 68},
|
||||
{Z_NULL, "Z80 Full Instruction Set Exerciser for Spectrum (2009)(Bobrowski, Jan)[!].tap", 8656, 108, 8547, 0x8000, 0x803D, TEST_FORMAT_HARSTON, 69},
|
||||
{Z_NULL, "Z80 Full Instruction Set Exerciser for Spectrum (2011)(Bobrowski, Jan)(Narrowed to BIT Instructions)[!].tap", 8656, 108, 8547, 0x8000, 0x803D, TEST_FORMAT_HARSTON, 4},
|
||||
{Z_NULL, "Z80 Full Instruction Set Exerciser for Spectrum (2017-0x)(Harston, Jonathan Graham)[!].tap", 8704, 91, 8612, 0x8000, 0x803D, TEST_FORMAT_HARSTON, 69},
|
||||
{Z_NULL, "Z80 Full Instruction Set Exerciser for Spectrum (2018)(Harston, Jonathan Graham)[!].tap", 8716, 91, 8624, 0x8000, 0x803D, TEST_FORMAT_HARSTON, 69},
|
||||
{"Z80 Instruction Set Exerciser for Spectrum 2 v0.1 (2012-11-27)(Rak, Patrik)[!].zip", "zexall2-0.1/zexall2.tap", 9316, 87, 9228, 0x8000, 0x8040, TEST_FORMAT_HARSTON, 76},
|
||||
{"Zilog Z80 CPU Test Suite v1.0 (2012-12-08)(Rak, Patrik)[!].zip", "z80test-1.0/z80full.tap", 13758, 91, 13666, 0x8000, 0x7003, TEST_FORMAT_RAK, 156},
|
||||
{"Zilog Z80 CPU Test Suite v1.0 (2012-12-08)(Rak, Patrik)[!].zip", "z80test-1.0/z80doc.tap", 13758, 91, 13666, 0x8000, 0x7003, TEST_FORMAT_RAK, 156},
|
||||
{"Zilog Z80 CPU Test Suite v1.0 (2012-12-08)(Rak, Patrik)[!].zip", "z80test-1.0/z80flags.tap", 13758, 91, 13666, 0x8000, 0x7003, TEST_FORMAT_RAK, 156},
|
||||
{"Zilog Z80 CPU Test Suite v1.0 (2012-12-08)(Rak, Patrik)[!].zip", "z80test-1.0/z80docflags.tap", 13758, 91, 13666, 0x8000, 0x7003, TEST_FORMAT_RAK, 156},
|
||||
{"Zilog Z80 CPU Test Suite v1.0 (2012-12-08)(Rak, Patrik)[!].zip", "z80test-1.0/z80ccf.tap", 14219, 91, 14127, 0x8000, 0x7003, TEST_FORMAT_RAK, 156},
|
||||
{"Zilog Z80 CPU Test Suite v1.0 (2012-12-08)(Rak, Patrik)[!].zip", "z80test-1.0/z80memptr.tap", 13758, 91, 13666, 0x8000, 0x7003, TEST_FORMAT_RAK, 156},
|
||||
{"Zilog Z80 CPU Test Suite v1.2 (2022-01-26)(Rak, Patrik)[!].zip", "z80test-1.2/z80full.tap", 14390, 91, 14298, 0x8000, 0x7003, TEST_FORMAT_RAK, 164},
|
||||
{"Zilog Z80 CPU Test Suite v1.2 (2022-01-26)(Rak, Patrik)[!].zip", "z80test-1.2/z80doc.tap", 14390, 91, 14298, 0x8000, 0x7003, TEST_FORMAT_RAK, 164},
|
||||
{"Zilog Z80 CPU Test Suite v1.2 (2022-01-26)(Rak, Patrik)[!].zip", "z80test-1.2/z80flags.tap", 14390, 91, 14298, 0x8000, 0x7003, TEST_FORMAT_RAK, 164},
|
||||
{"Zilog Z80 CPU Test Suite v1.2 (2022-01-26)(Rak, Patrik)[!].zip", "z80test-1.2/z80docflags.tap", 14390, 91, 14298, 0x8000, 0x7003, TEST_FORMAT_RAK, 164},
|
||||
{"Zilog Z80 CPU Test Suite v1.2 (2022-01-26)(Rak, Patrik)[!].zip", "z80test-1.2/z80ccf.tap", 14875, 91, 14783, 0x8000, 0x7003, TEST_FORMAT_RAK, 164},
|
||||
{"Zilog Z80 CPU Test Suite v1.2 (2022-01-26)(Rak, Patrik)[!].zip", "z80test-1.2/z80memptr.tap", 14390, 91, 14298, 0x8000, 0x7003, TEST_FORMAT_RAK, 164},
|
||||
{Z_NULL, "Z80 Test Suite (2008)(Woodmass, Mark)[!].tap", 5573, 120, 5452, 0x8057, 0x80E6, TEST_FORMAT_WOODMASS, 50},
|
||||
{Z_NULL, "Z80 Test Suite (2008)(Woodmass, Mark)[!].tap", 5573, 120, 5452, 0x8049, 0x80E6, TEST_FORMAT_WOODMASS, 61}
|
||||
};
|
||||
|
||||
static char const *const cpu_model_identifiers[4] = {
|
||||
"zilog-nmos",
|
||||
"zilog-cmos",
|
||||
"nec-nmos",
|
||||
"st-cmos"
|
||||
};
|
||||
|
||||
static char const cpu_model_keys[4] = {
|
||||
Z80_MODEL_ZILOG_NMOS,
|
||||
Z80_MODEL_ZILOG_CMOS,
|
||||
Z80_MODEL_NEC_NMOS,
|
||||
Z80_MODEL_ST_CMOS
|
||||
};
|
||||
|
||||
/* Instance of the Z80 Emulator. */
|
||||
static Z80 cpu;
|
||||
|
||||
/* 64 KB of memory needed by the emulator. */
|
||||
static zuint8 memory[65536];
|
||||
|
||||
/* TRUE if the test is completed, or FALSE otherwise. */
|
||||
static zboolean test_completed;
|
||||
|
||||
static zboolean zx_spectrum_tab;
|
||||
|
||||
/* X position of the cursor inside ZX Spectrum screen paper
|
||||
* (in characters). */
|
||||
static zuint zx_spectrum_column;
|
||||
|
||||
/* Number of text lines printed by the current/latest test.
|
||||
* It is used to know whether the test passed or produced errors. */
|
||||
static zuint lines;
|
||||
|
||||
/* Address where to place a CPU trap to intercept the PRINT */
|
||||
static zuint16 print_hook_address;
|
||||
|
||||
/* */
|
||||
static zuint8 in_values[2];
|
||||
|
||||
static char* path_buffer = Z_NULL;
|
||||
static char** search_paths = Z_NULL;
|
||||
static zuint search_path_count = 0;
|
||||
|
||||
|
||||
/* MARK: - CPU Callbacks: Common */
|
||||
|
||||
|
||||
static zuint8 cpu_read(void *context, zuint16 address)
|
||||
{
|
||||
Z_UNUSED(context)
|
||||
return memory[address];
|
||||
}
|
||||
|
||||
|
||||
static zuint8 cpu_in(void *context, zuint16 port)
|
||||
{
|
||||
Z_UNUSED(context)
|
||||
return in_values[port & 1];
|
||||
}
|
||||
|
||||
|
||||
static void cpu_out(void *context, zuint16 port, zuint8 value)
|
||||
{Z_UNUSED(context) Z_UNUSED(port) Z_UNUSED(value)}
|
||||
|
||||
|
||||
static void cpu_halt(void *context, zboolean state)
|
||||
{
|
||||
Z_UNUSED(context) Z_UNUSED(state)
|
||||
cpu.cycles = Z80_CYCLE_LIMIT;
|
||||
test_completed = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* MARK: - CPU Callbacks: CP/M */
|
||||
|
||||
|
||||
static void cpm_cpu_write(void *context, zuint16 address, zuint8 value)
|
||||
{
|
||||
Z_UNUSED(context)
|
||||
memory[address] = value;
|
||||
}
|
||||
|
||||
|
||||
static zuint8 cpm_cpu_hook(void *context, zuint16 address)
|
||||
{
|
||||
Z_UNUSED(context)
|
||||
|
||||
if (address != 5) return OPCODE_NOP;
|
||||
|
||||
if (Z80_C(cpu) == 2) switch (Z80_E(cpu))
|
||||
{
|
||||
case 0x0D:
|
||||
break;
|
||||
|
||||
case 0x0A:
|
||||
putchar('\n');
|
||||
lines++;
|
||||
break;
|
||||
|
||||
default:
|
||||
putchar(Z80_E(cpu));
|
||||
}
|
||||
|
||||
else if (Z80_C(cpu) == 9)
|
||||
{
|
||||
zuint16 i = Z80_DE(cpu);
|
||||
zuint c = 0;
|
||||
|
||||
while (memory[i] != '$')
|
||||
{
|
||||
zuint8 character;
|
||||
|
||||
if (c++ > 100)
|
||||
{
|
||||
putchar('\n');
|
||||
fputs("Error: String to print is too long!\n", stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch ((character = memory[i++]))
|
||||
{
|
||||
case 0x0D:
|
||||
break;
|
||||
|
||||
case 0x0A:
|
||||
putchar('\n');
|
||||
lines++;
|
||||
break;
|
||||
|
||||
default:
|
||||
putchar(character);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OPCODE_RET;
|
||||
}
|
||||
|
||||
|
||||
/* MARK: - CPU Callbacks: ZX Spectrum */
|
||||
|
||||
|
||||
static void zx_spectrum_cpu_write(void *context, zuint16 address, zuint8 value)
|
||||
{
|
||||
Z_UNUSED(context)
|
||||
if (address > 0x3FFF) memory[address] = value;
|
||||
}
|
||||
|
||||
|
||||
static zuint8 zx_spectrum_cpu_hook(void *context, zuint16 address)
|
||||
{
|
||||
Z_UNUSED(context)
|
||||
|
||||
if (address != print_hook_address) return OPCODE_NOP;
|
||||
|
||||
if (zx_spectrum_tab)
|
||||
{
|
||||
zuint c = (Z80_A(cpu) % 32) - (zx_spectrum_column % 32);
|
||||
|
||||
while (c--) putchar(' ');
|
||||
zx_spectrum_tab = FALSE;
|
||||
}
|
||||
|
||||
else switch (Z80_A(cpu))
|
||||
{
|
||||
case 0x0D: /* CR */
|
||||
putchar('\n');
|
||||
lines++;
|
||||
zx_spectrum_column = 0;
|
||||
break;
|
||||
|
||||
case 0x7F: /* © */
|
||||
printf("©");
|
||||
zx_spectrum_column++;
|
||||
break;
|
||||
|
||||
case 0x17: /* TAB */
|
||||
zx_spectrum_tab = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (Z80_A(cpu) >= 32 && Z80_A(cpu) < 127)
|
||||
{
|
||||
putchar(Z80_A(cpu));
|
||||
zx_spectrum_column++;
|
||||
}
|
||||
}
|
||||
|
||||
return OPCODE_RET;
|
||||
}
|
||||
|
||||
|
||||
/* Only needed for Woody's Z80 Test Suite. */
|
||||
static zuint8 zx_spectrum_cpu_fetch_opcode(void *context, zuint16 address)
|
||||
{
|
||||
Z_UNUSED(context)
|
||||
|
||||
return (address == 0x0D6B /* 0D6B: THE 'CLS' COMMAND ROUTINE */ ||
|
||||
address == 0x1601 /* 1601: THE 'CHAN_OPEN' SUBROUTINE */
|
||||
)
|
||||
? OPCODE_RET : memory[address];
|
||||
}
|
||||
|
||||
|
||||
static char const *compose_path(char const *base_path, const char *file_path)
|
||||
{
|
||||
zusize base_path_size;
|
||||
|
||||
if (base_path == Z_NULL) return file_path;
|
||||
base_path_size = strlen(base_path);
|
||||
memcpy(path_buffer, base_path, base_path_size);
|
||||
path_buffer[base_path_size] = '/';
|
||||
strcpy(path_buffer + base_path_size + 1, file_path);
|
||||
return path_buffer;
|
||||
}
|
||||
|
||||
|
||||
static zboolean load_file(
|
||||
char const* path,
|
||||
char const* file_path,
|
||||
zuint32 file_size,
|
||||
zuint16 offset,
|
||||
zuint16 size,
|
||||
void* buffer
|
||||
)
|
||||
{
|
||||
zboolean status = FALSE;
|
||||
FILE *file = fopen(compose_path(path, file_path), "rb");
|
||||
|
||||
if (file != Z_NULL)
|
||||
{
|
||||
fseek(file, 0, SEEK_END);
|
||||
|
||||
if (ftell(file) == file_size)
|
||||
{
|
||||
fseek(file, offset, SEEK_SET);
|
||||
status = fread(buffer, size, 1, file) == 1;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static zboolean load_test(const char *path, Test const *test, void *buffer)
|
||||
{
|
||||
# ifdef TEST_Z80_WITH_ARCHIVE_EXTRACTION
|
||||
zboolean status = load_file(
|
||||
path, test->file_path, test->file_size,
|
||||
test->code_offset, test->code_size, buffer);
|
||||
|
||||
if (!status && test->archive_name != Z_NULL)
|
||||
{
|
||||
path = compose_path(path, test->archive_name);
|
||||
|
||||
/* .tar.gz */
|
||||
if (strrchr(test->archive_name, '.')[1] == 'g')
|
||||
{
|
||||
union {zuint8 data[Z_TAR_BLOCK_SIZE]; Z_TARHeader fields;} header;
|
||||
gzFile gz = gzopen(path, "rb");
|
||||
|
||||
if (gz != Z_NULL)
|
||||
{
|
||||
while (!gzeof(gz))
|
||||
{
|
||||
char *end;
|
||||
zulong file_size, block_tail_size;
|
||||
|
||||
if (gzread(gz, header.data, Z_TAR_BLOCK_SIZE) != Z_TAR_BLOCK_SIZE) break;
|
||||
file_size = strtoul((char *)header.fields.size, &end, 8);
|
||||
|
||||
if (!strcmp(test->file_path, (char *)header.fields.name))
|
||||
{
|
||||
status =
|
||||
file_size == test->file_size &&
|
||||
gzseek(gz, test->code_offset, SEEK_CUR) != -1 &&
|
||||
gzread(gz, buffer, test->code_size) == test->code_size;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (zuint8 *)end == header.fields.size || *end ||
|
||||
-1 == gzseek(gz, (block_tail_size = (file_size % Z_TAR_BLOCK_SIZE))
|
||||
? file_size + (Z_TAR_BLOCK_SIZE - block_tail_size)
|
||||
: file_size, SEEK_CUR)
|
||||
)
|
||||
break;
|
||||
}
|
||||
|
||||
gzclose(gz);
|
||||
}
|
||||
}
|
||||
|
||||
/* .zip */
|
||||
else {
|
||||
int error;
|
||||
zip_t *zip = zip_open(path, ZIP_RDONLY | ZIP_CHECKCONS, &error);
|
||||
|
||||
if (zip != Z_NULL)
|
||||
{
|
||||
zip_file_t *file;
|
||||
zip_stat_t stat;
|
||||
|
||||
if ( !zip_stat(zip, test->file_path, ZIP_FL_ENC_STRICT, &stat) &&
|
||||
(stat.valid & ZIP_STAT_SIZE) && stat.size == test->file_size &&
|
||||
(file = zip_fopen(zip, test->file_path, 0)) != Z_NULL
|
||||
)
|
||||
{
|
||||
if ( zip_fread(file, buffer, test->code_offset) == test->code_offset &&
|
||||
zip_fread(file, buffer, test->code_size) == test->code_size
|
||||
)
|
||||
status = TRUE;
|
||||
|
||||
zip_fclose(file);
|
||||
}
|
||||
|
||||
zip_close(zip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
# else
|
||||
return load_file(
|
||||
path, test->file_path, test->file_size,
|
||||
test->code_offset, test->code_size, buffer);
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
static zboolean run_test(zuint test_index)
|
||||
{
|
||||
Test const *test = &tests[test_index];
|
||||
zuint16 start_address = test->start_address;
|
||||
zuint i = 0;
|
||||
|
||||
if (test->archive_name == Z_NULL) printf(
|
||||
"[%02u] %s\n* Loading program...",
|
||||
test_index, test->file_path);
|
||||
|
||||
else printf(
|
||||
"[%02u] %s/%s\n* Loading program...",
|
||||
test_index, test->archive_name, test->file_path);
|
||||
|
||||
memset(memory, 0, 65536);
|
||||
|
||||
for (; i < search_path_count &&
|
||||
!load_test(search_paths[i], test, memory + (start_address & 0xFF00));
|
||||
i++
|
||||
);
|
||||
|
||||
if ( i == search_path_count &&
|
||||
!load_test(Z_NULL, test, memory + (start_address & 0xFF00))
|
||||
)
|
||||
{
|
||||
puts(" ERROR\nTest skipped.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
puts(" OK");
|
||||
z80_power(&cpu, TRUE);
|
||||
|
||||
if (test->format == TEST_FORMAT_CPM)
|
||||
{
|
||||
cpu.fetch_opcode = cpu_read;
|
||||
cpu.write = cpm_cpu_write;
|
||||
cpu.hook = cpm_cpu_hook;
|
||||
memory[0] = OPCODE_HALT;
|
||||
memory[5] = Z80_HOOK; /* PRINT */
|
||||
}
|
||||
|
||||
else {
|
||||
cpu.write = zx_spectrum_cpu_write;
|
||||
cpu.hook = zx_spectrum_cpu_hook;
|
||||
cpu.im = 1;
|
||||
cpu.i = 0x3F;
|
||||
|
||||
if (test->format == TEST_FORMAT_WOODMASS)
|
||||
{
|
||||
printf("* Loading firmware...");
|
||||
|
||||
for ( i = 0;
|
||||
i < search_path_count &&
|
||||
!load_file(search_paths[i], "ZX Spectrum.rom", 16384, 0, 16384, memory);
|
||||
i++
|
||||
);
|
||||
|
||||
if ( i == search_path_count &&
|
||||
!load_file(Z_NULL, "ZX Spectrum.rom", 16384, 0, 16384, memory)
|
||||
)
|
||||
{
|
||||
puts(" ERROR\nTest skipped.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
puts(" OK");
|
||||
Z80_SP(cpu) = 0x7FE8;
|
||||
Z80_AF(cpu) = 0x3222;
|
||||
|
||||
cpu.fetch_opcode = zx_spectrum_cpu_fetch_opcode;
|
||||
|
||||
/* 0010: THE 'PRINT A CHARACTER' RESTART */
|
||||
memory[0x0010] = OPCODE_JP_WORD; /* jp PRINT */
|
||||
memory[0x0011] = 0xF2;
|
||||
memory[0x0012] = 0x70;
|
||||
|
||||
/* 70F2: PRINT */
|
||||
memory[print_hook_address = 0x70F2] = Z80_HOOK;
|
||||
}
|
||||
|
||||
else {
|
||||
cpu.fetch_opcode = cpu_read;
|
||||
|
||||
/* 0010: THE 'PRINT A CHARACTER' RESTART */
|
||||
memory[print_hook_address = 0x0010] = Z80_HOOK;
|
||||
|
||||
/* 0D6B: THE 'CLS' COMMAND ROUTINE */
|
||||
memory[0x0D6B] = OPCODE_RET;
|
||||
|
||||
/* 1601: THE 'CHAN_OPEN' SUBROUTINE */
|
||||
memory[0x1601] = OPCODE_RET;
|
||||
|
||||
if (test->format == TEST_FORMAT_RAK)
|
||||
{
|
||||
/* 7000: START */
|
||||
memory[0x7000] = OPCODE_CALL_WORD;
|
||||
memory[0x7001] = (zuint8)start_address;
|
||||
memory[0x7002] = (zuint8)(start_address >> 8);
|
||||
/*memory[0x7003] = HALT;*/
|
||||
start_address = 0x7000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memory[test->exit_address] = OPCODE_HALT;
|
||||
Z80_PC(cpu) = start_address;
|
||||
lines = 0;
|
||||
zx_spectrum_column = 0;
|
||||
zx_spectrum_tab = FALSE;
|
||||
test_completed = FALSE;
|
||||
|
||||
puts("* Running program...\n");
|
||||
|
||||
do
|
||||
# ifdef TEST_Z80_WITH_EXECUTE
|
||||
z80_execute(&cpu, Z80_CYCLE_LIMIT);
|
||||
# else
|
||||
z80_run(&cpu, Z80_CYCLE_LIMIT);
|
||||
# endif
|
||||
while (!test_completed);
|
||||
|
||||
puts(test->format == TEST_FORMAT_RAK ? "" : "\n");
|
||||
return lines == test->lines_expected;
|
||||
}
|
||||
|
||||
|
||||
static zboolean is_option(
|
||||
char const* string,
|
||||
char const* short_option,
|
||||
char const* long_option
|
||||
)
|
||||
{
|
||||
return !strcmp(string, short_option) ||
|
||||
!strcmp(string, long_option);
|
||||
}
|
||||
|
||||
|
||||
static zboolean byte_value(char const* string, zuint8 maximum_value, zuint8 *byte)
|
||||
{
|
||||
char *end;
|
||||
zulong value = strtoul(string, &end, 0);
|
||||
|
||||
if (end == string || *end || value > maximum_value) return FALSE;
|
||||
if (byte != Z_NULL) *byte = (zuint8)value;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
zboolean all = FALSE;
|
||||
zuint32 tests_run = 0;
|
||||
zusize longest_search_path_size = 0;
|
||||
int ii, i = 0, status = 0;
|
||||
|
||||
cpu.options = Z80_MODEL_ZILOG_NMOS;
|
||||
in_values[0] = 191;
|
||||
in_values[1] = 255;
|
||||
|
||||
while (++i < argc && *argv[i] == '-')
|
||||
{
|
||||
if (is_option(argv[i], "-h", "--help"))
|
||||
{
|
||||
puts( "Usage: test-Z80 [options] (--all | <test>...)\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -a, --all Run all tests.\n"
|
||||
" -h, --help Show this help message.\n"
|
||||
" -e, --in-even <value> Set the 8-bit value to be read from even I/O ports.\n"
|
||||
" -o, --in-odd <value> Set the 8-bit value to be read from odd I/O ports.\n"
|
||||
" -m, --model <model> Specify the CPU model to emulate.\n"
|
||||
" -p, --path <path> Specify a directory where to look for test files.\n"
|
||||
" -v, --version Show version and copyright.\n"
|
||||
"\n"
|
||||
"CPU models:\n"
|
||||
" zilog-nmos Zilog NMOS (default)\n"
|
||||
" zilog-cmos Zilog CMOS\n"
|
||||
" nec-nmos NEC NMOS\n"
|
||||
" st-cmos SGS-Thomson CMOS\n"
|
||||
"\n"
|
||||
"Tests:\n"
|
||||
" Versions of the Z80 Documented Instruction Set Exerciser:\n"
|
||||
" 00 CP/M ~ Cringle, Frank D. (2004-04-23).\n"
|
||||
" 01 ZX Spectrum ~ Harston, Jonathan Graham (2018).\n"
|
||||
" Versions of the Z80 Full Instruction Set Exerciser:\n"
|
||||
" 02 CP/M ~ Cringle, Frank D. (2004-04-23).\n"
|
||||
" 03 ZX Spectrum ~ Bobrowski, Jan (2009).\n"
|
||||
" 04 ZX Spectrum ~ Bobrowski, Jan (2011). Narrowed to BIT instructions.\n"
|
||||
" 05 ZX Spectrum ~ Harston, Jonathan Graham (2017).\n"
|
||||
" 06 ZX Spectrum ~ Harston, Jonathan Graham (2018).\n"
|
||||
" 07 ZX Spectrum ~ Rak, Patrik (2012-11-27).\n"
|
||||
" Zilog Z80 CPU Test Suite v1.0 ~ ZX Spectrum ~ Rak, Patrik (2012-12-08):\n"
|
||||
" 08 Tests all flags and registers.\n"
|
||||
" 09 Tests all registers, but only officially documented flags.\n"
|
||||
" 10 Tests all flags, ignores registers.\n"
|
||||
" 11 Tests documented flags only, ignores registers.\n"
|
||||
" 12 Tests all flags after executing CCF after each instruction tested.\n"
|
||||
" 13 Tests all flags after executing BIT N,(HL) after each instruction tested.\n"
|
||||
" Zilog Z80 CPU Test Suite v1.2 ~ ZX Spectrum ~ Rak, Patrik (2022-01-26):\n"
|
||||
" 14 Tests all flags and registers.\n"
|
||||
" 15 Tests all registers, but only officially documented flags.\n"
|
||||
" 16 Tests all flags, ignores registers.\n"
|
||||
" 17 Tests documented flags only, ignores registers.\n"
|
||||
" 18 Tests all flags after executing CCF after each instruction tested.\n"
|
||||
" 19 Tests all flags after executing BIT N,(HL) after each instruction tested.\n"
|
||||
" Z80 Test Suite ~ ZX Spectrum ~ Woodmass, Mark (2008):\n"
|
||||
" 20 Tests flags.\n"
|
||||
" 21 Tests MEMPTR.\n"
|
||||
"\n"
|
||||
"Email bug reports and questions to <manuel@zxe.io>\n"
|
||||
"Open issues at <https://github.com/redcode/Z80>");
|
||||
|
||||
goto exit_without_error;
|
||||
}
|
||||
|
||||
else if (is_option(argv[i], "-v", "--version"))
|
||||
{
|
||||
puts( "test-Z80 v" Z80_LIBRARY_VERSION_STRING "\n"
|
||||
"Copyright (C) 2021-2022 Manuel Sainz de Baranda y Goñi.\n"
|
||||
"Released under the terms of the GNU General Public License v3.");
|
||||
|
||||
goto exit_without_error;
|
||||
}
|
||||
|
||||
else if (is_option(argv[i], "-e", "--in-even"))
|
||||
{
|
||||
if (++i == argc) goto incomplete_option;
|
||||
if (!byte_value(argv[i], 255, &in_values[0])) goto invalid_io_value;
|
||||
}
|
||||
|
||||
else if (is_option(argv[i], "-o", "--in-odd"))
|
||||
{
|
||||
if (++i == argc) goto incomplete_option;
|
||||
if (!byte_value(argv[i], 255, &in_values[1])) goto invalid_io_value;
|
||||
}
|
||||
|
||||
else if (is_option(argv[i], "-m", "--model"))
|
||||
{
|
||||
if (++i == argc) goto incomplete_option;
|
||||
for (ii = 0; ii < 4; ii++) if (!strcmp(argv[i], cpu_model_identifiers[ii])) break;
|
||||
|
||||
if (ii == 4)
|
||||
{
|
||||
fprintf(stderr, "Invalid CPU model: '%s'\n", argv[i]);
|
||||
goto bad_syntax;
|
||||
}
|
||||
|
||||
cpu.options = cpu_model_keys[ii];
|
||||
}
|
||||
|
||||
else if (is_option(argv[i], "-p", "--path"))
|
||||
{
|
||||
zusize s;
|
||||
char **p;
|
||||
|
||||
if (++i == argc || !(s = strlen(argv[i]))) goto incomplete_option;
|
||||
if (s > longest_search_path_size) longest_search_path_size = s;
|
||||
|
||||
if ((p = realloc(search_paths, (search_path_count + 1) * sizeof(char *))) == Z_NULL)
|
||||
{
|
||||
fputs("Error: Not enough memory available.", stderr);
|
||||
goto exit_with_error;
|
||||
}
|
||||
|
||||
search_paths = p;
|
||||
search_paths[search_path_count++] = argv[i];
|
||||
}
|
||||
|
||||
else if (is_option(argv[i], "-a", "--all"))
|
||||
all = TRUE;
|
||||
|
||||
else {
|
||||
fprintf(stderr, "Invalid option: '%s'\n", argv[i]);
|
||||
goto bad_syntax;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == argc && !all)
|
||||
{
|
||||
fputs("No test specified.\n", stderr);
|
||||
goto bad_syntax;
|
||||
}
|
||||
|
||||
if (search_path_count) path_buffer = malloc(longest_search_path_size + 110);
|
||||
|
||||
/* Configure stdout as unbuffered. */
|
||||
setvbuf(stdout, Z_NULL, _IONBF, 0);
|
||||
|
||||
/* Configure the Z80 emulator */
|
||||
cpu.context = Z_NULL;
|
||||
cpu.fetch =
|
||||
cpu.read =
|
||||
cpu.nop = cpu_read;
|
||||
cpu.in = cpu_in;
|
||||
cpu.out = cpu_out;
|
||||
cpu.halt = cpu_halt;
|
||||
cpu.nmia =
|
||||
cpu.inta =
|
||||
cpu.int_fetch = Z_NULL;
|
||||
cpu.reset = Z_NULL;
|
||||
cpu.ld_i_a =
|
||||
cpu.ld_r_a =
|
||||
cpu.reti =
|
||||
cpu.retn = Z_NULL;
|
||||
|
||||
/* Ensure that all specified test numbers are valid. */
|
||||
for (ii = i; i < argc; i++)
|
||||
{
|
||||
char const *string = argv[i];
|
||||
char *end;
|
||||
|
||||
if (strtoul(string, &end, 10) >= Z_ARRAY_SIZE(tests) || end == string || *end)
|
||||
{
|
||||
fprintf(stderr, "Invalid test number: '%s'\n", string);
|
||||
goto bad_syntax;
|
||||
}
|
||||
}
|
||||
|
||||
while (ii < argc)
|
||||
{
|
||||
tests_run |= Z_UINT32(1) << (i = atoi(argv[ii++]));
|
||||
if (!run_test(i)) status = -1;
|
||||
}
|
||||
|
||||
if (all) for (i = 0; i < Z_ARRAY_SIZE(tests); i++)
|
||||
if (!(tests_run & (Z_UINT32(1) << i)) && !run_test(i)) status = -1;
|
||||
|
||||
exit_without_error:
|
||||
free(search_paths);
|
||||
free(path_buffer);
|
||||
return status;
|
||||
|
||||
incomplete_option:
|
||||
fprintf(stderr, "Incomplete option: '%s'\n", argv[i - 1]);
|
||||
goto bad_syntax;
|
||||
|
||||
invalid_io_value:
|
||||
fprintf(stderr, "Invalid I/O value: '%s'\n", argv[i]);
|
||||
|
||||
bad_syntax:
|
||||
fputs("Type 'test-Z80 -h' for help.\n", stderr);
|
||||
|
||||
exit_with_error:
|
||||
free(search_paths);
|
||||
free(path_buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* test-Z80.c EOF */
|
||||
11
support/Z80.pc.in
Normal file
11
support/Z80.pc.in
Normal file
@@ -0,0 +1,11 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: @PROJECT_NAME@
|
||||
Description: @PROJECT_DESCRIPTION@.
|
||||
URL: https://zxe.io/software/@PROJECT_NAME@
|
||||
Version: @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -l@PROJECT_NAME@
|
||||
Cflags: -I${includedir}
|
||||
61
support/Z80Config.cmake.in
Normal file
61
support/Z80Config.cmake.in
Normal file
@@ -0,0 +1,61 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
|
||||
set(@PROJECT_NAME@_known_components Static Shared)
|
||||
set(@PROJECT_NAME@_component_Static NO)
|
||||
set(@PROJECT_NAME@_component_Shared NO)
|
||||
|
||||
foreach (@PROJECT_NAME@_component IN LISTS ${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS)
|
||||
if (@PROJECT_NAME@_component IN_LIST @PROJECT_NAME@_known_components)
|
||||
set(@PROJECT_NAME@_component_${@PROJECT_NAME@_component} YES)
|
||||
else()
|
||||
set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE
|
||||
"@PROJECT_NAME@ does not recognize component `${@PROJECT_NAME@_component}`.")
|
||||
set(${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if (@PROJECT_NAME@_component_Static AND @PROJECT_NAME@_component_Shared)
|
||||
set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE
|
||||
"@PROJECT_NAME@ `Static` and `Shared` components are mutually exclusive.")
|
||||
set(${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(@PROJECT_NAME@_Static_targets "${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@StaticTargets.cmake")
|
||||
set(@PROJECT_NAME@_Shared_targets "${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@SharedTargets.cmake")
|
||||
|
||||
macro(@PROJECT_NAME@_load_targets type)
|
||||
if (NOT EXISTS "${@PROJECT_NAME@_${type}_targets}")
|
||||
set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE
|
||||
"@PROJECT_NAME@ `${type}` libraries were requested but not found.")
|
||||
set(${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(Zeta)
|
||||
include("${@PROJECT_NAME@_${type}_targets}")
|
||||
endmacro()
|
||||
|
||||
if(@PROJECT_NAME@_component_Static)
|
||||
@PROJECT_NAME@_load_targets(Static)
|
||||
elseif(@PROJECT_NAME@_component_Shared)
|
||||
@PROJECT_NAME@_load_targets(Shared)
|
||||
elseif(DEFINED @PROJECT_NAME@_SHARED_LIBS AND @PROJECT_NAME@_SHARED_LIBS)
|
||||
@PROJECT_NAME@_load_targets(Shared)
|
||||
elseif(DEFINED @PROJECT_NAME@_SHARED_LIBS AND NOT @PROJECT_NAME@_SHARED_LIBS)
|
||||
@PROJECT_NAME@_load_targets(Static)
|
||||
elseif(BUILD_SHARED_LIBS)
|
||||
if(EXISTS "${@PROJECT_NAME@_Shared_targets}")
|
||||
@PROJECT_NAME@_load_targets(Shared)
|
||||
else()
|
||||
@PROJECT_NAME@_load_targets(Static)
|
||||
endif()
|
||||
else()
|
||||
if(EXISTS "${@PROJECT_NAME@_Static_targets}")
|
||||
@PROJECT_NAME@_load_targets(Static)
|
||||
else()
|
||||
@PROJECT_NAME@_load_targets(Shared)
|
||||
endif()
|
||||
endif()
|
||||
1
support/firmware.sha512sum
Normal file
1
support/firmware.sha512sum
Normal file
@@ -0,0 +1 @@
|
||||
D5394DC919B1820E1956CB227E8DFFDA7887CB3D3A78E802EA690EE6B47EDF35DB3B29EA72E5E824B32B36FB18D79C72688AB7469A3D383A39EA01BA49AFC261 ZX Spectrum.rom
|
||||
10
support/software.sha512sum
Normal file
10
support/software.sha512sum
Normal file
@@ -0,0 +1,10 @@
|
||||
2254439627B0A513C2E87266C5F57573C1607744FDD72C634329F8F79CAEAE2C4475DDD4C5945434DBF8F2B189BA0BEBA12ADA3C12A34FAE2DDD44E8DDAA528B POSIX/Yaze v1.14 (2004-04-23)(Cringle, Frank D.)(Sources)[!].tar.gz
|
||||
FD6DF9FF65ED2F6502DE8892601CF803FBBB1D91F3BE43CF314464AADCB6B05E635F1A83A25C72E309EABEADC69975055EFDA6085A9D95B4815C7512801AC00E ZX Spectrum/Z80 Documented Instruction Set Exerciser for Spectrum (2018)(Harston, Jonathan Graham)[!].tap
|
||||
C8BC407C874D305CA9BB2647A83D726ACB6969FE7525EEAB0BA2C3270FFF94B3D90CFA186F3059F468CF07F651FD8D4D9465C32989B33A5F4FEF1FABCC2DBA23 ZX Spectrum/Z80 Full Instruction Set Exerciser for Spectrum (2009)(Bobrowski, Jan)[!].tap
|
||||
E4CD187FA712418863A85BD9FF2C2CC11717C0CCE4510686E3BBF367F38DB0A987BADC7CBC6AD22E88859587747FA818CCB04858B163502A870F45847FF9FE69 ZX Spectrum/Z80 Full Instruction Set Exerciser for Spectrum (2011)(Bobrowski, Jan)(Narrowed to BIT Instructions)[!].tap
|
||||
CD9B552F3F56298FA7EC75B4B7A4A115CA326CBD3B9DED2BE01EC31534B572216E7A95B7AC5EF920E5E28343CE048F33DC163F47B5CE8BB8DED5232CF41F6D91 ZX Spectrum/Z80 Full Instruction Set Exerciser for Spectrum (2017-0x)(Harston, Jonathan Graham)[!].tap
|
||||
3B4D93D5BEE0F58E187350E5EA90A92EA7F4874F5A7AABA91A944D92DA63B8EBC0B4B9F4AED264863B256C761307EA4EF3D5FD4A2896469A117EF1C676E6F2A6 ZX Spectrum/Z80 Full Instruction Set Exerciser for Spectrum (2018)(Harston, Jonathan Graham)[!].tap
|
||||
3F8306CC7EDB49DEFC8C2D8A792D970C4681983D46A0B37982432531D5F56F8CDC1850C41038C3EA1C5AF2C4E98994BBD57C039496C783D9D9626F2D2C0B88B2 ZX Spectrum/Z80 Instruction Set Exerciser for Spectrum 2 v0.1 (2012-11-27)(Rak, Patrik)[!].zip
|
||||
668542FC9965199659F03044F16A9943223A190B8D1BD9CC4699F58B4FF99FA304B8B3281DBD8B179C9AE0B047DA82D741D187F619B5293241BC1185657F7687 ZX Spectrum/Z80 Test Suite (2008)(Woodmass, Mark)[!].tap
|
||||
28C1F2BB5E523E4F03A23A5BBB70136F01BC06E12C2EC2AF8074FBF4C31218C9E8235BEEACC8A892128204738EC4C0548ACC0C825D6EA30BD393B1AA28C734F6 ZX Spectrum/Zilog Z80 CPU Test Suite v1.0 (2012-12-08)(Rak, Patrik)[!].zip
|
||||
5DD2F8335C4543D5D920318A526024CD7442E0CC15E208622D466A0CF57579908652A5301FD286A9AC61BA73341E4D8ACA1583635FC9D4204693FCB2C7364386 ZX Spectrum/Zilog Z80 CPU Test Suite v1.2 (2022-01-26)(Rak, Patrik)[!].zip
|
||||
Reference in New Issue
Block a user