diff --git a/champ.rb b/champ.rb
index 7d27d47..2189aed 100755
--- a/champ.rb
+++ b/champ.rb
@@ -48,6 +48,7 @@ class Champ
             STDERR.puts 'Usage: ./champ.rb [options] <config.yaml>'
             STDERR.puts 'Options:'
             STDERR.puts '  --max-frames <n>'
+            STDERR.puts '  --error-log-size <n> (default: 20)'
             STDERR.puts '  --no-animation'
             exit(1)
         end
@@ -58,11 +59,17 @@ class Champ
         @max_frames = nil
         @record_frames = true
         @cycles_per_function = {}
+        @execution_log = []
+        @execution_log_size = 20
+        @code_for_pc = {}
+        @source_for_file = {}
         args = ARGV.dup
         while args.size > 1
             item = args.shift
             if item == '--max-frames'
                 @max_frames = args.shift.to_i
+            elsif item == '--error-log-size'
+                @execution_log_size = args.shift.to_i
             elsif item == '--no-animation'
                 @record_frames = false
             else
@@ -189,7 +196,7 @@ class Champ
             @max_cycle_count = 0
             call_stack = []
             last_call_stack_cycles = 0
-            Open3.popen2("./p65c02 #{@record_frames ? '' : '--no-screen'} --hide-log --start-pc #{start_pc} #{File.join(temp_dir, 'disk_image')}") do |stdin, stdout, thread|
+            Open3.popen2("./p65c02 #{@record_frames ? '' : '--no-screen'} --start-pc #{start_pc} #{File.join(temp_dir, 'disk_image')}") do |stdin, stdout, thread|
                 stdin.puts watch_input.split("\n").size
                 stdin.puts watch_input
                 stdin.close
@@ -205,7 +212,19 @@ class Champ
                     stdout.each_line do |line|
 #                         puts "> #{line}"
                         parts = line.split(' ')
-                        if parts.first == 'jsr'
+                        if parts.first == 'error'
+                            parts.shift
+                            pc = parts.shift.to_i(16)
+                            message = parts.join(' ')
+                            @error = {:pc => pc, :message => message}
+                        elsif parts.first == 'log'
+                            parts.shift
+                            log = parts.map { |x| x.to_i(16) }
+                            @execution_log << log
+                            while @execution_log.size > @execution_log_size
+                                @execution_log.shift
+                            end
+                        elsif parts.first == 'jsr'
                             pc = parts[1].to_i(16)
                             cycles = parts[2].to_i
                             @max_cycle_count = cycles
@@ -725,9 +744,9 @@ class Champ
                 io.puts "overlap = false;"
                 io.puts "rankdir = LR;"
                 io.puts "splines = true;"
-                io.puts "graph [fontname = sans, fontsize = 8, size = \"14, 11\", nodesep = 0.2, ranksep = 0.3, ordering = out];"
-                io.puts "node [fontname = sans, fontsize = 8, shape = rect, style = filled, fillcolor = \"#fce94f\" color = \"#c4a000\"];"
-                io.puts "edge [fontname = sans, fontsize = 8, color = \"#444444\"];"
+                io.puts "graph [fontname = Arial, fontsize = 8, size = \"14, 11\", nodesep = 0.2, ranksep = 0.3, ordering = out];"
+                io.puts "node [fontname = Arial, fontsize = 8, shape = rect, style = filled, fillcolor = \"#fce94f\" color = \"#c4a000\"];"
+                io.puts "edge [fontname = Arial, fontsize = 8, color = \"#444444\"];"
                 all_nodes.each do |node|
                     label = @label_for_pc[node] || sprintf('0x%04x', node)
                     label = "<B>#{label}</B>"
@@ -766,6 +785,43 @@ class Champ
                 report.sub!('#{call_graph}', '<em>(GraphViz not installed)</em>')
             end
             
+            # write error dump
+            if @error
+                io = StringIO.new
+                io.puts "<div>"
+                io.puts "<h2>Error log</h2>"
+                
+                io.puts "<code><pre>"
+                source_code = @code_for_pc[@error[:pc]]
+                STDERR.puts source_code.to_yaml
+                offset = source_code[:line] - 1
+                this_filename = source_code[:file]
+                io.puts "<span class='heading'>#{sprintf('%-83s', this_filename)}</span>"
+                ((offset - 16)..(offset + 16)).each do |i|
+                    next if i < 0 || i >= @source_for_file[this_filename].size
+                    io.print "<span class='#{(i == offset) ? 'error' : 'code'}'>"
+                    io.print sprintf('%5d | %-75s', i + 1, @source_for_file[this_filename][i])
+                    io.print "</span>" if i == offset
+                    io.puts
+                end
+                io.puts "</pre></code>"
+                
+                io.puts "<h3>Debug log</h3>"
+                io.puts "<code><pre>"
+                io.puts sprintf("<span class='heading'>   PC    |    A     X     Y     PC      SP  Flags </span>")
+                @execution_log.each do |item|
+                    io.puts sprintf("<span class='code'> 0x%04x  |  0x%02x  0x%02x  0x%02x  0x%04x  0x%02x  0x%02x  </span>", *item)
+                end
+                io.puts sprintf("<span class='error'> 0x%04x  |  %-37s </span>", @error[:pc], @error[:message])
+                io.puts "</pre></code>"
+                
+                io.puts "</div>"
+                
+                report.sub!('#{error}', io.string)
+            else
+                report.sub!('#{error}', '')
+            end
+            
             f.puts report
         end
         puts ' done.'
@@ -782,6 +838,8 @@ class Champ
     end
 
     def parse_merlin_output(path)
+        input_file = File.basename(@source_path)
+        @source_for_file[input_file] = File.read(@source_path).split("\n")
         @source_line = -3
         File.open(path, 'r') do |f|
             f.each_line do |line|
@@ -795,8 +853,18 @@ class Champ
                     pc = parts[6].split(' ').first.split('/').last.to_i(16)
                     code = parts[7].strip
                     code_parts = code.split(/\s+/)
-                    next if code_parts.empty?
 
+                    line_number = parts[1].split(' ').map { |x| x.strip }.reject { |x| x.empty? }.last.to_i
+#                     unless (@pc_code_lines.last || 0) == pc
+                        STDERR.puts line_number
+                        @code_for_pc[pc] = {
+                            :file => input_file,
+                            :line => line_number,
+                        }
+#                         @pc_code_lines << pc
+#                     end
+                            
+                    next if code_parts.empty?
                     label = nil
 
                     champ_directives = []
@@ -834,7 +902,6 @@ class Champ
                     elsif line_type == 'Code'
                         @watches[pc] ||= []
                         champ_directives.each do |directive|
-                            line_number = parts[1].split(' ').map { |x| x.strip }.reject { |x| x.empty? }.last.to_i
                             watch = parse_champ_directive(directive, false)
                             watch[:line_number] = line_number
                             watch[:pc] = pc
@@ -949,9 +1016,23 @@ __END__
         text-align: left;
         padding: 0 0.5em;
     }
+    .heading {
+        color: #2e3436;
+        background-color: #babdb6;
+        font-weight: bold;
+    }
+    .code {
+        color: #555753;
+        background-color: #edeeec;
+    }
+    .error {
+        color: #cc0000;
+        background-color: #f2bfbf;
+    }
     </style>
 </head>
 <body>
+#{error}
 <div style='float: left; padding-right: 10px;'>
     <h2>Frames</h2>
     #{screenshots}
diff --git a/examples/example05.s b/examples/example05.s
new file mode 100644
index 0000000..7d76247
--- /dev/null
+++ b/examples/example05.s
@@ -0,0 +1,17 @@
+        DSK test
+        MX %11
+        ORG $6000
+        
+        LDX #$20
+        JSR COUNT
+        LDX #$30
+        JSR COUNT
+        LDX #$40
+        JSR COUNT
+        
+        BRK
+    
+COUNT   DEX         ; @Xu(post) @cycles
+        BNE COUNT
+        BRK
+        RTS
diff --git a/examples/example05.yaml b/examples/example05.yaml
new file mode 100644
index 0000000..6823282
--- /dev/null
+++ b/examples/example05.yaml
@@ -0,0 +1,3 @@
+load:
+    0x6000: example05.s
+entry: 0x6000
diff --git a/p65c02.c b/p65c02.c
index b373dec..2d6810d 100644
--- a/p65c02.c
+++ b/p65c02.c
@@ -633,13 +633,6 @@ void handle_next_opcode()
             break;
     }
 
-    if (show_log)
-    {
-        fprintf(stderr, "# %04x | %d | %02x | %s %-18s | ", old_pc, cycles, read_opcode, OPCODE_STRINGS[opcode],
-            ADDRESSING_MODE_STRINGS[addressing_mode]
-        );
-    }
-
     int unhandled_opcode = 0;
     uint8_t t8 = 0;
     uint16_t t16 = 0;
@@ -948,7 +941,10 @@ void handle_next_opcode()
     };
     if (unhandled_opcode)
     {
-        fprintf(stderr, "Opcode %s not implemented yet at PC 0x%04x\n",
+        printf("error %04x Opcode %s not implemented yet.\n",
+               old_pc, OPCODE_STRINGS[opcode]);
+        fflush(stdout);
+        fprintf(stderr, "Opcode %s not implemented yet at PC 0x%04x.\n",
                 OPCODE_STRINGS[opcode], cpu.pc);
         exit(1);
     }
@@ -957,17 +953,9 @@ void handle_next_opcode()
         cycles_per_function[trace_stack_function[trace_stack_pointer + 1]] += cycles;
     if (show_log)
     {
-        char flags_str[6];
-        flags_str[0] = test_flag(CARRY) ? 'C' : 'c';
-        flags_str[1] = test_flag(ZERO) ? 'Z' : 'z';
-        flags_str[2] = test_flag(DECIMAL_MODE) ? 'D' : 'd';
-        flags_str[3] = test_flag(OVERFLOW) ? 'V' : 'v';
-        flags_str[4] = test_flag(NEGATIVE) ? 'N' : 'n';
-        flags_str[5] = 0;
-
-        fprintf(stderr, "A: %02x, X: %02x, Y: %02x, PC: %04x, SP: %02x, FLAGS: %02x %s | %10ld |",
-               cpu.a, cpu.x, cpu.y, cpu.pc, cpu.sp, cpu.flags, flags_str, cpu.total_cycles);
-        fprintf(stderr, "\n");
+        printf("log %04x %02x %02x %02x %04x %02x %02x\n",
+               old_pc, cpu.a, cpu.x, cpu.y, cpu.pc, cpu.sp, cpu.flags);
+        fflush(stdout);
     }
 }