Using IX, IY.
Using IX, IY.
Although I think I've managed to get a fair amount of good stuff out of the humble Zeddy, I've never really messed with just how it works with regards to refreshing the screen.
However, I'm currently involved in a project which would really benefit from being about to use the IX & IY registers, but I can't as they are used by the display routine and so are corrupted(?) I presume I could move the display routine into RAM, and PUSH / POP both IX & IY to preserve them - is that possible and safe for all machines?
Thanks,
Bob.
However, I'm currently involved in a project which would really benefit from being about to use the IX & IY registers, but I can't as they are used by the display routine and so are corrupted(?) I presume I could move the display routine into RAM, and PUSH / POP both IX & IY to preserve them - is that possible and safe for all machines?
Thanks,
Bob.
Re: Using IX, IY.
By using a custom display routine, it is possible to use IY exclusively, if you intend to use NMI to generate top and bottom margin and then jump to custom display routine then IX is used for that jump address, it is possible to use IX inside the display routine, as long as it holds the jump address once your normal code is running again.
hope that helps for starters
Andy
hope that helps for starters
Andy
what's that Smell.... smells like fresh flux and solder fumes...
Re: Using IX, IY.
During FAST Mode you can use the registers without problems when restoring before switching back to SLOW mode.
So if you need the index registers only during start of program you could choose temporarily fast mode which will be seen in short flickering when starting the program.
By porting the display routine into main memory you could use the IY register by changing following code portion:
But I think this is timing effective - so you have to adjust the included timing for non-flickering.
You can not use the IX register during display because it is used by the NMI, which you cannot change or port to main memory.
And there is the possibility to write a complete own display routines - not using the NMI's at all. Bad this is the hardest part I think.
Use of some HRG routines could be solution as well.
If it is just for convenience I would throw the idea of using index registers in your program. It's more easy to use the second register set with EXX if you need more or use the stack. EX (SP),HL is very useful and powerful. So you can use the stack as a 4th 16 bit register.
So if you need the index registers only during start of program you could choose temporarily fast mode which will be seen in short flickering when starting the program.
By porting the display routine into main memory you could use the IY register by changing following code portion:
Code: Select all
; ---------------------------------
; THE 'DISPLAY BLANK LINES' ROUTINE
; ---------------------------------
; This subroutine is called twice (see above) to generate first the blank
; lines at the top of the television display and then the blank lines at the
; bottom of the display.
;; DISPLAY-3
L0292: POP IX ; pop the return address to IX register.
; will be either L0281 or L028F - see above.
LD C,(IY+$28) ; load C with value of system constant MARGIN.
BIT 7,(IY+$3B) ; test CDFLAG for compute and display.
JR Z,L02A9 ; forward, with FAST mode, to DISPLAY-4
LD A,C ; move MARGIN to A - 31d or 55d.
NEG ; Negate
INC A ;
EX AF,AF' ; place negative count of blank lines in A'
You can not use the IX register during display because it is used by the NMI, which you cannot change or port to main memory.
And there is the possibility to write a complete own display routines - not using the NMI's at all. Bad this is the hardest part I think.
Use of some HRG routines could be solution as well.
If it is just for convenience I would throw the idea of using index registers in your program. It's more easy to use the second register set with EXX if you need more or use the stack. EX (SP),HL is very useful and powerful. So you can use the stack as a 4th 16 bit register.
Re: Using IX, IY.
Thanks for the information. Unfortunately it would be used during the main game loop, so switching to FAST mode isn't an option, and although I'd always hope not to have to use the index registers (as they are slow anyway) I just wanted to see what the possibilities are. Hopefully I'll be able to write the code in such a way that doesn't need them at all. 

Re: Using IX, IY.
Something I've noticed is that IY seems to remain constant at $4000 - is this true?
Re: Using IX, IY.
Yes - that's true.
Unfortunately this is not very helpful when you want to assign variables in a program in the first REM line as this is at 16514 = $4000+$82 while offset can be between $80 (-128) and $7F (+127). But if you place your game data in the area of the printer buffer (IY+60 / 16444) you have 33 bytes to use here exclusively if no printer is used. You could use 30 bytes more if you don't use BASIC context (MEMBOT) or if this area could be destroyed after. MEMBOT is not used from video display routine.
Unfortunately this is not very helpful when you want to assign variables in a program in the first REM line as this is at 16514 = $4000+$82 while offset can be between $80 (-128) and $7F (+127). But if you place your game data in the area of the printer buffer (IY+60 / 16444) you have 33 bytes to use here exclusively if no printer is used. You could use 30 bytes more if you don't use BASIC context (MEMBOT) or if this area could be destroyed after. MEMBOT is not used from video display routine.
Re: Using IX, IY.
Further to the constant nature of IY is the fact that only a few bytes are accessed using it. And while a program runs the values in these bytes don't change, if memory serves. If you search the ROM code you'll see.
I wrote a game a long time ago, ballblaster, which used IY as a base register for object data. I allocated 64 bytes per object on a heap but reserved certain bytes within each block which were initialised with copies of the data which would ordinarily be read if IY was $4000. As IY changes the ROM sees the expected values in memory, and I could use IY to address my object's data
It is wasteful of memory but it didn't matter for the simple thing that I'd done. The code includes a simple co-operative multitasking system where game objects exist in a circularly linked list and execution proceeds by each object executing for some time then yielding the processor to the next in the list. Execution returns to the instruction after the object yields, so the logic for your game objects is more linear, without any of that messy state to contend with. I think it's all explained in the source.
C
I wrote a game a long time ago, ballblaster, which used IY as a base register for object data. I allocated 64 bytes per object on a heap but reserved certain bytes within each block which were initialised with copies of the data which would ordinarily be read if IY was $4000. As IY changes the ROM sees the expected values in memory, and I could use IY to address my object's data

It is wasteful of memory but it didn't matter for the simple thing that I'd done. The code includes a simple co-operative multitasking system where game objects exist in a circularly linked list and execution proceeds by each object executing for some time then yielding the processor to the next in the list. Execution returns to the instruction after the object yields, so the logic for your game objects is more linear, without any of that messy state to contend with. I think it's all explained in the source.
C
- Attachments
-
- BallBlaster2.zip
- (114.52 KiB) Downloaded 268 times
Re: Using IX, IY.
That's a quite good approach as well.sirmorris wrote:I allocated 64 bytes per object on a heap but reserved certain bytes within each block which were initialised with copies of the data which would ordinarily be read if IY was $4000. As IY changes the ROM sees the expected values in memory, and I could use IY to address my object's data![]()

For me using index registers isn't very recommendable as they consume both program memory (3 bytes for instruction) and are quite slow as well with 5 M-cycles and 19 T states per instruction.
Re: Using IX, IY.
Well yes, but sometimes they come in very useful. The code I'm currently converting to the '81 uses indexing all over the place, but as I work through it and understand it all more it looks as if I might be able to get away without them. Certainly that's the plan, but knowing that IY is a possibility is useful as a backup.PokeMon wrote:That's a quite good approach as well.![]()
For me using index registers isn't very recommendable as they consume both program memory (3 bytes for instruction) and are quite slow as well with 5 M-cycles and 19 T states per instruction.
Re: Using IX, IY.
That is TRUE in "normal" BASIC/ROM evironment.bobs wrote:Something I've noticed is that IY seems to remain constant at $4000 - is this true?
But if you use Z88DK to compile a C-Program for ZX81 (which of course can also contain assembly statements) Z88DK installs its own display routine, which does not use IY. So IY (resp. IX, see below) may be used (and is used by Z88DK in its libraries) and may contain any value and can be set to any value while running in the Z88DK environment.
Caution: if you want to call ROM routines with a Z88DK compiled program, you should first do
Code: Select all
call restore81
Caution 2: Since Z88DK makes a lot of use of the IX register in its floating point libraries, which would not work on ZX81 and its NMI-routine, a "trick" is made: during assembly the IX register is swapped with IY (so the floating point libraries use IY when being used for ZX81), so you should also use only IX in your assembly files (which gets to IY after assembly).
Good luck!
Siggi
My ZX81 web-server: online since 2007, running since dec. 2020 using ZeddyNet hardware
http://zx81.ddns.net/ZxTeaM
http://zx81.ddns.net/ZxTeaM