Added feature
Closed this issue · 3 comments
Not a bug just a new feature i added.
When EI (enable interrupts) occur i need to know if there is an interrupt waiting so i should leave the emulating loop so i added a new function also i am not sure if it is a bug but i also changed the
number_cycles += 4;
with number_cycles = elapsed_cycles+4;
so the loop will end after 4 cycles.
`
case EI: {
bool c;
state->iff1 = state->iff2 = 1;
#ifdef Z80_CATCH_EI
state->status = Z80_STATUS_FLAG_EI;
goto stop_emulation;
#else
/* See comment for DI. */
// number_cycles += 4;
//TODO:Ask if there is an interrupt
// getint before exiting
Z80_GetInterrupt(c);
if (c) {
number_cycles = elapsed_cycles+4;
}
break;
#endif
}
`
on user.h just added a new macro
#define Z80_GetInterrupt(x)
{
(x) = MyZ80->Z_GetInterrupt();
}
MyZ80 is a Delphi class i use to communicate with C++ Builder so people just put there their own function that tells Z80 if there is an interrupt waiting in order to break the emulation.
If i don't use this the emulation is very slow because it exits the loop every 100 cycles which interrupts get enabled and then disabled again on the machine that i emulate.
Anyway i am ok with these changes just letting you know in case you wanted to implement something like that for everyone to use.
Hi Chris,
My rational was to arrange the code so z80emu.c isn't modified directly by the end user, but rather throught z80config.h configuration macros and z80user.h callback macros.
This way, new bug fixed versions of z80emu can be used just by overwriting the older z80emu.c, but without having to modify the user code.
So I would rather suggest that you leave macro Z80_CATCH_EI enabled (this is default), this will stop the emulation each time EI is encountered. But to write a wrapper C/C++ code around and to call this code using Delphi instead of z80emu directly.
Something like this (pseudo C++ code):
void wrapper_to_be_called_by_delphi (SYSTEM_STATE system number_cycles)
{
elapsed = 0
do {
// emulator always first clear z80state.status to zero
elapsed += Z80Emulate (system.z80state, int number_cycles, system);
if (system.z80state.status == Z80_STATUS_FLAG_EI) {
Z80_GetInterrupt(system) ;
// do interrupt things.
}
else if (system.z80state.status == Z80_STATUS_FLAG_DI) {
}
// do more things...
} while (elapsed < number_cycles);
}
Exiting the emulation loop and re-entering it, shouldn't be very slow if we stay in C++ without switching between Delphi. Otherwise, you will indeed have to customize the code.
The "number_cycles += 4" is used to force the emulation of the next instruction because according to the Z80 manual, no interrupt is accepted right after an EI instruction. I don't think this is a problem if that fact is ignored.
Best regards,
Hi,
It's not Delphi that makes the program slow but the way i do the emulation i use a 1ms timer to emulate (not the best way) the code until the next interrupt (interrupts occur every 13ms and every 20 ms) so that is some thousand cycles. If i use an interrupt every time en EI executes that happens every 180cycles so if i loose 1ms that makes the emulation very slow.
So i realy need to exit the loop when EI gets executed AND an interrupt is waiting to be served that's why i changed the code on z80emu.c.
I just thought that checking through a function if an interrupt is waiting to happen would be a nice feature but i can do without it anyway, no problem.
Best regards,
Chris
Hi Chris,
I tried my best to have z80emu usable right out of the box with minimal changes.
But it seems there are sometimes customizations that are inevitable.
Best wishes for your emulation project.
Kind regards,