Seyed Masoud Hosseini · Overview · Study log · Ideas · Transcript · RSS feed

Embedded Systems, 6502 breadboard computer · Lecture 24 of 29 · 16:41

Lecture 24: Adapting WozMon for the Breadboard 6502

Adapting WozMon for the breadboard 6502 on YouTube

Study guide

What this lecture covers

Following a companion video that walked through the original Wozmon source line by line, this lecture details the specific edits needed to make Wozmon work on the breadboard 6502 computer's 6551 UART serial interface instead of the Apple 1's keyboard and display. It continues the series' work on the serial interface and the previous video's demonstration of the ported monitor in use.

The core constraint driving every decision is size: Wozmon must still fit inside exactly 256 bytes of ROM, so each added instruction has to be paid for by removing or shrinking something else.

Key ideas

  • Hardware differences drive the port: the Apple 1's memory-mapped keyboard/display registers at $D010-$D013 are replaced with the 6551 UART's registers at $5000-$5003.
  • ASCII bit-7 convention: the Apple 1 keyboard sets the top bit of every character code; the serial terminal does not, so every hard-coded character constant in Wozmon (backspace, escape, colon, dot, and others) has to be changed to its plain-ASCII value rather than patching each read.
  • Byte budget: Wozniak's original code left exactly two bytes unused in the 256-byte block; each change is tracked in bytes gained or lost against that budget, and the final result comes out only two bytes longer, fitting exactly.
  • Reusing a value with the right property: instead of adding an instruction to load a specific register value after reset, the lecture picks a register configuration value that happens to have the needed high bit set, killing two birds with one register write.
  • Mode-flag bit positions matter more than exact values: Wozmon distinguishes store/examine/block-examine modes using two specific bits of a "mode" variable, so any character value works as long as shifting it left lands the right bits in the right place.
  • Preserving external assumptions: the lecture keeps the output routine's address fixed at $FFEF so an existing Apple 1 test program that calls that address directly still works unmodified.

Walkthrough

Hardware differences (0:00)

The lecture identifies the 6551 UART's four registers as the replacement for the Apple 1's keyboard/display hardware and sets the goal of updating input and output routines while keeping the program at 256 bytes.

Serial input routine (0:21)

The character-wait loop is changed from checking a keyboard-ready bit to checking the UART status register's receive-data-full bit (bit 3), requiring an AND $08 before the branch — a two-byte cost against the budget.

Character code mapping (1:11)

Because the serial interface delivers plain ASCII rather than ASCII with bit 7 set, every hard-coded character comparison in Wozmon (backspace, escape, backslash, carriage return, dot, colon, "R", space) is rewritten to its bit-7-clear value, avoiding the extra cost of setting the bit on every character read.

Hex parsing modifications (4:00)

The routine that converts typed hex digits to values, and the reverse routine that converts bytes back to hex characters for display, both have their masking constant changed from $B0 to $30 to match plain ASCII, with the digit/letter threshold comparison updated accordingly.

Serial output routine (7:03)

The output ("echo") routine is rewritten to write a character to the UART's data register, then wait using a fixed delay loop instead of polling the (unreliable, per the earlier hardware-bug video) transmit-empty status bit, at a further two-byte cost.

Serial initialization (8:43)

The Apple 1's keyboard/display setup code is replaced with initialization of the UART's control register (19,200 baud, 8 data bits, 1 stop bit) and command register (no parity, no echo, no interrupts) — code that turns out three bytes shorter than the original it replaces.

Fixing dependencies on the reset code (9:43)

The lecture discovers that later code relies on the Y register holding a specific leftover value ($7F) after reset to correctly fall into the escape/initialize path. Rather than spend bytes loading Y explicitly, it changes the command register value to $8B (still valid per the datasheet, since parity is disabled regardless of those bits) and loads it via the Y register, reusing the initialization write to also set up this fall-through behavior.

Mode variable adjustments (12:48)

Because the store/examine/block-examine mode flags are derived by shifting the colon or dot character code left, and the new plain-ASCII values shift differently, the lecture adds one extra shift-left instruction for the "dot" case so the correct two bits land in the mode byte, bringing the total code size to exactly two bytes over the original — precisely the two bytes Wozniak left unused.

Testing and conclusion (15:38)

With the output routine kept at address $FFEF, the Apple 1 manual's sample test program (which calls that fixed address) still runs correctly on the modified monitor, confirming the port preserves compatibility with existing example code.

Before you watch

  • The companion video walking through the original Wozmon source code line by line.
  • The earlier videos on the 6551 UART registers and its transmit-status hardware bug.
  • Comfort reading 6502 assembly and ASCII/hex character tables.

Check your understanding

  1. Why did changing every hard-coded character constant cost fewer bytes than or-ing bit 7 onto each character read?
  2. How did reusing the command register's value to also set up the Y register save code space?
  3. Why does the exact character value used for a mode flag matter less than which specific bits it sets?
  4. What constraint forced the output routine to stay at address $FFEF?

Chapters

From the YouTube description

Support these videos on Patreon: https://www.patreon.com/beneater or https://eater.net/support for other ways to support.

------------------

Social media:
Website: https://www.eater.net
Twitter: https://x.com/beneater
Patreon: https://patreon.com/beneater
Reddit: https://www.reddit.com/r/beneater

Special thanks to these supporters for making this video possible:
Adrien Friggeri, Aleksey Smolenchuk, An Dương, Anthony Weems, anula, Ben, Ben Cochran, Ben Williams, Bill Cooksey, Bill Watkins, Binh Tran, Богдан Федоров, Bradley Stach, Brian Haug, Burt Humburg, Carl Fooks, Carsten Schwender, Chai, Chaitanya Bhatt, Chris Anders, Chris Lajoie, Chris Sachs, criis, Cristi Cobzarenco, Daniel Pink, Daniel Tang, Daniel Zimmer, Dave Walter, David Clark, David Cox, David Dawkins, David House, David Klassen, David Sastre Medina, David Turner, Dean Bevan, Dean Winger, Deep Kalra, Dennis Henderson, Dennis Schubert, Dilip Gowda, Dirk Sperling, Dmitry Guyvoronsky, Dustin Campbell, Dzevad Trumic, Emilio Mendoza, Eric Dynowski, Erik Broeders, Erik Granlund, Ethan Sifferman, Eugene Bulkin, Evan Serrano, Evan Thayer, Eveli László, EvinSaysMarxWasRight!, Florian Bürgi, fxshlein, George Miroshnykov, ghostdunk, Gregory Burns, GusGold, Hailey, Hovis Biddle, Ingo Eble, Jacob Ford, James Beldock, James Capuder, Jared Dziedzic, Jason Bowen, Jason DeStefano, Jason Grim, Jason Thorpe, JavaXP, Jaxon Ketterman, jemmons, Jeremy Cole, Jesse Miller, Jim Kelly, Jim Knowler, Joe Beda, Joe Pregracke, Joe Rork, Joel, Joey Murphy, John Hamberger jn., John Henning, John Meade, Jon Dugan, Jonn Miller, Joseph Portaro, Josh Smith, Justin Graziani, Kai Wells, Kefen, Ken Paul, Kennard Smith, Kenneth Christensen, Kyle Kellogg, Lambda GPU Workstations, László Bácsi, Lithou, Lukasz Pacholik, Marcos Fujisawa, Marcus Classon, Mariano Uvalle, Mark Day, Martin Noble, Mats Fredriksson, Matthew Clifford, melvin2001, Michael, Michael Cartwright, MICHAEL SLASS, Michael Tedder, Michael Timbrook, Michael Weitman, Miguel Ríos, mikebad, Miles Macchiaroli, Muqeet Mujahid, Nate Welch, Nicholas Counts, Nicholas Moresco, Nick Chapman, Olivier HUBER, Örn Arnarson, Paul Heller, Paul Pluzhnikov, Phil Dennis, Philip Hofstetter, ProgrammerDor, Ralph Irons, Randal Masutani, Randy True, raoulvp, real_huitz, ReJ aka Renaldas Zioma, Ric King, Richard Wagoner, Rick Hennigan, Rob Bruno, Robert Brown, Robert Diaz, Robert Keown, Robey Pointer, Roland Munsil, Sagnik Bhattacharya, Sam Sturgis, Scott Gorlick, Scott Holmes, Sean Bright, Sean Patrick O’Brien, Sergey Kruk, Shane Mulcahy, SonOfSofaman, sorek.uk, Spencer Ruport, Stefan Nesinger, Stephen Kovalcik, Stephen Riley, Steve Jones, TheWebMachine, Thomas Eriksen, Tim Oriol, Tim Sanders, Tim Walkowski, Tom, Tom Smith, Tyler Latham, Usseod, Vincent Bernat, Warren Miller, Wim Coekaerts, Wraithan McCarroll, Yee Lam Wan

← Lecture 23: Running Apple 1 Software (Wozmon) · Lecture 25: A Simple BIOS for My Breadboard Computer →