kosarev / z80

Fast and flexible Z80/i8080 emulator with C++ and Python APIs
MIT License
65 stars 10 forks source link

How to enable 'hooks' for out and in instructions #56

Open mortenjc opened 3 months ago

mortenjc commented 3 months ago

Hey

I am using this emulator to help revive an old Z80 based minicomputer (Q1 Lite).

I have modified the single_stepping.py example to created a disassembler and also a use it to run the code (have 8 ROM images that I can load).

Now it seems like I am likely to get stuck on the out and in instructions.

Do you have a hint on how I could emulate an IO device. For example by having a python function called on every in and out instruction?

Thanks for the project Morten

kosarev commented 3 months ago

Hi Morten, for input there's Z80Machine.set_input_callback() that sets a hook taking the port address. There's no such function for output yet, but I think I can add one -- let me know.

Alternatively, if you disassemble instructions (like in https://github.com/kosarev/z80/issues/55), you could just catch IN and OUT instructions and read/update registers as necessary on them.

mortenjc commented 3 months ago

Hey, Thanks for the answer. I used the set_input_callback() - had to do some debugging to learn that it gets a 16 bit integer where the most significant byte is the register value at the time of the callback and the least significant is the IO address. Ths helped me progress a little further!

mortenjc commented 3 months ago

Just one comment. Yes it would be very useful to have a set_output_callback as it would allow me to emulate IO devices!

I've already had to do some hacking in order to capture data written to the display:

instr = b.build_instr(m.pc, bytes(m.memory[m.pc:m.pc + MAX_INSTR_SIZE]))
        instr_str = f"{instr}"
        if instr_str[:9] == 'out (0x3)':
            out03 += chr(m.a)
            print(f'; out (0x3): 0x{m.a:02X} char: ({chr(m.a)})')

But as mentioned I am very happy with the project as it helps me move forward with bringing an old and forgotten computer to life..

kosarev commented 3 months ago

27af8c12f93f88aee99e9be4c2ee5fa6c71cf9c9 adds the support for set_output_callback(). Hope it helps.

mortenjc commented 3 months ago

Just a quick comment. The set_output_callback() works for me. Luckily I had the same abstraction so the code change was minimal. This is a much cleaner way.

However I do get a segmentation fault (on macos) if I run the emulator without registering the output callback.

kosarev commented 3 months ago

However I do get a segmentation fault (on macos) if I run the emulator without registering the output callback.

Oops. Fixed in 99ef518966763fdd9c1cf6489352ea827d5daacf.