Using IX, IY.

Any discussions related to the creation of new hardware or software for the ZX80 or ZX81
User avatar
bobs
Posts: 325
Joined: Thu Aug 27, 2009 10:49 pm
Location: UK
Contact:

Using IX, IY.

Post by bobs »

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.
User avatar
Andy Rea
Posts: 1606
Joined: Fri May 09, 2008 2:48 pm
Location: Planet Earth
Contact:

Re: Using IX, IY.

Post by Andy Rea »

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
what's that Smell.... smells like fresh flux and solder fumes...
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

Re: Using IX, IY.

Post by PokeMon »

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:

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'
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.
User avatar
bobs
Posts: 325
Joined: Thu Aug 27, 2009 10:49 pm
Location: UK
Contact:

Re: Using IX, IY.

Post by bobs »

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. :)
User avatar
bobs
Posts: 325
Joined: Thu Aug 27, 2009 10:49 pm
Location: UK
Contact:

Re: Using IX, IY.

Post by bobs »

Something I've noticed is that IY seems to remain constant at $4000 - is this true?
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

Re: Using IX, IY.

Post by PokeMon »

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.
sirmorris
Posts: 2812
Joined: Thu May 08, 2008 5:45 pm

Re: Using IX, IY.

Post by sirmorris »

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 :D

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 267 times
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

Re: Using IX, IY.

Post by PokeMon »

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 :D
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.
User avatar
bobs
Posts: 325
Joined: Thu Aug 27, 2009 10:49 pm
Location: UK
Contact:

Re: Using IX, IY.

Post by bobs »

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.
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.
User avatar
siggi
Posts: 1043
Joined: Thu May 08, 2008 9:30 am
Location: Wetterau, Germany
Contact:

Re: Using IX, IY.

Post by siggi »

bobs wrote:Something I've noticed is that IY seems to remain constant at $4000 - is this true?
That is TRUE in "normal" BASIC/ROM evironment.

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
to reset the registers (at least IY) to the value the ROM expects.

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
Post Reply