Since the ZX81 display routine uses during SLOW mode the alternate register AF' (used by NMI-routine) of the z80 as well as IX and IY (IX: holds address of next executed display routine (2 different values), IY used to access the system variables necessary for display), those registers may not be modified by the application or libraries (except by special applications like hires graphics routines, which use IX to jump to the new hrg-display routine).
Siggi
Addendum:
a solution or workaround could be:
- remove access to AF' and IX/IY from libraries or generated code where possible (e. g. in memset())
Where this is not possible or is too complex:
- switch to FAST mode during critical code sections and restore registers and original run mode afterwards.
This could be done with rom-calls to KFAST and SLOWFAST. During SLOW mode the screen would flicker, but the Zeddy won't crash ...
Of course that rom-calls should only be made, if the program is compiled for a Zeddy ...
SLOW mode for ZX81
SLOW mode for ZX81
Last edited by siggi on Thu Sep 13, 2007 8:28 am, edited 1 time in total.
Hey,
It is very nice to see someone still playing around that port !
The biggest problem I had adapting the Z88DK libraries to the ZX81 is that the earlier emulators didn't handle the NMI stuff as the real machine did.. and I discovered it very late.
This brought me introducing those many workarounds, and even making the "FAST" mode working correctly has been difficult (I've even rewritten the floating point library, to make it run)
Please, explain me better the KFAST/SLOWFAST trick.. then we might focus on a simple demo progam and begin fixing it.
It is very nice to see someone still playing around that port !
The biggest problem I had adapting the Z88DK libraries to the ZX81 is that the earlier emulators didn't handle the NMI stuff as the real machine did.. and I discovered it very late.
This brought me introducing those many workarounds, and even making the "FAST" mode working correctly has been difficult (I've even rewritten the floating point library, to make it run)
Please, explain me better the KFAST/SLOWFAST trick.. then we might focus on a simple demo progam and begin fixing it.
Hey,
and it is very nice to see someone still willing to support that port !
Indeed I used Z88DK to compile a web-server running in my ZX81:
http://zx81-siggi.endoftheinternet.org/index.html
But back to SLOW/FAST
The "normal" SLOW and FAST routine enable / disable the NMI generator in the Zeddy AND save its state in a system variable.
But the other routines are used to momentarily disable NMI (during time critical sections e. g. tape load or save) and to switch back to the previous state saved in the system variables.
So a call to SETFAST (KFAST was the wrong name) at $2E7 switches to FAST mode, but does not touch the corresponding system variable.
And SLOWFAST at $207 switches back to the mode, saved in the corresponding system variable (results in SLOW or FAST mode).
So in libraries or code sections, where IX/IY are used, the code for a ZX81 should be
call setfast
PUSH IX
PUSH IY
...
<critical code >
...
POP IY
POP IX
call slowfast
IX should not be set to default values in rom, because it could be used by HIRES-display-routines to be called instead of the standard-display routines in rom. IY could also be set to $4000.
AF`should never be used, because it is the NMI counter during slow mode and is incremented every 62 usec.
HTH Siggi
and it is very nice to see someone still willing to support that port !
Indeed I used Z88DK to compile a web-server running in my ZX81:
http://zx81-siggi.endoftheinternet.org/index.html
But back to SLOW/FAST
The "normal" SLOW and FAST routine enable / disable the NMI generator in the Zeddy AND save its state in a system variable.
But the other routines are used to momentarily disable NMI (during time critical sections e. g. tape load or save) and to switch back to the previous state saved in the system variables.
So a call to SETFAST (KFAST was the wrong name) at $2E7 switches to FAST mode, but does not touch the corresponding system variable.
And SLOWFAST at $207 switches back to the mode, saved in the corresponding system variable (results in SLOW or FAST mode).
So in libraries or code sections, where IX/IY are used, the code for a ZX81 should be
call setfast
PUSH IX
PUSH IY
...
<critical code >
...
POP IY
POP IX
call slowfast
IX should not be set to default values in rom, because it could be used by HIRES-display-routines to be called instead of the standard-display routines in rom. IY could also be set to $4000.
AF`should never be used, because it is the NMI counter during slow mode and is incremented every 62 usec.
HTH Siggi
Last edited by siggi on Tue Oct 25, 2011 1:02 pm, edited 1 time in total.
IX is used to support longs (adds, multiplies, divides) and I've used IX, IY as function pointers in library code and certainly AF' in a few spots. memset() should now be safe though
I agree with you -- there needs to be multiple versions of library code selected for each model depending on whether IX/IY/EXX/AF' is available or not. In fact there is some such code in z88dk already but (I) in particular haven't been supplying code alternatives for libraries I've written.
But yes, something to add to the to-do list.
I agree with you -- there needs to be multiple versions of library code selected for each model depending on whether IX/IY/EXX/AF' is available or not. In fact there is some such code in z88dk already but (I) in particular haven't been supplying code alternatives for libraries I've written.
But yes, something to add to the to-do list.
Recent experiments showed me that AF' makes the screen flicker, but normally the machine doesn't hang. Also, reading ROM code it looks that the other alternate registers shouldn't give problems.
So, if we swap IX and IY, the only critical register is (in theory) IY..
Let me make some more experiment, I really hope it is the good one.
So, if we swap IX and IY, the only critical register is (in theory) IY..
Let me make some more experiment, I really hope it is the good one.
But the NMI routine uses AF' as counter and increments it. So if you use it, it is modified (in background), and the algorithm (in foreground) using it will fail (as "memset" did, because the value to be set was incremented).stefano wrote:Recent experiments showed me that AF' makes the screen flicker, but normally the machine doesn't hang.
Siggi
You're damn right !
I was wondering why the "normal" fill routine wasn't crashing... simply it uses the flag part only of AF' !
I noticed that "bogomips" hangs in non-FAST modes; since I need it to evaluate the CPU speed in the different FAST/SLOW/HI-REZ modes, I'll start from there.
P.S. will you put your ZX81 online again ? ... I miss it ! )
I was wondering why the "normal" fill routine wasn't crashing... simply it uses the flag part only of AF' !
I noticed that "bogomips" hangs in non-FAST modes; since I need it to evaluate the CPU speed in the different FAST/SLOW/HI-REZ modes, I'll start from there.
P.S. will you put your ZX81 online again ? ... I miss it ! )