Z80 Assembly 50: Floating-Point to ASCII Conversion

The Challenge of Displaying Floats In Z80 assembly, a floating-point number is stored internally across multiple bytes (e.g., 4 or 5 bytes) in a specialized format (Part 30). The screen, however, only displays ASCII characters. Converting the binary float into a series of characters (“3”, “.”, “1”, “4”) is one of the most complex tasks in 8-bit programming. The Conversion Strategy The process is too complex for a single routine and is typically broken down into four major steps: ...

September 27, 2025

Z80 Assembly 49: Memory Diagnostics (Testing RAM Reliability)

The Need for RAM Testing Before running any critical code, especially on vintage or newly built Z80 hardware, you must verify that the Random Access Memory (RAM) is working correctly. Faulty RAM chips can lead to unpredictable crashes and data corruption. Goal: To ensure every memory cell can reliably store both a logic ‘0’ and a logic ‘1’. The Simplest Test: The Fill Test The fastest, simplest test is to fill the entire memory block with a single value (e.g., 00H or FFH) and then read it back to verify. However, this test is weak because a faulty address line might cause two memory locations to point to the same physical chip, and this test wouldn’t catch it. ...

September 27, 2025

Z80 Assembly 48: Interrupt Prioritization and the Daisy Chain

The Challenge of Multiple Devices In a complex Z80 system, you might have several devices that need to interrupt the CPU (e.g., a timer, a keyboard controller, and a disk controller). If two devices signal an interrupt at the exact same time, the CPU needs a clear way to decide which one to service first. This is called priority resolution. The Daisy Chain Protocol The Z80 uses a hardware architecture called a Daisy Chain to resolve interrupt priority. ...

September 27, 2025

Z80 Assembly 47: Debugging with the Stack (Crash Analysis)

The Value of the Stack in Debugging When a Z80 program crashes, the CPU registers often hold garbage data. The Stack, however, holds the historical sequence of return addresses created by every CALL instruction. Examining the stack is the primary method to determine how the program arrived at the crash point—the call chain. The Principle: You read the values on the stack, and these values are the addresses of the instructions immediately following the last few CALL commands. ...

September 27, 2025

Z80 Assembly 45: Software Sprite Scaling and Rotation

The Challenge of Geometric Transformations The Z80 has no native support for the complex trigonometric math needed for rotation, nor does it have floating-point math for precise scaling. All geometric transformations must be calculated using fixed-point math and look-up tables (LUTs). Sprite Scaling (Zooming) Scaling a sprite involves sampling the source image at mathematically calculated intervals and writing the result to the screen. The Principle: To double the size of a sprite (Scale Factor = 2), you read every $1^{st}$ pixel from the source and draw it twice on the screen, both horizontally and vertically. ...

September 27, 2025

Z80 Assembly 44: Sprite Multiplexing and Display Lists

The Limitation: Hardware Sprite Count Many systems with dedicated sprite hardware (like the MSX or certain arcade boards) have a severe limit on the number of sprites that can be displayed on a single horizontal scanline (e.g., 8 or 16 sprites). Exceeding this limit causes sprites to disappear or flicker. The Solution: Sprite Multiplexing Sprite Multiplexing is a software technique that dynamically reuses the hardware’s limited number of sprite slots multiple times per frame. The goal is to quickly change the sprite’s position and pattern as the display beam moves down the screen. ...

September 27, 2025

Z80 Assembly 43: Memory Banking (Switching ROM and RAM)

The Limitation: 64 KB Address Space The Z80 uses 16-bit address lines, meaning it can only directly address 64 kilobytes (65,536 bytes) of memory (from address 0000H to FFFFH). Since many systems (like the MSX or larger Spectrums) have $128$ KB or more of RAM/ROM, they must use Memory Banking to access it all. How Memory Banking Works Memory Banking is the technique of using an I/O port to physically switch which $16$ KB or $8$ KB block of memory is visible to the CPU at a specific address range. ...

September 27, 2025

Z80 Assembly 42: Interfacing with a Real-Time Clock (RTC) Chip

The Need for a Real-Time Clock The Z80’s internal clock is only useful for instruction timing. It cannot track actual time (hours, minutes, days). A Real-Time Clock (RTC) is a separate, dedicated chip (like the DS1307 or MC146818) that contains its own crystal oscillator and often a small battery to maintain time even when the main computer is powered off. Communication: Indexed I/O The Z80 communicates with an RTC chip using a method called indexed I/O (similar to how the AY sound chip works). The RTC has a set of internal registers (e.g., 0-12) that store the seconds, minutes, hours, day, date, and control flags. ...

September 27, 2025

Z80 Assembly 41: Interrupt-Driven Serial Input (The Receiver)

The Challenge of Reliable Input In receiving serial data, the Z80 must wait for the exact moment the Start Bit arrives and then sample the input line precisely at the center of each of the next eight data bits. If the CPU misses the timing, the data is corrupted. The Solution: Interrupt-Driven Sampling The CPU cannot wait in a tight timing loop for data to arrive. Instead, we use a timer interrupt to tell the CPU exactly when to check the input line. ...

September 27, 2025

Z80 Assembly 40: Software Serial I/O (Bit-Banging Communication)

The Need for Bit-Banging The Z80 CPU does not have a built-in UART (Universal Asynchronous Receiver/Transmitter) for serial communication. To send data to a modem or another computer, we must bit-bang the signal: we use software and timing loops to manually control the state of an I/O pin. Key Components: I/O Port: A dedicated hardware output port (often the same as the beeper port) where one bit is wired to the serial output pin. Timing Loops: Precise timing loops (using T-states) to control the Baud Rate (bits per second). The Serial Data Format Serial communication sends one byte at a time, surrounded by fixed timing signals: ...

September 27, 2025