zemu 0.2.2 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/zemu.rb +1 -1
 - data/lib/zemu/config.rb +80 -10
 - data/lib/zemu/instance.rb +65 -8
 - data/lib/zemu/interactive.rb +11 -3
 - data/src/debug.c +13 -61
 - data/src/debug.h +5 -17
 - data/src/io.c.erb +22 -0
 - data/src/io.h.erb +7 -0
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 3278a3fa602a14489f1bfe77bee8d51781be503fac50dba4334dd400f492b5ca
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 0dc3644e09613e7449bbc2dd3167f4823fca647cd0b5df94b35a0d39768a8b26
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: bb87eef723a62c64742f06ec85bf7f5c976103c6e5b8678b5efec665b49ea3242efe59238f1ea28808c7ef3e597471ec050cda5f0152f3c74fa900f88df294ea
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 29de4f2e78acae5a24a443595e3b683acb3fd3a6d00ec84991c1126e3e7b07ce35078de8721347ec84926ee99fd2bd21912b1ef768fa868c0d1cc75ae966db02
         
     | 
    
        data/lib/zemu.rb
    CHANGED
    
    | 
         @@ -128,7 +128,7 @@ module Zemu 
     | 
|
| 
       128 
128 
     | 
    
         | 
| 
       129 
129 
     | 
    
         
             
                    includes_str += " -I" + autogen
         
     | 
| 
       130 
130 
     | 
    
         | 
| 
       131 
     | 
    
         
            -
                    command = "#{compiler} -Werror -Wno-unknown-warning-option -fPIC -shared -Wl,-undefined -Wl,dynamic_lookup #{includes_str} #{defines_str} -o #{output} #{inputs_str}"
         
     | 
| 
      
 131 
     | 
    
         
            +
                    command = "#{compiler} -O2 -Werror -Wno-unknown-warning-option -fPIC -shared -Wl,-undefined -Wl,dynamic_lookup #{includes_str} #{defines_str} -o #{output} #{inputs_str}"
         
     | 
| 
       132 
132 
     | 
    
         | 
| 
       133 
133 
     | 
    
         
             
                    # Run the compiler and generate a library.
         
     | 
| 
       134 
134 
     | 
    
         
             
                    return system(command)
         
     | 
    
        data/lib/zemu/config.rb
    CHANGED
    
    | 
         @@ -228,6 +228,10 @@ module Zemu 
     | 
|
| 
       228 
228 
     | 
    
         
             
                            end
         
     | 
| 
       229 
229 
     | 
    
         | 
| 
       230 
230 
     | 
    
         
             
                            @ports = []
         
     | 
| 
      
 231 
     | 
    
         
            +
                            @setup_block = nil
         
     | 
| 
      
 232 
     | 
    
         
            +
                            @read_block = nil
         
     | 
| 
      
 233 
     | 
    
         
            +
                            @write_block = nil
         
     | 
| 
      
 234 
     | 
    
         
            +
                            @clock_block = nil
         
     | 
| 
       231 
235 
     | 
    
         | 
| 
       232 
236 
     | 
    
         
             
                            super
         
     | 
| 
       233 
237 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -269,28 +273,46 @@ module Zemu 
     | 
|
| 
       269 
273 
     | 
    
         
             
                            @write_block = block
         
     | 
| 
       270 
274 
     | 
    
         
             
                        end
         
     | 
| 
       271 
275 
     | 
    
         | 
| 
      
 276 
     | 
    
         
            +
                        # Defines the per-cycle behaviour of this IO device.
         
     | 
| 
      
 277 
     | 
    
         
            +
                        #
         
     | 
| 
      
 278 
     | 
    
         
            +
                        # Expects a block, the return value of which is a string
         
     | 
| 
      
 279 
     | 
    
         
            +
                        # defining the behaviour of the IO device on each system clock cycle.
         
     | 
| 
      
 280 
     | 
    
         
            +
                        # Care must be taken to ensure that this functionality does not conflict with that of
         
     | 
| 
      
 281 
     | 
    
         
            +
                        # any other IO devices.
         
     | 
| 
      
 282 
     | 
    
         
            +
                        #
         
     | 
| 
      
 283 
     | 
    
         
            +
                        # The block will be instance-evaluated at build-time, so it is possible to use
         
     | 
| 
      
 284 
     | 
    
         
            +
                        # instance variables of the IO device.
         
     | 
| 
      
 285 
     | 
    
         
            +
                        def when_clock(&block)
         
     | 
| 
      
 286 
     | 
    
         
            +
                            @clock_block = block
         
     | 
| 
      
 287 
     | 
    
         
            +
                        end
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
       272 
289 
     | 
    
         
             
                        # Evaluates the when_setup block of this IO device and returns the resulting string.
         
     | 
| 
       273 
290 
     | 
    
         
             
                        def setup
         
     | 
| 
       274 
     | 
    
         
            -
                            instance_eval(&@setup_block)
         
     | 
| 
      
 291 
     | 
    
         
            +
                            return instance_eval(&@setup_block) unless @setup_block.nil?
         
     | 
| 
      
 292 
     | 
    
         
            +
                            return ""
         
     | 
| 
       275 
293 
     | 
    
         
             
                        end
         
     | 
| 
       276 
294 
     | 
    
         | 
| 
       277 
295 
     | 
    
         
             
                        # Evaluates the when_read block of this IO device and returns the resulting string.
         
     | 
| 
       278 
296 
     | 
    
         
             
                        def read
         
     | 
| 
       279 
     | 
    
         
            -
                            instance_eval(&@read_block)
         
     | 
| 
      
 297 
     | 
    
         
            +
                            return instance_eval(&@read_block) unless @read_block.nil?
         
     | 
| 
      
 298 
     | 
    
         
            +
                            return ""
         
     | 
| 
       280 
299 
     | 
    
         
             
                        end
         
     | 
| 
       281 
300 
     | 
    
         | 
| 
       282 
301 
     | 
    
         
             
                        # Evaluates the when_write block of this IO device and returns the resulting string.
         
     | 
| 
       283 
302 
     | 
    
         
             
                        def write
         
     | 
| 
       284 
     | 
    
         
            -
                            instance_eval(&@write_block)
         
     | 
| 
      
 303 
     | 
    
         
            +
                            return instance_eval(&@write_block) unless @write_block.nil?
         
     | 
| 
      
 304 
     | 
    
         
            +
                            return ""
         
     | 
| 
      
 305 
     | 
    
         
            +
                        end
         
     | 
| 
      
 306 
     | 
    
         
            +
             
     | 
| 
      
 307 
     | 
    
         
            +
                        # Evaluates the when_clock block of this IO device and returns the resulting string.
         
     | 
| 
      
 308 
     | 
    
         
            +
                        def clock
         
     | 
| 
      
 309 
     | 
    
         
            +
                            return instance_eval(&@clock_block) unless @clock_block.nil?
         
     | 
| 
      
 310 
     | 
    
         
            +
                            return ""
         
     | 
| 
       285 
311 
     | 
    
         
             
                        end
         
     | 
| 
       286 
312 
     | 
    
         | 
| 
       287 
313 
     | 
    
         
             
                        # Defines FFI API which will be available to the instance wrapper if this IO device is used.
         
     | 
| 
       288 
314 
     | 
    
         
             
                        def functions
         
     | 
| 
       289 
     | 
    
         
            -
                            [
         
     | 
| 
       290 
     | 
    
         
            -
                                {"name" => "zemu_io_#{name}_master_puts".to_sym, "args" => [:uint8], "return" => :void},
         
     | 
| 
       291 
     | 
    
         
            -
                                {"name" => "zemu_io_#{name}_master_gets".to_sym, "args" => [], "return" => :uint8},
         
     | 
| 
       292 
     | 
    
         
            -
                                {"name" => "zemu_io_#{name}_buffer_size".to_sym, "args" => [], "return" => :uint64}
         
     | 
| 
       293 
     | 
    
         
            -
                            ]
         
     | 
| 
      
 315 
     | 
    
         
            +
                            []
         
     | 
| 
       294 
316 
     | 
    
         
             
                        end
         
     | 
| 
       295 
317 
     | 
    
         | 
| 
       296 
318 
     | 
    
         
             
                        # Valid parameters for this object.
         
     | 
| 
         @@ -401,6 +423,15 @@ module Zemu 
     | 
|
| 
       401 
423 
     | 
    
         
             
                            end
         
     | 
| 
       402 
424 
     | 
    
         
             
                        end
         
     | 
| 
       403 
425 
     | 
    
         | 
| 
      
 426 
     | 
    
         
            +
                        # Defines FFI API which will be available to the instance wrapper if this IO device is used.
         
     | 
| 
      
 427 
     | 
    
         
            +
                        def functions
         
     | 
| 
      
 428 
     | 
    
         
            +
                            [
         
     | 
| 
      
 429 
     | 
    
         
            +
                                {"name" => "zemu_io_#{name}_master_puts".to_sym, "args" => [:uint8], "return" => :void},
         
     | 
| 
      
 430 
     | 
    
         
            +
                                {"name" => "zemu_io_#{name}_master_gets".to_sym, "args" => [], "return" => :uint8},
         
     | 
| 
      
 431 
     | 
    
         
            +
                                {"name" => "zemu_io_#{name}_buffer_size".to_sym, "args" => [], "return" => :uint64}
         
     | 
| 
      
 432 
     | 
    
         
            +
                            ]
         
     | 
| 
      
 433 
     | 
    
         
            +
                        end
         
     | 
| 
      
 434 
     | 
    
         
            +
             
     | 
| 
       404 
435 
     | 
    
         
             
                        # Valid parameters for a SerialPort, along with those
         
     | 
| 
       405 
436 
     | 
    
         
             
                        # defined in [Zemu::Config::IOPort].
         
     | 
| 
       406 
437 
     | 
    
         
             
                        def params
         
     | 
| 
         @@ -408,6 +439,44 @@ module Zemu 
     | 
|
| 
       408 
439 
     | 
    
         
             
                        end
         
     | 
| 
       409 
440 
     | 
    
         
             
                    end
         
     | 
| 
       410 
441 
     | 
    
         | 
| 
      
 442 
     | 
    
         
            +
                    # Non-Maskable Interrupt Timer
         
     | 
| 
      
 443 
     | 
    
         
            +
                    #
         
     | 
| 
      
 444 
     | 
    
         
            +
                    # Represents a timer device, the period of which can be controlled
         
     | 
| 
      
 445 
     | 
    
         
            +
                    # by the CPU through an IO port. The timer generates an NMI once this
         
     | 
| 
      
 446 
     | 
    
         
            +
                    # period has expired. The timer can be reset via a control port.
         
     | 
| 
      
 447 
     | 
    
         
            +
                    class Timer < IOPort
         
     | 
| 
      
 448 
     | 
    
         
            +
                        def initialize
         
     | 
| 
      
 449 
     | 
    
         
            +
                            super
         
     | 
| 
      
 450 
     | 
    
         
            +
             
     | 
| 
      
 451 
     | 
    
         
            +
                            when_setup do
         
     | 
| 
      
 452 
     | 
    
         
            +
                                "zuint8 io_#{name}_count;\n" +
         
     | 
| 
      
 453 
     | 
    
         
            +
                                "zuint8 io_#{name}_running = 0;\n"
         
     | 
| 
      
 454 
     | 
    
         
            +
                            end
         
     | 
| 
      
 455 
     | 
    
         
            +
             
     | 
| 
      
 456 
     | 
    
         
            +
                            when_read do
         
     | 
| 
      
 457 
     | 
    
         
            +
                            end
         
     | 
| 
      
 458 
     | 
    
         
            +
             
     | 
| 
      
 459 
     | 
    
         
            +
                            when_write do
         
     | 
| 
      
 460 
     | 
    
         
            +
                                "if (port == #{count_port}) io_#{name}_count = value;\n" +
         
     | 
| 
      
 461 
     | 
    
         
            +
                                "else if (port == #{control_port}) io_#{name}_running = value;\n"
         
     | 
| 
      
 462 
     | 
    
         
            +
                            end
         
     | 
| 
      
 463 
     | 
    
         
            +
             
     | 
| 
      
 464 
     | 
    
         
            +
                            when_clock do
         
     | 
| 
      
 465 
     | 
    
         
            +
                                "if (io_#{name}_running)\n" +
         
     | 
| 
      
 466 
     | 
    
         
            +
                                "{\n" +
         
     | 
| 
      
 467 
     | 
    
         
            +
                                "    if (io_#{name}_count > 0) io_#{name}_count--;\n" +
         
     | 
| 
      
 468 
     | 
    
         
            +
                                "    else zemu_io_nmi(instance);\n" +
         
     | 
| 
      
 469 
     | 
    
         
            +
                                "}\n"
         
     | 
| 
      
 470 
     | 
    
         
            +
                            end
         
     | 
| 
      
 471 
     | 
    
         
            +
                        end
         
     | 
| 
      
 472 
     | 
    
         
            +
             
     | 
| 
      
 473 
     | 
    
         
            +
                        # Valid parameters for a Timer, along with those defined in
         
     | 
| 
      
 474 
     | 
    
         
            +
                        # [Zemu::Config::IOPort].
         
     | 
| 
      
 475 
     | 
    
         
            +
                        def params
         
     | 
| 
      
 476 
     | 
    
         
            +
                            super + %w(count_port control_port)
         
     | 
| 
      
 477 
     | 
    
         
            +
                        end
         
     | 
| 
      
 478 
     | 
    
         
            +
                    end
         
     | 
| 
      
 479 
     | 
    
         
            +
             
     | 
| 
       411 
480 
     | 
    
         
             
                    # Gets a binding for this object.
         
     | 
| 
       412 
481 
     | 
    
         
             
                    def get_binding
         
     | 
| 
       413 
482 
     | 
    
         
             
                        return binding
         
     | 
| 
         @@ -421,7 +490,7 @@ module Zemu 
     | 
|
| 
       421 
490 
     | 
    
         | 
| 
       422 
491 
     | 
    
         
             
                    # Parameters accessible by this configuration object.
         
     | 
| 
       423 
492 
     | 
    
         
             
                    def params
         
     | 
| 
       424 
     | 
    
         
            -
                        return %w(name compiler output_directory clock_speed)
         
     | 
| 
      
 493 
     | 
    
         
            +
                        return %w(name compiler output_directory clock_speed serial_delay)
         
     | 
| 
       425 
494 
     | 
    
         
             
                    end
         
     | 
| 
       426 
495 
     | 
    
         | 
| 
       427 
496 
     | 
    
         
             
                    # Initial value for parameters of this configuration object.
         
     | 
| 
         @@ -429,7 +498,8 @@ module Zemu 
     | 
|
| 
       429 
498 
     | 
    
         
             
                        return {
         
     | 
| 
       430 
499 
     | 
    
         
             
                            "compiler" => "clang",
         
     | 
| 
       431 
500 
     | 
    
         
             
                            "output_directory" => "bin",
         
     | 
| 
       432 
     | 
    
         
            -
                            "clock_speed" => 0
         
     | 
| 
      
 501 
     | 
    
         
            +
                            "clock_speed" => 0,
         
     | 
| 
      
 502 
     | 
    
         
            +
                            "serial_delay" => 0
         
     | 
| 
       433 
503 
     | 
    
         
             
                        }
         
     | 
| 
       434 
504 
     | 
    
         
             
                    end
         
     | 
| 
       435 
505 
     | 
    
         | 
    
        data/lib/zemu/instance.rb
    CHANGED
    
    | 
         @@ -37,8 +37,24 @@ module Zemu 
     | 
|
| 
       37 
37 
     | 
    
         
             
                        "L'" => 19
         
     | 
| 
       38 
38 
     | 
    
         
             
                    }
         
     | 
| 
       39 
39 
     | 
    
         | 
| 
      
 40 
     | 
    
         
            +
                    # States that the emulated machine can be in.
         
     | 
| 
      
 41 
     | 
    
         
            +
                    class RunState
         
     | 
| 
      
 42 
     | 
    
         
            +
                        # Currently executing an instruction.
         
     | 
| 
      
 43 
     | 
    
         
            +
                        RUNNING = 0
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                        # Executed a HALT instruction in the previous cycle.
         
     | 
| 
      
 46 
     | 
    
         
            +
                        HALTED = 1
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                        # Hit a breakpoint in the previous cycle.
         
     | 
| 
      
 49 
     | 
    
         
            +
                        BREAK = 2
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                        # Undefined. Emulated machine has not yet reached a well-defined state.
         
     | 
| 
      
 52 
     | 
    
         
            +
                        UNDEFINED = -1
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
       40 
55 
     | 
    
         
             
                    def initialize(configuration)
         
     | 
| 
       41 
56 
     | 
    
         
             
                        @clock = configuration.clock_speed
         
     | 
| 
      
 57 
     | 
    
         
            +
                        @serial_delay = configuration.serial_delay
         
     | 
| 
       42 
58 
     | 
    
         | 
| 
       43 
59 
     | 
    
         
             
                        @wrapper = make_wrapper(configuration)
         
     | 
| 
       44 
60 
     | 
    
         | 
| 
         @@ -47,6 +63,10 @@ module Zemu 
     | 
|
| 
       47 
63 
     | 
    
         
             
                        @instance = @wrapper.zemu_init
         
     | 
| 
       48 
64 
     | 
    
         
             
                        @wrapper.zemu_power_on(@instance)
         
     | 
| 
       49 
65 
     | 
    
         
             
                        @wrapper.zemu_reset(@instance)
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                        @state = RunState::UNDEFINED
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                        @breakpoints = {}
         
     | 
| 
       50 
70 
     | 
    
         
             
                    end
         
     | 
| 
       51 
71 
     | 
    
         | 
| 
       52 
72 
     | 
    
         
             
                    # Returns the clock speed of this instance in Hz.
         
     | 
| 
         @@ -54,6 +74,11 @@ module Zemu 
     | 
|
| 
       54 
74 
     | 
    
         
             
                        return @clock
         
     | 
| 
       55 
75 
     | 
    
         
             
                    end
         
     | 
| 
       56 
76 
     | 
    
         | 
| 
      
 77 
     | 
    
         
            +
                    # Returns the delay between characters on the serial port for this instance in seconds.
         
     | 
| 
      
 78 
     | 
    
         
            +
                    def serial_delay
         
     | 
| 
      
 79 
     | 
    
         
            +
                        return @serial_delay
         
     | 
| 
      
 80 
     | 
    
         
            +
                    end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
       57 
82 
     | 
    
         
             
                    # Returns a hash containing current values of the emulated
         
     | 
| 
       58 
83 
     | 
    
         
             
                    # machine's registers. All names are as those given in the Z80
         
     | 
| 
       59 
84 
     | 
    
         
             
                    # reference manual.
         
     | 
| 
         @@ -124,7 +149,32 @@ module Zemu 
     | 
|
| 
       124 
149 
     | 
    
         
             
                    #
         
     | 
| 
       125 
150 
     | 
    
         
             
                    # Returns the number of cycles executed.
         
     | 
| 
       126 
151 
     | 
    
         
             
                    def continue(run_cycles=-1)
         
     | 
| 
       127 
     | 
    
         
            -
                         
     | 
| 
      
 152 
     | 
    
         
            +
                        # Return immediately if we're HALTED.
         
     | 
| 
      
 153 
     | 
    
         
            +
                        return if @state == RunState::HALTED
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                        cycles_executed = 0
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                        @state = RunState::RUNNING
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                        # Run as long as:
         
     | 
| 
      
 160 
     | 
    
         
            +
                        #   We haven't hit a breakpoint
         
     | 
| 
      
 161 
     | 
    
         
            +
                        #   We haven't halted
         
     | 
| 
      
 162 
     | 
    
         
            +
                        #   We haven't hit the number of cycles we've been told to execute for.
         
     | 
| 
      
 163 
     | 
    
         
            +
                        while (run_cycles == -1 || cycles_executed < run_cycles) && (@state == RunState::RUNNING)
         
     | 
| 
      
 164 
     | 
    
         
            +
                            cycles_executed += @wrapper.zemu_debug_step(@instance)
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                            pc = @wrapper.zemu_debug_pc(@instance)
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                            # If the PC is now pointing to one of our breakpoints,
         
     | 
| 
      
 169 
     | 
    
         
            +
                            # we're in the BREAK state.
         
     | 
| 
      
 170 
     | 
    
         
            +
                            if @breakpoints[pc]
         
     | 
| 
      
 171 
     | 
    
         
            +
                                @state = RunState::BREAK
         
     | 
| 
      
 172 
     | 
    
         
            +
                            elsif @wrapper.zemu_debug_halted()
         
     | 
| 
      
 173 
     | 
    
         
            +
                                @state = RunState::HALTED
         
     | 
| 
      
 174 
     | 
    
         
            +
                            end
         
     | 
| 
      
 175 
     | 
    
         
            +
                        end
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                        return cycles_executed
         
     | 
| 
       128 
178 
     | 
    
         
             
                    end
         
     | 
| 
       129 
179 
     | 
    
         | 
| 
       130 
180 
     | 
    
         
             
                    # Set a breakpoint of the given type at the given address.
         
     | 
| 
         @@ -133,17 +183,26 @@ module Zemu 
     | 
|
| 
       133 
183 
     | 
    
         
             
                    # @param type The type of breakpoint:
         
     | 
| 
       134 
184 
     | 
    
         
             
                    #   * :program => Break when the program counter hits the address given. 
         
     | 
| 
       135 
185 
     | 
    
         
             
                    def break(address, type)
         
     | 
| 
       136 
     | 
    
         
            -
                        @ 
     | 
| 
      
 186 
     | 
    
         
            +
                        @breakpoints[address] = true
         
     | 
| 
      
 187 
     | 
    
         
            +
                    end
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                    # Remove a breakpoint of the given type at the given address.
         
     | 
| 
      
 190 
     | 
    
         
            +
                    # Does nothing if no breakpoint previously existed at that address.
         
     | 
| 
      
 191 
     | 
    
         
            +
                    #
         
     | 
| 
      
 192 
     | 
    
         
            +
                    # @param address The address of the breakpoint to be removed.
         
     | 
| 
      
 193 
     | 
    
         
            +
                    # @param type The type of breakpoint. See Instance#break.
         
     | 
| 
      
 194 
     | 
    
         
            +
                    def remove_break(address, type)
         
     | 
| 
      
 195 
     | 
    
         
            +
                        @breakpoints[address] = false
         
     | 
| 
       137 
196 
     | 
    
         
             
                    end
         
     | 
| 
       138 
197 
     | 
    
         | 
| 
       139 
198 
     | 
    
         
             
                    # Returns true if the CPU has halted, false otherwise.
         
     | 
| 
       140 
199 
     | 
    
         
             
                    def halted?
         
     | 
| 
       141 
     | 
    
         
            -
                        return @ 
     | 
| 
      
 200 
     | 
    
         
            +
                        return @state == RunState::HALTED
         
     | 
| 
       142 
201 
     | 
    
         
             
                    end
         
     | 
| 
       143 
202 
     | 
    
         | 
| 
       144 
203 
     | 
    
         
             
                    # Returns true if a breakpoint has been hit, false otherwise.
         
     | 
| 
       145 
204 
     | 
    
         
             
                    def break?
         
     | 
| 
       146 
     | 
    
         
            -
                        return @ 
     | 
| 
      
 205 
     | 
    
         
            +
                        return @state == RunState::BREAK
         
     | 
| 
       147 
206 
     | 
    
         
             
                    end
         
     | 
| 
       148 
207 
     | 
    
         | 
| 
       149 
208 
     | 
    
         
             
                    # Powers off the emulated CPU and destroys this instance.
         
     | 
| 
         @@ -168,14 +227,12 @@ module Zemu 
     | 
|
| 
       168 
227 
     | 
    
         | 
| 
       169 
228 
     | 
    
         
             
                        wrapper.attach_function :zemu_reset, [:pointer], :void
         
     | 
| 
       170 
229 
     | 
    
         | 
| 
       171 
     | 
    
         
            -
                        wrapper.attach_function : 
     | 
| 
      
 230 
     | 
    
         
            +
                        wrapper.attach_function :zemu_debug_step, [:pointer], :uint64
         
     | 
| 
       172 
231 
     | 
    
         | 
| 
       173 
232 
     | 
    
         
             
                        wrapper.attach_function :zemu_debug_halted, [], :bool
         
     | 
| 
       174 
     | 
    
         
            -
                        wrapper.attach_function :zemu_debug_break, [], :bool
         
     | 
| 
       175 
     | 
    
         
            -
             
     | 
| 
       176 
     | 
    
         
            -
                        wrapper.attach_function :zemu_debug_set_breakpoint, [:uint16], :void
         
     | 
| 
       177 
233 
     | 
    
         | 
| 
       178 
234 
     | 
    
         
             
                        wrapper.attach_function :zemu_debug_register, [:pointer, :uint16], :uint16
         
     | 
| 
      
 235 
     | 
    
         
            +
                        wrapper.attach_function :zemu_debug_pc, [:pointer], :uint16
         
     | 
| 
       179 
236 
     | 
    
         | 
| 
       180 
237 
     | 
    
         
             
                        wrapper.attach_function :zemu_debug_get_memory, [:uint16], :uint8
         
     | 
| 
       181 
238 
     | 
    
         | 
    
        data/lib/zemu/interactive.rb
    CHANGED
    
    | 
         @@ -114,13 +114,19 @@ module Zemu 
     | 
|
| 
       114 
114 
     | 
    
         
             
                        cycles_left = cycles
         
     | 
| 
       115 
115 
     | 
    
         
             
                        actual_cycles = 0
         
     | 
| 
       116 
116 
     | 
    
         | 
| 
      
 117 
     | 
    
         
            +
                        serial_count = @instance.serial_delay
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
       117 
119 
     | 
    
         
             
                        while ((cycles == -1) || (cycles_left > 0))
         
     | 
| 
       118 
120 
     | 
    
         
             
                            # Get time before execution.
         
     | 
| 
       119 
121 
     | 
    
         
             
                            start = Time.now
         
     | 
| 
       120 
122 
     | 
    
         | 
| 
       121 
123 
     | 
    
         
             
                            old_pc = r16("PC")
         
     | 
| 
       122 
124 
     | 
    
         | 
| 
       123 
     | 
    
         
            -
                             
     | 
| 
      
 125 
     | 
    
         
            +
                            if (serial_count >= @instance.serial_delay)
         
     | 
| 
      
 126 
     | 
    
         
            +
                                process_serial
         
     | 
| 
      
 127 
     | 
    
         
            +
                                serial_count = 0
         
     | 
| 
      
 128 
     | 
    
         
            +
                            end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
       124 
130 
     | 
    
         
             
                            cycles_done = @instance.continue(1)
         
     | 
| 
       125 
131 
     | 
    
         
             
                            cycles_left -= cycles_done
         
     | 
| 
       126 
132 
     | 
    
         
             
                            actual_cycles += cycles_done
         
     | 
| 
         @@ -132,7 +138,9 @@ module Zemu 
     | 
|
| 
       132 
138 
     | 
    
         
             
                            if @instance.clock_speed > 0
         
     | 
| 
       133 
139 
     | 
    
         
             
                                elapsed = ending - start
         
     | 
| 
       134 
140 
     | 
    
         | 
| 
       135 
     | 
    
         
            -
                                execution_time =  
     | 
| 
      
 141 
     | 
    
         
            +
                                execution_time = cycles_done * (1.0/@instance.clock_speed)
         
     | 
| 
      
 142 
     | 
    
         
            +
                                serial_count += execution_time
         
     | 
| 
      
 143 
     | 
    
         
            +
                                
         
     | 
| 
       136 
144 
     | 
    
         
             
                                padding = execution_time - elapsed
         
     | 
| 
       137 
145 
     | 
    
         
             
                                sleep(padding) unless padding < 0
         
     | 
| 
       138 
146 
     | 
    
         
             
                            end
         
     | 
| 
         @@ -169,7 +177,7 @@ module Zemu 
     | 
|
| 
       169 
177 
     | 
    
         | 
| 
       170 
178 
     | 
    
         
             
                        (address.to_i(16)...address.to_i(16) + size.to_i(16)).each do |a|
         
     | 
| 
       171 
179 
     | 
    
         
             
                            m = @instance.memory(a)
         
     | 
| 
       172 
     | 
    
         
            -
                            if (m < 32)
         
     | 
| 
      
 180 
     | 
    
         
            +
                            if (m < 32 || m > 126)
         
     | 
| 
       173 
181 
     | 
    
         
             
                                log "%04x: %02x    ." % [a, m]
         
     | 
| 
       174 
182 
     | 
    
         
             
                            else
         
     | 
| 
       175 
183 
     | 
    
         
             
                                log ("%04x: %02x    " % [a, m]) + m.chr("UTF-8")
         
     | 
    
        data/src/debug.c
    CHANGED
    
    | 
         @@ -1,69 +1,16 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #include "debug.h"
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            /* Currently, the number of breakpoints is defined statically.
         
     | 
| 
       6 
     | 
    
         
            -
             * Perhaps in future there will be an unlimited number.
         
     | 
| 
       7 
     | 
    
         
            -
             */
         
     | 
| 
       8 
     | 
    
         
            -
            zuint16 breakpoints[ZEMU_DEBUG_MAX_BREAKPOINTS];
         
     | 
| 
       9 
     | 
    
         
            -
            unsigned int breakpoint_count = 0;
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
            zusize zemu_debug_continue(Z80 * instance, zinteger run_cycles)
         
     | 
| 
       12 
     | 
    
         
            -
            {
         
     | 
| 
       13 
     | 
    
         
            -
                /* Return if we've halted. */
         
     | 
| 
       14 
     | 
    
         
            -
                if (zemu_debug_state == HALTED) return 0;
         
     | 
| 
       15 
     | 
    
         
            -
             
         
     | 
| 
       16 
     | 
    
         
            -
                zusize cycles = 0;
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                zemu_debug_state = RUNNING;
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                /* Run as long as:
         
     | 
| 
       21 
     | 
    
         
            -
                 * We don't hit a breakpoint
         
     | 
| 
       22 
     | 
    
         
            -
                 * We haven't run for more than the number of cycles given
         
     | 
| 
       23 
     | 
    
         
            -
                 */
         
     | 
| 
       24 
     | 
    
         
            -
                while (zemu_debug_state == RUNNING && (run_cycles < 0 || cycles < run_cycles))
         
     | 
| 
       25 
     | 
    
         
            -
                {
         
     | 
| 
       26 
     | 
    
         
            -
                    cycles += zemu_debug_step(instance);
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                    /* See if the Program Counter now matches any address
         
     | 
| 
       29 
     | 
    
         
            -
                     * in the breakpoint array.
         
     | 
| 
       30 
     | 
    
         
            -
                     */
         
     | 
| 
       31 
     | 
    
         
            -
                    for (unsigned int b = 0; b < breakpoint_count; b++)
         
     | 
| 
       32 
     | 
    
         
            -
                    {
         
     | 
| 
       33 
     | 
    
         
            -
                        if (instance->state.pc == breakpoints[b])
         
     | 
| 
       34 
     | 
    
         
            -
                        {
         
     | 
| 
       35 
     | 
    
         
            -
                            zemu_debug_state = BREAK;
         
     | 
| 
       36 
     | 
    
         
            -
                        }
         
     | 
| 
       37 
     | 
    
         
            -
                    }
         
     | 
| 
       38 
     | 
    
         
            -
                }
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                return cycles;
         
     | 
| 
       41 
     | 
    
         
            -
            }
         
     | 
| 
      
 3 
     | 
    
         
            +
            zboolean halted = FALSE;
         
     | 
| 
       42 
4 
     | 
    
         | 
| 
       43 
5 
     | 
    
         
             
            zusize zemu_debug_step(Z80 * instance)
         
     | 
| 
       44 
6 
     | 
    
         
             
            {
         
     | 
| 
       45 
7 
     | 
    
         
             
                /* Will run for at least one cycle. */
         
     | 
| 
       46 
8 
     | 
    
         
             
                zusize cycles = z80_run(instance, 1);
         
     | 
| 
       47 
9 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                 
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
            void zemu_debug_halt(void * context, zboolean state)
         
     | 
| 
       52 
     | 
    
         
            -
            {
         
     | 
| 
       53 
     | 
    
         
            -
                if (state)
         
     | 
| 
       54 
     | 
    
         
            -
                {
         
     | 
| 
       55 
     | 
    
         
            -
                    zemu_debug_state = HALTED;
         
     | 
| 
       56 
     | 
    
         
            -
                }
         
     | 
| 
       57 
     | 
    
         
            -
                else
         
     | 
| 
       58 
     | 
    
         
            -
                {
         
     | 
| 
       59 
     | 
    
         
            -
                    zemu_debug_state = RUNNING;
         
     | 
| 
       60 
     | 
    
         
            -
                }
         
     | 
| 
       61 
     | 
    
         
            -
            }
         
     | 
| 
      
 10 
     | 
    
         
            +
                /* Execute the per-cycle behaviour of the peripheral devices. */
         
     | 
| 
      
 11 
     | 
    
         
            +
                for (zusize i = 0; i < cycles; i++) zemu_io_clock(instance);
         
     | 
| 
       62 
12 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
            {
         
     | 
| 
       65 
     | 
    
         
            -
                breakpoints[breakpoint_count] = address;
         
     | 
| 
       66 
     | 
    
         
            -
                breakpoint_count++;
         
     | 
| 
      
 13 
     | 
    
         
            +
                return cycles;
         
     | 
| 
       67 
14 
     | 
    
         
             
            }
         
     | 
| 
       68 
15 
     | 
    
         | 
| 
       69 
16 
     | 
    
         
             
            zuint16 zemu_debug_register(Z80 * instance, zuint16 r)
         
     | 
| 
         @@ -106,14 +53,19 @@ zuint16 zemu_debug_register(Z80 * instance, zuint16 r) 
     | 
|
| 
       106 
53 
     | 
    
         
             
                }
         
     | 
| 
       107 
54 
     | 
    
         
             
            }
         
     | 
| 
       108 
55 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
      
 56 
     | 
    
         
            +
            zuint16 zemu_debug_pc(Z80 * instance)
         
     | 
| 
      
 57 
     | 
    
         
            +
            {
         
     | 
| 
      
 58 
     | 
    
         
            +
                return instance->state.pc;
         
     | 
| 
      
 59 
     | 
    
         
            +
            }
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            void zemu_debug_halt(void * context, zboolean state)
         
     | 
| 
       110 
62 
     | 
    
         
             
            {
         
     | 
| 
       111 
     | 
    
         
            -
                 
     | 
| 
      
 63 
     | 
    
         
            +
                halted = state;
         
     | 
| 
       112 
64 
     | 
    
         
             
            }
         
     | 
| 
       113 
65 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
            zboolean  
     | 
| 
      
 66 
     | 
    
         
            +
            zboolean zemu_debug_halted(void)
         
     | 
| 
       115 
67 
     | 
    
         
             
            {
         
     | 
| 
       116 
     | 
    
         
            -
                return ( 
     | 
| 
      
 68 
     | 
    
         
            +
                return (halted);
         
     | 
| 
       117 
69 
     | 
    
         
             
            }
         
     | 
| 
       118 
70 
     | 
    
         | 
| 
       119 
71 
     | 
    
         
             
            zuint8 zemu_debug_get_memory(zuint16 address)
         
     | 
    
        data/src/debug.h
    CHANGED
    
    | 
         @@ -3,28 +3,16 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            #include <stdio.h>
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            #include "memory.h"
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
            /* Define number of breakpoints, if not done so already. */
         
     | 
| 
       8 
     | 
    
         
            -
            #ifndef ZEMU_DEBUG_MAX_BREAKPOINTS
         
     | 
| 
       9 
     | 
    
         
            -
            #define ZEMU_DEBUG_MAX_BREAKPOINTS 256
         
     | 
| 
       10 
     | 
    
         
            -
            #endif
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
            typedef enum RunState
         
     | 
| 
       13 
     | 
    
         
            -
            {
         
     | 
| 
       14 
     | 
    
         
            -
                RUNNING,
         
     | 
| 
       15 
     | 
    
         
            -
                HALTED,
         
     | 
| 
       16 
     | 
    
         
            -
                BREAK,
         
     | 
| 
       17 
     | 
    
         
            -
                UNDEFINED
         
     | 
| 
       18 
     | 
    
         
            -
            } RunState;
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
            zusize zemu_debug_continue(Z80 * instance, zinteger run_cycles);
         
     | 
| 
      
 6 
     | 
    
         
            +
            #include "io.h"
         
     | 
| 
       21 
7 
     | 
    
         | 
| 
       22 
8 
     | 
    
         
             
            zusize zemu_debug_step(Z80 * instance);
         
     | 
| 
       23 
9 
     | 
    
         | 
| 
       24 
10 
     | 
    
         
             
            void zemu_debug_halt(void * context, zboolean state);
         
     | 
| 
       25 
11 
     | 
    
         | 
| 
       26 
12 
     | 
    
         
             
            zboolean zemu_debug_halted(void);
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 13 
     | 
    
         
            +
            zboolean zemu_debug_break(void);
         
     | 
| 
      
 14 
     | 
    
         
            +
            zboolean zemu_debug_running(void);
         
     | 
| 
       29 
15 
     | 
    
         | 
| 
       30 
16 
     | 
    
         
             
            zuint16 zemu_debug_register(Z80 * instance, zuint16 r);
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            zuint16 zemu_debug_pc(Z80 * instance);
         
     | 
    
        data/src/io.c.erb
    CHANGED
    
    | 
         @@ -4,6 +4,21 @@ 
     | 
|
| 
       4 
4 
     | 
    
         
             
            <%= device.setup %>
         
     | 
| 
       5 
5 
     | 
    
         
             
            <% end %>
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
      
 7 
     | 
    
         
            +
            void zemu_io_nmi(Z80 * instance)
         
     | 
| 
      
 8 
     | 
    
         
            +
            {
         
     | 
| 
      
 9 
     | 
    
         
            +
                z80_nmi(instance);
         
     | 
| 
      
 10 
     | 
    
         
            +
            }
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            void zemu_io_int_on(Z80 * instance)
         
     | 
| 
      
 13 
     | 
    
         
            +
            {
         
     | 
| 
      
 14 
     | 
    
         
            +
                z80_int(instance, TRUE);
         
     | 
| 
      
 15 
     | 
    
         
            +
            }
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            void zemu_io_int_off(Z80 * instance)
         
     | 
| 
      
 18 
     | 
    
         
            +
            {
         
     | 
| 
      
 19 
     | 
    
         
            +
                z80_int(instance, FALSE);
         
     | 
| 
      
 20 
     | 
    
         
            +
            }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
       7 
22 
     | 
    
         
             
            zuint8 zemu_io_in(void * context, zuint16 port)
         
     | 
| 
       8 
23 
     | 
    
         
             
            {
         
     | 
| 
       9 
24 
     | 
    
         
             
                /* Z80 IO ports occupy the lower half of the address bus.
         
     | 
| 
         @@ -28,3 +43,10 @@ void zemu_io_out(void * context, zuint16 port, zuint8 value) 
     | 
|
| 
       28 
43 
     | 
    
         
             
            <%= device.write %>
         
     | 
| 
       29 
44 
     | 
    
         
             
            <% end %>
         
     | 
| 
       30 
45 
     | 
    
         
             
            }
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            void zemu_io_clock(Z80 * instance)
         
     | 
| 
      
 48 
     | 
    
         
            +
            {
         
     | 
| 
      
 49 
     | 
    
         
            +
            <% io.each do |device| %>
         
     | 
| 
      
 50 
     | 
    
         
            +
            <%= device.clock %>
         
     | 
| 
      
 51 
     | 
    
         
            +
            <% end %>
         
     | 
| 
      
 52 
     | 
    
         
            +
            }
         
     | 
    
        data/src/io.h.erb
    CHANGED
    
    | 
         @@ -1,3 +1,6 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #ifndef _ZEMU_IO_H
         
     | 
| 
      
 2 
     | 
    
         
            +
            #define _ZEMU_IO_H
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
       1 
4 
     | 
    
         
             
            #include "emulation/CPU/Z80.h"
         
     | 
| 
       2 
5 
     | 
    
         | 
| 
       3 
6 
     | 
    
         
             
            #ifndef ZEMU_IO_SERIAL_BUFFER_SIZE
         
     | 
| 
         @@ -16,3 +19,7 @@ zusize zemu_io_serial_buffer_size(void); 
     | 
|
| 
       16 
19 
     | 
    
         | 
| 
       17 
20 
     | 
    
         
             
            zuint8 zemu_io_in(void * context, zuint16 port);
         
     | 
| 
       18 
21 
     | 
    
         
             
            void zemu_io_out(void * context, zuint16 port, zuint8 value);
         
     | 
| 
      
 22 
     | 
    
         
            +
            void zemu_io_nmi(Z80 * instance);
         
     | 
| 
      
 23 
     | 
    
         
            +
            void zemu_io_clock(Z80 * instance);
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            #endif
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: zemu
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.3.9
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Jay Valentine
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2020- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2020-08-26 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies: []
         
     | 
| 
       13 
13 
     | 
    
         
             
            description: |2
         
     | 
| 
       14 
14 
     | 
    
         
             
                  Zemu is a gem which allows the user to configure a Z80-based system
         
     |