{"id":50614453,"url":"https://github.com/algodesigner/z80","last_synced_at":"2026-06-06T07:02:04.539Z","repository":{"id":119188431,"uuid":"403331771","full_name":"algodesigner/z80","owner":"algodesigner","description":"Z80 CPU Emulator (with built-in debugger)","archived":false,"fork":false,"pushed_at":"2025-01-09T20:32:25.000Z","size":165,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-09T21:32:29.743Z","etag":null,"topics":["cpu-emulator","emulator","z80","z80-emulator"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/algodesigner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-05T14:37:56.000Z","updated_at":"2025-01-09T20:32:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"29451877-9314-4e2b-b158-5ae43591fab4","html_url":"https://github.com/algodesigner/z80","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/algodesigner/z80","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algodesigner%2Fz80","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algodesigner%2Fz80/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algodesigner%2Fz80/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algodesigner%2Fz80/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/algodesigner","download_url":"https://codeload.github.com/algodesigner/z80/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algodesigner%2Fz80/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33972398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-06T02:00:07.033Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpu-emulator","emulator","z80","z80-emulator"],"created_at":"2026-06-06T07:02:03.639Z","updated_at":"2026-06-06T07:02:04.517Z","avatar_url":"https://github.com/algodesigner.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Z80 CPU Emulator\n\nA standalone Z80 CPU emulator with built-in debugger, forked from the [RunCPM Project](https://github.com/MockbaTheBorg/RunCPM) (implemented by [MockbaTheBorg](https://github.com/MockbaTheBorg)). This library provides a complete Z80 processor implementation that can be used independently or integrated into computer simulation projects.\n\n## Features\n\n- **Complete Z80 instruction set** - Implements all documented Z80 instructions\n- **Built-in debugger** - Interactive debugger with step-by-step execution, register inspection, and memory viewing\n- **Multiple CPU instances** - Support for creating multiple Z80 instances in the same process\n- **Clean API** - Simple C interface for easy integration\n- **Platform independent** - Written in standard C with minimal dependencies\n- **Intercept functionality** - Custom callback for instruction-level monitoring and control\n\n## Project Structure\n\n- `z80.h` - Public API and type definitions\n- `z80.c` - Z80 CPU implementation (4,600+ lines) - **modify this file to implement I/O**\n- `console.h` / `console.c` - Terminal I/O and debugger interface\n- `globals.h` - Global definitions and macros\n- `main.c` - Example usage\n- `Makefile` - Build configuration\n\n**Note:** This project is structured as a standalone emulator rather than a library. To customize I/O behavior, you need to modify the `cpu_out()` and `cpu_in()` functions in `z80.c` directly.\n\n## Quick Start\n\n### Building\n\n```bash\nmake all\n```\n\nThis will compile the example program `main` which demonstrates basic usage.\n\n### Running the Example\n\n```bash\n./main\n```\n\nThe example creates a Z80 CPU instance, enables debug mode, sets an intercept function, and runs the CPU until the program counter reaches address 5.\n\n## API Documentation\n\n### Core Functions\n\n#### `z80* z80_new(void)`\nCreates and initializes a new Z80 CPU instance. Returns a pointer to the CPU structure.\n\n#### `void z80_destroy(z80* cpu)`\nDestroys a Z80 CPU instance and frees associated resources.\n\n#### `void z80_run(z80* cpu)`\nStarts execution of the Z80 CPU. The CPU will run until its status changes (e.g., via an intercept function or debugger command).\n\n#### `void z80_set_intercept(z80* cpu, void* ctx, void (*intercept)(void* ctx))`\nSets an intercept function that is called before each instruction execution. The intercept function can examine or modify CPU state.\n\n### CPU State Structure\n\nThe `z80` structure contains all CPU registers and state:\n\n```c\ntypedef struct {\n    int32_t pcx;    /* external view of PC */\n    int32_t af;     /* AF register */\n    int32_t bc;     /* BC register */\n    int32_t de;     /* DE register */\n    int32_t hl;     /* HL register */\n    int32_t ix;     /* IX register */\n    int32_t iy;     /* IY register */\n    int32_t pc;     /* program counter */\n    int32_t sp;     /* SP register */\n    int32_t af1;    /* alternate AF register */\n    int32_t bc1;    /* alternate BC register */\n    int32_t de1;    /* alternate DE register */\n    int32_t hl1;    /* alternate HL register */\n    int32_t iff;    /* Interrupt Flip Flop */\n    int32_t ir;     /* Interrupt (upper) / Refresh (lower) register */\n    int32_t status; /* Status: 0=running, 1=end request, 2=back to CCP */\n    int32_t debug;  /* Debug mode flag */\n    // ... internal state\n} z80;\n```\n\n### Memory and I/O Interface\n\nThe Z80 emulator includes a 64KB RAM array as part of the CPU structure (`cpu-\u003eRAM[65536]`). Memory access is handled internally through macros:\n\n- `_RamRead(address)` - Read byte from memory\n- `_RamWrite(address, value)` - Write byte to memory\n- `_RamRead16(address)` - Read 16-bit word from memory\n- `_RamWrite16(address, value)` - Write 16-bit word to memory\n\nFor I/O operations, you need to implement these functions:\n\n```c\nvoid cpu_out(z80 *cpu, uint32_t port, uint32_t value);\nuint32_t cpu_in(z80 *cpu, uint32_t port);\n```\n\nThe default implementations in `z80.c` are stubs that return default values. You should replace them with your actual I/O implementation.\n\n## Usage Examples\n\n### Basic CPU Instantiation\n\n```c\n#include \"z80.h\"\n\nint main() {\n    z80* cpu = z80_new();\n    cpu-\u003edebug = 1;  // Enable debug mode\n    z80_run(cpu);\n    z80_destroy(cpu);\n    return 0;\n}\n```\n\n### Simple Example Without I/O Modification\n\n```c\n#include \u003cstdio.h\u003e\n#include \"z80.h\"\n\n/* Intercept function to stop execution at address 5 */\nstatic void intercept(void *ctx) {\n    z80 *cpu = ctx;\n    if (cpu-\u003epc == 5) {\n        printf(\"\\nReached address 5, stopping execution.\\n\");\n        cpu-\u003estatus = 1;\n    }\n}\n\nint main() {\n    z80 *cpu = z80_new();\n    cpu-\u003edebug = 1;  // Enable debug mode\n    z80_set_intercept(cpu, cpu, intercept);\n    z80_run(cpu);\n    z80_destroy(cpu);\n    return 0;\n}\n```\n\nCompile and run:\n```bash\ngcc -o example z80.c console.c example.c\nprintf \"c\\n\" | ./example  # Press 'c' to continue execution\n```\n\n### Using Intercept Functions\n\n```c\n#include \"z80.h\"\n\nstatic void my_intercept(void* ctx) {\n    z80* cpu = ctx;\n    if (cpu-\u003epc == 0x100) {\n        printf(\"Reached address 0x100\\n\");\n        cpu-\u003estatus = 1;  // Stop execution\n    }\n}\n\nint main() {\n    z80* cpu = z80_new();\n    z80_set_intercept(cpu, cpu, my_intercept);\n    z80_run(cpu);\n    z80_destroy(cpu);\n    return 0;\n}\n```\n\n### Implementing I/O\n\nTo implement I/O, you need to modify the `cpu_out()` and `cpu_in()` functions in `z80.c`:\n\n```c\n// In z80.c, replace the existing cpu_out function:\nvoid cpu_out(z80 *cpu, const uint32_t Port, const uint32_t Value) {\n    // Handle output to port\n    switch (Port) {\n        case 0x00:\n            // Write to console\n            putchar(Value \u0026 0xFF);\n            break;\n        // Add more port handlers as needed\n    }\n}\n\n// In z80.c, replace the existing cpu_in function:\nuint32_t cpu_in(z80 *cpu, const uint32_t Port) {\n    // Handle input from port\n    switch (Port) {\n        case 0x00:\n            // Read from keyboard\n            int ch = getchar();\n            return (ch == EOF) ? 0xFF : ch;\n        // Add more port handlers as needed\n    }\n    return 0xFF;  // Default value\n}\n```\n\n### Accessing Memory\n\nSince memory is internal to the CPU structure, you can access it directly:\n\n```c\n// Write a program to memory\nuint8_t program[] = {0x3E, 0x41, 0xD3, 0x00, 0x76};  // LD A,0x41; OUT (0),A; HALT\nfor (int i = 0; i \u003c sizeof(program); i++) {\n    cpu-\u003eRAM[i] = program[i];\n}\n\n// Read from memory\nuint8_t value = cpu-\u003eRAM[0x1000];\n\n// Write to memory\ncpu-\u003eRAM[0x2000] = 0x55;\n```\n\n## Debugger Usage\n\nWhen debug mode is enabled (`cpu-\u003edebug = 1`), the emulator enters an interactive debugger after each instruction. The debugger displays:\n\n```\nBC:0000 DE:0000 HL:0000 AF:0000 : [........]\nIX:0000 IY:0000 SP:0000 PC:0000 : NOP\nCommand|? : \n```\n\n### Available Commands\n\nPress `?` in the debugger to see all available commands:\n\n**Lowercase commands:**\n- `t` - Trace to the next instruction (single step)\n- `c` - Continue execution (exit debug mode)\n- `b` - Dump memory pointed to by BC register\n- `d` - Dump memory pointed to by DE register  \n- `h` - Dump memory pointed to by HL register\n- `p` - Dump the memory page PC points to (PC \u0026 0xFF00)\n- `s` - Dump the memory page SP points to (SP \u0026 0xFF00)\n- `x` - Dump the memory page IX points to (IX \u0026 0xFF00)\n- `y` - Dump the memory page IY points to (IY \u0026 0xFF00)\n- `l` - Disassemble 16 instructions from current PC\n- `q` - Quit simulation (set CPU status to 1)\n\n**Uppercase commands:**\n- `B` - Set breakpoint at specified address\n- `C` - Clear breakpoint\n- `D` - Dump memory at specified address\n- `L` - Disassemble at specified address\n- `T` - Step over a CALL instruction\n- `W` - Set a byte/word watch at specified address\n\n**Note:** Pressing Enter (no command) will single step to the next instruction.\n\n### Example Debug Session\n\n```\nBC:0000 DE:0000 HL:0000 AF:0000 : [........]\nIX:0000 IY:0000 SP:0000 PC:0000 : NOP\nCommand|? : l\n0000 : NOP\n0001 : NOP\n0002 : NOP\n0003 : NOP\n0004 : NOP\n0005 : NOP\n0006 : NOP\n0007 : NOP\n0008 : NOP\n0009 : NOP\n000A : NOP\n000B : NOP\n000C : NOP\n000D : NOP\n000E : NOP\n000F : NOP\n\nBC:0000 DE:0000 HL:0000 AF:0000 : [........]\nIX:0000 IY:0000 SP:0000 PC:0000 : NOP\nCommand|? : B\n Addr: 0100\nBreakpoint set to 0100\n\nBC:0000 DE:0000 HL:0000 AF:0000 : [........]\nIX:0000 IY:0000 SP:0000 PC:0000 : NOP\nCommand|? : c\n```\n\n## Integration Guide\n\n### Step 1: Include the Z80 Library\n\nCopy `z80.h`, `z80.c`, `console.h`, `console.c`, and `globals.h` to your project.\n\n### Step 2: Implement I/O Functions\n\nProvide implementations for `cpu_in()` and `cpu_out()` functions. Memory is already built into the CPU structure.\n\n### Step 3: Initialize and Run\n\n```c\nz80* cpu = z80_new();\n// Configure memory/I/O callbacks\n// Load program into memory\nz80_run(cpu);\nz80_destroy(cpu);\n```\n\n### Step 4: Handle Debugging (Optional)\n\nSet `cpu-\u003edebug = 1` to enable the built-in debugger for development.\n\n## Building for Different Platforms\n\n### Linux/macOS\n\n```bash\ngcc -o my_emulator z80.c console.c my_code.c\n```\n\n### Windows (MinGW)\n\n```bash\ngcc -o my_emulator.exe z80.c console.c my_code.c\n```\n\n### Custom Build Options\n\nThe Makefile can be extended with additional compiler flags:\n\n```makefile\nCFLAGS = -O2 -Wall -Wextra\n```\n\n## Testing\n\nThe project includes a basic test in `main.c` that demonstrates CPU instantiation and debug mode. For comprehensive testing:\n\n1. Create test programs in Z80 machine code\n2. Load them into memory via direct access to `cpu-\u003eRAM[]`\n3. Set the program counter and run\n4. Verify register states and memory contents\n\n## Limitations\n\n- **I/O stubs**: The default I/O implementations are empty stubs\n- **Fixed 64KB memory**: Memory is fixed at 64KB within the CPU structure\n- **Instruction timing**: Cycle-accurate timing is not implemented\n- **Interrupt handling**: Basic support exists but may need enhancement for specific use cases\n- **Platform-specific console**: The console code uses termios and may need adaptation for Windows\n\n## Contributing\n\nContributions are welcome! Please ensure:\n\n1. Code follows the existing style (spaces, not tabs)\n2. New features include appropriate documentation\n3. Changes don't break existing functionality\n\n## License\n\nMIT License\n\nCopyright (c) 2017 Mockba the Borg\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n## Acknowledgments\n\n- **MockbaTheBorg** for the original RunCPM implementation\n- **Zilog** for the Z80 microprocessor architecture\n- **Contributors** to the RunCPM project\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falgodesigner%2Fz80","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falgodesigner%2Fz80","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falgodesigner%2Fz80/lists"}