Diagnostics

In addition to the command line arguments shown on the Usage page, MEMU has arguments which are of interest when debugging Z80 programs and when debugging MEMU itself :-

Option Description
-diag-console Log diagnostic information to the console. Cannot be used with -mon-th as this would cause the diagnostic information to interfere with the text mode screen output.
-diag-file Append diagnostic information to a file called memu.log.
-diag-file=filename As above, but to file of your choice.
-diag-ring Log diagnostic information to a ring buffer in memory. When MEMU terminates, dump this to memu.ring. A great way to avoid filling the disk with memu.log when all you care about is recent activity prior to failure.
-diag-ring=filename As above, but to file of your choice.
-diag-win-unknown-key Displays host operating system specific keycodes typed in the windows which are not recognised by MEMUs window handling code. These will be XWindows KeySym values or Windows virtual keycodes. Recognised values are passed on to the emulation of the MTX keyboard.
-diag-win Turn on all diagnostic options with names starting with -diag-win
-diag-mem-iobyte Show when the IOBYTE is written to.
-diag-mem-subpage Show when the ROM subpage register is written to.
-diag-mem-dump When the program terminates, write the Z80 address space to a file called memu.mem.
-diag-mem Turn on all diagnostic options with names starting with -diag-mem.
-diag-vid-status Show when the VDP status register is read.
-diag-vid-registers Show when VDP registers are written to.
-diag-vid-address Show when the VDP address register is set, and whether for read or write.
-diag-vid-data Show all data transferred to/from the VDP memory. Tries to log the data in formats allowing you to recognise which graphics data is being uploaded. Will cause a lot of logging.
-diag-vid-refresh Show when the VDP screen is repainted to the Window on the host screen. This is the point at which the VDP interrupt bit becomes set.
-diag-vid-markers Show additional markers on the Window. One is a line which moves down the screen, one pixel per frame, which can be observed to see if time is progressing smoothly in the emulation. Another shows on which scan lines there are >=5 sprites.
-diag-vid-time-check Perform VDP timing sanity checks. Information about the timing parameters is given below.
-diag-vid-time-check-abort Terminate if timing check fails.
-diag-vid-time-check-drop Fail to store the data in VRAM, or return 0xff, if timing check fails.
-diag-vid Turn on all diagnostic options with names starting with -diag-vid.
-diag-kbd-win-key Show recognised key presses and releases in the VDP window which are not understood.
-diag-kbd-drive Show keyboard drive values returned.
-diag-kbd-sense Show keyboard drive and sense values returned.
-diag-kbd-auto-type Show the workings of the auto-type mechanism.
-diag-kbd-remap Show diagnostics relating to the keyboard remapping feature.
-diag-kbd Turn on all diagnostic options with names starting with -diag-kbd.
-diag-joy-init Show joystick initialisation messages.
-diag-joy-usage Show joystick messages generated as joystick data is read.
-diag-joy Turn on all diagnostics options with names starting with -diag-joy.
-diag-dart-ports Show accesses to DART ports.
-diag-dart-config Show DART configuration.
-diag-dart-data Show DART data transfer.
-diag-dart Turn on all diagnostics options with names starting with -diag-dart.
-diag-snd-registers Show accesses to the sound chip registers.
-diag-snd-latency Show information relating to the latency parameters passed to PortAudio.
-diag-snd-init Don't suppress stderr during Pa_Initialize() call.
-diag-snd Turn on all diagnostic options with names starting with -diag-snd.
-diag-ctc-registers Show when CTC registers are written to.
-diag-ctc-pending Show when an interrupt becomes pending on a channel.
-diag-ctc-interrupt Show when the fact the interrupt is pending is communicated to the Z80 chip (usually within 1000 clks).
-diag-ctc Turn on all diagnostic options with names starting with -diag-ctc.
-diag-mon-hw Show diagnostics relating to the hardware level emulation of the 6845 CRTC card and underlying memory.
-diag-mon-kbd-win-key Show recognised key presses and releases sent to 80-column window. Only applies if -mon-win is being used.
-diag-mon-kbd-map-th Show keycodes read from TH. Only applies if -mon-th is being used.
-diag-mon Turn on all diagnostic options with names starting with -diag-mon.
-diag-sdxfdc-port Turn on all diagnostic relating to SDX FDC port access.
-diag-sdxfdc-hw Turn on all diagnostic relating to SDX FDC hardware.
-diag-sdxfdc-data Turn on all diagnostic relating to SDX FDC data.
-diag-sdxfdc-status Turn on all diagnostic relating to SDX FDC status.
-diag-sdxfdc Turn on all diagnostic options with names starting with -diag-sdxfdc.
-diag-sidisc-file Turn on all diagnostic relating to Silicon Disc file reading and writing.
-diag-sidisc-address Turn on all diagnostic relating to Silicon Disc sector address control.
-diag-sidisc-data Turn on all diagnostic relating to Silicon Disc data transfer.
-diag-sidisc Turn on all diagnostic options with names starting with -diag-sidisc.
-diag-print Show characters that are printed.
-diag-spec-ports Log accesses to Speculator ports.
-diag-spec-interrupts Log things relating to Speculator interrupts.
-diag-spec Turn on all diagnostic options with names starting with -diag-spec.
-diag-cpm-driver Log all calls to driver code in high memory.
-diag-cpm-cbios Log all calls to CBIOS routines.
-diag-cpm-bdos-file Log all calls to CP/M BDOS relating to file access.
-diag-cpm-bdos-other Log other calls to CP/M BDOS.
-diag-cpm-bdos Turn on all diagnostic options with names starting with -diag-cpm-bdos.
-diag-cpm Turn on all diagnostic options with names starting with -diag-cpm.
-diag-z80-instructions Log CPU registers and disassemble instruction prior to executing each instruction. Will cause a lot of logging.
-diag-z80-instructions-exclude from-to Turn off logging CPU registers and disassemble instructions for instructions at addresses between from and to (eg: 0x0000-0x3fff).
-diag-z80-instructions-include from-to Turn on logging CPU registers and disassemble instructions for instructions at addresses between from and to.
-diag-z80-interrupts Log when the Z80 takes an interrupt, and show the peripheral supplied low byte of the vector table address.
-diag-z80-time Include timing information in the Z80 instructions logged.
-diag-z80 Turn on all diagnostic options with names starting with -diag-z80 (except -diag-z80-instructions-exclude).
-diag-bad-port-display Display when unemulated ports are accessed.
-diag-bad-port-ignore Do not halt MEMU when certain unemulated ports are accessed. By default, termination happens for ports which are known to be used by particular hardware.
-diag-bad-port Turn on all diagnostic options with names starting with -diag-bad-port.
-diag-panel-hack Diagnostics relating to the hack which allows PANEL and VDEB.COM single-stepping to work.
-diag-tape Diagnostics relating to the MTX BASIC LOAD/SAVE/VERIFY commands. It also shows diagnostics relating to the Z ZX Spectrum LOAD/SAVE/VERIFY commands.
-diag-speed Every second, output an estimate of the emulated chip speed. If running with -fast this could be much higher than 4MHz. If running with -mon-console and the program waits for keyboard input, because the simulation is suspended this could to drop to near zero.
-diag-exit Display the reason for the termination of MEMU.
-diag-all Turn on all of the above (except -diag-console and -diag-file).

By default the VDP timing checks assume the Z80 is running at 4MHz, the video is refreshing at 50Hz and a PAL video format. The 80000T between frames is therefore comprised of 120 vertical blank and 192 active scan lines, giving 30769T in which 8T between VDP I/Os is fine and 49230T in which the must be a 32T gap between VDP I/Os. The physical reality may be slightly different, so the sanity check may complain where it shouldn't, or fail to complain where it should. This default setup is equivalent to specifying -vid-time-check 8,32,30769 on the command line. You can vary these parameters.

In addition to the above, MEMU supports three diagnostic windows :-

Option Description
-diag-ui-mem The Memu Memory Inspector window allows you to specify an IOBYTE (and ROM subpage) and then to show what the Z80 processor sees at various addresses.
  • i - focus on the IOBYTE
  • u - focus on the ROM subpage
  • s - focus on the start address
  • p - focus on the highlighted address
  • t - focus on the data table
  • o - take a RAM snapshot
  • v - toggle whether current or snapshot RAM is shown
  • Tab - move focus
  • Left,Right,Up,Down,PageUp,PageDown - move the highlighted address
  • hex digits - edit the value where the cursor is
-diag-ui-vram The Memu VRAM Inspector window allows you to show the contents of VRAM.
  • s - focus on the start address
  • p - focus on the highlighted address
  • t - focus on the data table
  • Tab - move focus
  • Left,Right,Up,Down,PageUp,PageDown - move the highlighted address
  • hex digits - edit the value where the cursor is
-diag-ui-dis The Memu Disassembly Inspector window allows you to specify an IOBYTE (and ROM subpage) and disassemble the code seen by the Z80 at various addresses.
  • i - focus on the IOBYTE
  • u - focus on the ROM subpage
  • s - focus on the start address
  • Tab - move focus
  • j - jump to indicated address
  • k or Right - push current listing, list from indicated address
  • l - toggle display of illegal instruction infomation
  • m - toggle MTX specific disassembly
  • Escape or Left - pop to previous listing
  • Up,Down,PageUp,PageDown - move the highlighted address
When an instruction references (ie: jumps or calls) another address, an indication is given to the right of the instruction where the jump or call will go.

MEMU has a special RAM snapshot feature. First, you tell MEMU how many of the RAM pages are to be included in the snapshot using the -mem-blocks-snapshot N command line argument. N is the number of 16KB RAM pages. This number is normally 0, but might reasonably be 4 when debugging. MEMU takes a snapshot just before the Z80 is started, and if you're running a RUN file from the MEMU command line, just before it is given control. In the Memu Memory Inspector window colours communicate the following :-

Pressing o takes a new snapshot. Pressing v toggles whether you are looking at the current value, or the value in the snapshot.

Remember to use -diag-console, -diag-file or -diag-ring (or a combination of these), or you won't see any diagnostic output.

MEMU also responds to the following diagnostic key presses. F9 is used like a Shift key :-

Key Description
F9+c Toggles -diag-console
F9+a Toggles accelerated mode
F9+b Toggles -diag-mem-iobyte
F9+d Dump memory to memu.mem
F9+f Toggles -diag-cpm-bdos-file
F9+i Toggles -diag-z80-interrupts
F9+k Toggles -diag-kbd-sense
F9+l Loads ZX snapshot file, as specified by -sna-file
F9+m Toggles -diag-speed
F9+p Toggles -diag-bad-port-display
F9+q Toggles -diag-bad-port-ignore
F9+r Dumps a snapshot of the Z80 registers
F9+s Saves ZX snapshot file, as specified by -sna-file
F9+t Rewinds to the start of a ZX tape file
F9+v Dumps a snapshot of the VDP registers
F9+n Dumps the VDP to memuNNNNNN.vdp. This writes 16KB VRAM, 8 register bytes, and 1 status register byte.
F9+o Toggles auto VDP dump mode on or off
F9+w Snapshots the VDP screen to memuNNNNNN.bmp
F9+x Toggles auto VDP snapshot mode on or off
F9+y Toggles -diag-spec-ports
F9+z Toggles -diag-z80-instructions

During development of MEMU, one of my games scrolled unevenly, due to an initially incorrect Z80 CTC implementation. I eventually tracked down what was going on using :-

$ memu -diag-console -diag-vid-refresh -diag-ctc -diag-z80-interrupts \
       -vid-win-big SMG2M.COM

The author is likely to add and/or remove -diag options and/or diagnostic key presses, depending on what he finds is needed to debug problems, and which options turn out to be seldom used. Don't get too attached to them.

Another trick you can use is to force MEMU to terminate when it reaches a given address. This relies on the fact MEMU only expects magic patch instructions to be at certain addresses. If patch.dat contains the 2 magic patch instruction bytes 0xed 0xfe, then you can cause MEMU to halt when it reaches 0x9999, dumping the last few thousand instructions it executed just before it got there :-

$ memu -diag-ring -diag-z80 \
       -addr 0x9999 -mem patch.dat \
       -vid-win-big -snd-portaudio \
        SOMEGAME.COM
memu: magic instruction unexpectedly encountered at 0x9999

On UNIX or Windows versions of MEMU, a backdoor can be enabled, allowing BE to access memory and VDP content via the BEMEMU memory extension. This can provide a better view inside emulated memory than is possible using -diag-ui-mem, -diag-ui-dis, and -diag-ui-vram, as BE supports sophisticated structured data decode, navigation, use of disassemblers, with reference to symbol tables.

The above example shows me disassembling Speculator.mtx, as it is running, which is possible as BE is also using the BEZ80 disassembler extension.