Why emulate a certain number of cycles?

I saw in several places - the next way to emulate

i.e. loops are passed to the emulation function

int CPU_execute(int cycles) { int cycle_count; cycle_count = cycles; do { /* OPCODE execution here */ } while(cycle_count > 0); return cycles - cycle_count; } 

I find it difficult to understand why you should make this approach for emulation. Why do you emulate a certain number of cycles? Can you give some scenarios where this approach is useful.

Any help is appreciated.

+4
source share
3 answers

Emulators are generally interested in tricking software written for multiple chip devices - from the point of view of the Z80 and best-selling devices, which you are probably talking about, at least about the graphics chip and the sound chip in addition to the processor.

In the real world, these chips operate simultaneously. There will be some kind of bus logic to allow them all to communicate, but they are otherwise in their own worlds.

Usually, you do not start emulating various chips as parallel processes, because the cost of forced execution of synchronization events is too high, especially in the general layout, where the same RAM block is used between several chips.

Thus, the easiest approach is the joint multitasking of various chips - run the Z80 for several cycles, then run the graphics chip in the same amount of time, etc. to infinity. What happens at start for n loops and return.

This is usually not an exact way to reproduce the behavior of a real computer bus, but it is easy to implement, and often you can trick most programs.

In the specific code that you posted, the author also decided that the emulation would cover the number of cycles until the end of the next whole instruction. Again, that is about ease of implementation, and not about what is connected with the actual interiors of a real machine. The number of running loops is returned, so other subsystems may try to adapt.

+6
source

Since you mentioned z80, I only know a perfect example of a platform where such precise emulation is sometimes required: ZX Spectrum. The standard graphics output area on the ZX Spectrum was a 256 x 192 pixel field located in the center of the screen, surrounded by a fairly wide β€œborder” area filled with solid color. The border color was controlled by outputting the value to a special output port. The idea of ​​a computer designer was that you could choose the border color that is most suitable for what is happening on the main screen.

ZX Spectrum does not have an accuracy timer. But programmers quickly realized that the β€œhard” (by modern standards) z80 timings made it possible to draw a pattern that was synchronized with the movement of the reference beam. On the ZX Spectrum, you could wait for the interrupt created at the beginning of each frame, and then literally count the exact number of cycles needed to achieve various effects. For example, one complete scanned line on the ZX Spectrum was scanned in 224 cycles. Thus, you can change the border color every 224 cycles and generate pixel lines on the border.

The graphics capacity of the ZX Spectrum was limited in the sense that the screen was divided into 8x8 blocks of pixels that could only use two colors at any given time. Programmers overcame this limitation by changing these two colors every 224 cycles, therefore, effectively, increasing the color resolution by 8 times.

I see that the discussion under a different answer focuses on whether a single scan line can be a sufficiently accurate resolution for the emulator. Well, some of the border scrolling effects that I saw on the ZX Spectrum are mostly dedicated to one z80 cycle. An emulator that wants to reproduce the correct output of such codes must also be accurate for one machine cycle.

+3
source

If you want to synchronize the processor with other equipment, it can be useful to do so. For example, if you want to synchronize it with a timer, you want to control how many cycles can go before the timer interrupts the CPU.

+2
source

All Articles