Someone has changed our timed character program. Right movement works, but left movement does not. Your job is to find out why, make a small repair, and show that it works.
Start by reproducing the symptom. A motionless character could mean several things: perhaps the program missed a key, perhaps it kept the old position, or perhaps it failed to draw a changed position. We need evidence to tell those explanations apart.
The investigation below introduces each debugger reading when it becomes useful. Follow the stages at your own pace; switching stages keeps your source edits and notes. Explanations and repairs stay folded away until you ask for them.
What works, and what fails?
Assemble this supplied program. Hold P, then O. Describe what happens in each direction before looking for a cause. Focus the screen to use your keyboard, or use the buttons below it.
Change only the instruction you believe is responsible. Assemble again, reproduce the original test, then test at the left edge. Record what would convince you the repair works.
Show a repair to compare with mine
In case 1, the left guard should be jr z,wait_frame. A non-zero position should reach DEC A; zero should return to waiting. Test both cases. A useful edge test is to assemble with position: defb 0, stop at left, and inspect the branch.
Case 2 moves in both directions, but something is left behind. Reproduce it, choose what to inspect, and distinguish the stored position from the picture at the old address.
Give me a hint
Stop at move. Follow the erase setup and inspect HL before the drawing call. What bytes will that pointer supply?
Show the case 2 diagnosis
The erase call points HL at patterns, so it draws the artwork again at the old address. Point that call at blank, then retest both directions. The position and keyboard were working.
Source · view and edit
Edit the source, then assemble.
Edits are saved in this browser. Keep a downloaded copy of work you want to keep.
Case 1 is in the editor. Revert restores this supplied faulty case; it does not repair it.
Reassemble for a fresh starting position, then choose Stop at left. This supplies O until the machine reaches the left decision, pauses before its first instruction, then releases O.
Assemble and run to enable the debugger.
Did the program recognise the key?
Reaching the left decision in response to O is evidence about input. We have not yet established whether the position or drawing is correct.
Relevant assembled source
Stop at a label to see its source.
Next instruction in the machine
- position in RAM
- —
- A
- —
- Z · zero flag
- —
- PC · next address
- —
Write a prediction, step, then compare.
Explain the step I just saw
More machine state and recent steps
- HL
- —
- DE
- —
- SP
- —
These are actual paused-machine readings. Source edits need reassembly. The screen may show its last rendered frame; registers and RAM let you inspect work before another frame is drawn.
What would count as a successful repair?
Keep a short record of four things:
- The symptom you reproduced, including something that still worked.
- The first instruction whose result disagreed with what the program needed to do.
- The smallest change you made, and why it addresses that disagreement.
- The ordinary movement and boundary tests you repeated afterwards.
For the left edge, change the initial position: defb 15 to position: defb 0, assemble again and stop at the left decision. Predict whether a decrement should happen. Restore your normal starting position afterwards.
A successful ordinary move does not establish that the edge is safe. Likewise, a correct position byte does not establish that the old picture was erased. Case 2 asks you to make that distinction with less guidance.
Working with this debugger
A breakpoint is an address where you ask execution to stop. The buttons supply a key and run to the named label from your assembled source; they do not change the position directly. If you have already moved, the current position may differ from the starting value. Assemble again for a fresh machine.
Step executes the paused machine, rather than replaying a scripted answer. Resume returns to normal running. The source excerpt comes from the last assembly; the next instruction is disassembled from actual machine memory. Different formatting or numeric addresses do not mean they are different instructions.
The main view starts with the position byte and A. Z appears when the zero test matters; PC appears when you need to establish where the branch went. More registers and recent steps are available in the folded machine-state panel. Your prediction is kept for comparison; there is no automatic marking of your answer.
A source edit does not change the running program until you assemble it. Revert restores the supplied faulty case 1, not a repaired answer. Loading case 2 replaces the editor contents only when you press its button.
If a breakpoint is not reached, or stepping seems to wait
Running to a label has a fixed execution budget. “Not reached” means that execution did not arrive there within that budget; it is not evidence that the requested instruction ran. Check the source and the route that should reach it. For example, disabling interrupts prevents the timed program from progressing past HALT.
The browser frame loop is suspended while debugging. Step advances the actual machine through the emulator’s bounded stepping operation. At HALT it may still be waiting afterwards. Interrupts can also carry execution into the ROM service. Run to a named decision again to return to the part you are investigating.
The screen may show the last rendered frame while you step. Registers and RAM let you inspect an operation before a fresh frame is drawn.
Take the method with you
Reproduce the fault. Choose an explanation you can test. Stop before the relevant work, predict a change, and compare it with what the machine did. Follow the evidence until you find the first disagreement, then repair and repeat the test.
The two exercise sources are debug-branch.asm and debug-trail.asm, deliberate faulty variants of lesson 7’s clocked-character.asm. They use the same Asm198x and Pasmo build commands, with the relevant filename substituted. They are investigation cases, not new game checkpoints.
This completes our introduction to instructions, memory, drawing, input, timing and investigation. Continue with Meteor Storm, beginning with a pixel crossing a byte boundary and building towards a complete timed game.
Sources
Zilog, Z80 CPU User Manual, UM008011-0816, “LD A, (nn)”, “OR r”, “JR cc, e” and their flag effects. The embedded debugger uses Emu198x’s stepping, register inspection, memory reads and disassembly operations.
Run it here
This unit's program, built for you.
- Program
- debug-branch.tap
- Machine
- ZX Spectrum 48K (PAL)