IY and the interrupt

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
dfzx
Manic Miner
Posts: 673
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

IY and the interrupt

Post by dfzx »

I was dicking about with an IM2 interrupt in C using z88dk. I wanted to return to BASIC leaving my interrupt routine running, but z88dk doesn't support that. (It restores IM1 when returning to BASIC from C.) It's a simple-ish change to add support to the framework, but I discovered I really didn't understand the relationship between the Spectrum BASIC interrupt handler at 0x0038 and the IY register. The fix Alcoholics Anonymous gave me on the z88dk forum was, at the end of my ISR, to load IY with 0x5c38, then call 0x0038, then return. I have no doubt he'll be right, but... why?

I was looking at the Spectrum ROM disassembly book, and I see in there:

Code: Select all

LD IY,+5C3A      IY holds +ERR-NR always.
but searching for "IY" in the rest of the book yields nothing. Um, eh? IY is set but never read or referenced? That can't be right. I must be missing something.

So I sort of understand. The BASIC ISR (and possibly the entire BASIC system?) expects IY to always hold the value 0x5c3a, so restoring it to that value before calling the BASIC ISR would clearly be the right thing to do. But why is IY needed to point to the ERR NR system variable and why doesn't it appear to be dereferenced in the Spectrum ROM?
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
Hikaru
Microbot
Posts: 100
Joined: Mon Nov 13, 2017 1:42 pm
Location: Russia
Contact:

Re: IY and the interrupt

Post by Hikaru »

Hello, world! What you're seeing here is the effect of the so-called 'good practices' at work. A small example:

Code: Select all

0038 MASK-INT     PUSH  AF                  Save the current values held in
                  PUSH  HL                  these registers.
                  LD    HL,(FRAMES)         The lower two bytes of the

                  INC   HL                  frame counter are incremented
                  LD    (FRAMES),HL         every 20 ms. (U.K.) The highest
                  LD    A,H                 byte of the frame counter is
                  OR    L                   only incremented when the
                  JR    NZ,0048,KEY-INT     value of the lower two bytes
                  INC   (FRAMES-3)          is zero.
With a bit of attention and clairvoyance, the reader will be able to infer that the line, INC (FRAMES-3), is actually implemented as INC (IY+#40).
Inactive account
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: IY and the interrupt

Post by Ast A. Moore »

Ah, a rookie mistake. ;) The BASIC interpreter—well, many ROM routines, to be precise—make heavy use of IY and prime registers. If you fool around with them, you need to save and restore them before returning to BASIC.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: IY and the interrupt

Post by Ast A. Moore »

dfzx wrote: Wed Jan 03, 2018 11:23 am But why is IY needed to point to the ERR NR system variable and why doesn't it appear to be dereferenced in the Spectrum ROM?
A lot of (but not all) system variables are accessed via the IY register in ROM. That’s just how it is. IY is initialized by NEW and STACK_BC routines.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
dfzx
Manic Miner
Posts: 673
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: IY and the interrupt

Post by dfzx »

Ast A. Moore wrote: Wed Jan 03, 2018 12:30 pm
dfzx wrote: Wed Jan 03, 2018 11:23 am But why is IY needed to point to the ERR NR system variable and why doesn't it appear to be dereferenced in the Spectrum ROM?
A lot of (but not all) system variables are accessed via the IY register in ROM. That’s just how it is. IY is initialized by NEW and STACK_BC routines.
OK, so my puzzlement now is the way this is expressed in the ROM disassembly book. Hikaru, and checking the ROM in my emulator's debugger, confirm that this:

Code: Select all

INC   (FRAMES-3)
is indeed implemented as:

Code: Select all

INC (IY+40)
How is the reader of the book supposed to go from "FRAMES-3" to "IY+40"? The word "FRAMES" doesn't appear anywhere else in the book. Is there a way of expressing such things in Z80 assembly language which I'm not familiar with?
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
User avatar
R-Tape
Site Admin
Posts: 6353
Joined: Thu Nov 09, 2017 11:46 am

Re: IY and the interrupt

Post by R-Tape »

^That is indeed a bizarre way of expressing it!

I can't find a link to it now but this ROM disassembly is much clearer (might be Geoff Wearmouth et al), and even criticises not storing IY.

Code: Select all

L0038:  PUSH    AF              ; Save the registers that will be used but not
        PUSH    HL              ; the IY register unfortunately.
        LD      HL,($5C78)      ; Fetch the first two bytes at FRAMES1.
        INC     HL              ; Increment lowest two bytes of counter.
        LD      ($5C78),HL      ; Place back in FRAMES1.
        LD      A,H             ; Test if the result was zero.
        OR      L               ;            
        JR      NZ,L0048        ; Forward, if not, to KEY-INT

        INC     (IY+$40)        ; otherwise increment FRAMES3 the third byte.
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: IY and the interrupt

Post by Seven.FFF »

Ha, that’s hilarious!! Would have confused the heck out of me too. I can kinda see why they did it, but still

There’s no such instruction as ld (nn), n or ld (nn+o), nn, of course... but who pays attention to that when they're reading an authoritative tome!
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Hikaru
Microbot
Posts: 100
Joined: Mon Nov 13, 2017 1:42 pm
Location: Russia
Contact:

Re: IY and the interrupt

Post by Hikaru »

dfzx wrote: Wed Jan 03, 2018 12:36 pmHow is the reader of the book supposed to go from "FRAMES-3" to "IY+40"? The word "FRAMES" doesn't appear anywhere else in the book.
Regarding the lack of constant/variable list in the book at least, perhaps the 'ROM Disassembly' authors were relying on the fact that these are listed in this Spectrum manual, which I assume was part of the package. As I've never owned any of the original Spectrum models, I can't really tell.
Inactive account
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: IY and the interrupt

Post by Ast A. Moore »

dfzx wrote: Wed Jan 03, 2018 12:36 pm How is the reader of the book supposed to go from "FRAMES-3" to "IY+40"? The word "FRAMES" doesn't appear anywhere else in the book.
Now that you’ve mentioned it, it does appear to be a little, well, idiosyncratic on their part. Granted, they used the standard names for Spectrum’s system variables, so anybody familiar with them wouldn’t have questions about them.

That said, I’ve always consulted that book “the other way around.” That is, I rarely read the book first and wrote my routines around it later. I used a debugger/monitor, found an entry point, and then consulted the book. That way I generally read the comments, rather than looked at the disassembly in the book.

In any event, there’s an excellent electronic version of it you can consult instead of the printed book or a PDF. It does treat index registers the proper way and many things are hyperlinked for easy access.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
AndyC
Dynamite Dan
Posts: 1388
Joined: Mon Nov 13, 2017 5:12 am

Re: IY and the interrupt

Post by AndyC »

Yeah, very weird way of writing it. I'd expect to see:

INC (IY+FRAMES)

or

INC (IY+$40); update FRAMES

I can kind-of see the logic in what it was trying to convey, given that the Spectrum ROM assumes IY remains constant all the time, but it doesn't make things very obvious at all.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: IY and the interrupt

Post by RMartins »

Yep, "weird" is the right choice of words.

It can surely baffle the casual or beginner ZX ASM programmer.

A "veteran" Z80 asm programmer will know that there is no instrution
INC (nn)
dfzx
Manic Miner
Posts: 673
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: IY and the interrupt

Post by dfzx »

Here's the result of my aforementioned dicking around:

[youtube]https://youtu.be/DW1viKMx5T0[/youtube]

I think you'll all agree that's dead useful! :D

The interrupt routine which animates the coin is written in C, using z88dk. It currently needs a tweaked z88dk runtime library because the default one switches the interrupt back to IM1 when the C program exits. But I'm going to fix that and give AA a pull request. :)
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
User avatar
R-Tape
Site Admin
Posts: 6353
Joined: Thu Nov 09, 2017 11:46 am

Re: IY and the interrupt

Post by R-Tape »

Very cool.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: IY and the interrupt

Post by Ast A. Moore »

Neat. I seem to remember a similar trick with a line of scrolling text made out of screen attributes. Was pretty jaw-dropping the first time I saw it.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
dfzx
Manic Miner
Posts: 673
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: IY and the interrupt

Post by dfzx »

Ast A. Moore wrote: Thu Jan 04, 2018 8:03 pm Neat. I seem to remember a similar trick with a line of scrolling text made out of screen attributes. Was pretty jaw-dropping the first time I saw it.
Yeah, I saw that too! In fact, that's what I intend to try next! :)

And on that topic I need a new thread...
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: IY and the interrupt

Post by RMartins »

dfzx wrote: Thu Jan 04, 2018 7:27 pm ...
I think you'll all agree that's dead useful! :D

The interrupt routine which animates the coin is written in C, using z88dk. It currently needs a tweaked z88dk runtime library because the default one switches the interrupt back to IM1 when the C program exits. But I'm going to fix that and give AA a pull request. :)
I would suggest that you either use XOR for placing the sprite, or correctly mask the thing against the already existing image.
It will look way nicer :)

And if you are careful (check if the screen data changed between updates ) you can make it pixel correct, even if "someone" else is messing with the screen.
Post Reply