Missed Interrupts with DI+IM2 in assembly

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
Wall_Axe
Manic Miner
Posts: 492
Joined: Mon Nov 13, 2017 11:13 pm

Re: Missed Interrupts with DI+IM2 in assembly

Post by Wall_Axe »

as soon as you enable interupts on other computers the interupt fires?
dont think its possible on spectrum
krt17
Drutt
Posts: 7
Joined: Wed Nov 22, 2017 6:54 pm

Re: Missed Interrupts with DI+IM2 in assembly

Post by krt17 »

There are several techniques without disabling interrupts to work with data on the stack. Their application depends on the specific situation, if you give an example of how the stack can be used more precisely.
AndyC
Dynamite Dan
Posts: 1387
Joined: Mon Nov 13, 2017 5:12 am

Re: Missed Interrupts with DI+IM2 in assembly

Post by AndyC »

The Gate Array in the CPC holds the interrupt line until the Z80 acknowledges it, which is why you won't miss an interrupt there (well unless you DI for long enough that multiple interrupts fire). IIRC the Speccy, in contrast, just pulses the interrupt line at the start of the frame. That has the advantage that interrupt positioning is more reliable but does create the possibility of missing out if you happen to have interrupts disabled. There's also not really much control over them either, it's basically an on/off switch.
Ralf
Rick Dangerous
Posts: 2279
Joined: Mon Nov 13, 2017 11:59 am
Location: Poland

Re: Missed Interrupts with DI+IM2 in assembly

Post by Ralf »

If your drawing code takes more time than one frame maybe split it into 2 parts and play music between them?
User avatar
R-Tape
Site Admin
Posts: 6353
Joined: Thu Nov 09, 2017 11:46 am

Re: Missed Interrupts with DI+IM2 in assembly

Post by R-Tape »

keith56 wrote: Sun Nov 26, 2017 3:04 am Hello there! I'm currently working on porting my Chibi Akumas game from the CPC to the ZX spectrum (and msx), things are going well, but one thing on the speccy has caught me out, so I thought I'd ask some advise on here!

Just to point out I'm using a custom interrupt handler using IM2, and do not use the firmware one in any way during gameplay

My game code 'Misuses' the stack pointer to fast fill areas of memory for sprites and screen clears, so obviously I need to disable interrupts during these times to avoid a horrible crash! On the CPC and MSX a missed interrupt occurs immediately after EI, but on the spectrum it seems that the missed interrupt never fires - which means the music is playing slowly!

I've had a look at the documentation, and I've not seen anything about changing how the 50hz interrupt fires,and I can think of some changes I can make to reduce the problem. But I thought I'd just ask on the offchance if there was some way of altering the way the Speccy fires it interrupts or detect when an interrupt was missed, of if I was totally misunderstanding things!

Game coding is going well, by the way, I should have some screenshots to show in the next few weeks!
That's my understanding, if you miss the interrupt you miss it.

Most people fit their stack routines around the interrupt by syncing to a HALT or similar, so they know it will never come during. Is that an option here?

You can't alter the way the int fires, or directly check if it was missed. If your int routine increased a counter you'd be able to tell if one hadn't happened yet, but I don't think that would help your problem.

Keen to see krt17's suggestions, I didn't realise it was possible.

Some of the suggestions how to play music in the Edge Grinder thread may help.
krt17
Drutt
Posts: 7
Joined: Wed Nov 22, 2017 6:54 pm

Re: Missed Interrupts with DI+IM2 in assembly

Post by krt17 »

method 1

Code: Select all

;sprite out routine
			ld c,(hl)
			inc hl
			ld b,(hl)
			inc hl
			ld sp,hl
			.... 
			pop bc
			....
;------
int
			ld	(.memhl), hl
			pop	hl
			ld	(.memret), hl
			ld	(.memsp), sp
			push	bc
			ld	sp, intSp
			.... ;player timer etc
.memhl		equ	$+1
			ld	hl, 0
.memsp		equ	$+1
			ld	sp, 0
			ei
.memret		equ	$+1
			jp	0			
Hikaru
Microbot
Posts: 100
Joined: Mon Nov 13, 2017 1:42 pm
Location: Russia
Contact:

Re: Missed Interrupts with DI+IM2 in assembly

Post by Hikaru »

Two cases isn't a problem:

1. Screen clears. As a general rule, you're just writing to the screen, so a triggered interrupt isn't going to corrupt anything. Just make sure not to get too close to #4000 (read: the ROM) or perhaps some sort of upper status panel/s that aren't updated constantly.

2. Sprite/tile graphics based on reading graphics data using the stack like: POP DE: LD (HL),E: INC L: LD (HL),D: INC L ...
Designate a single register pair to use for the POP-reading across all your sprite routines, for instance DE. Make sure DE = (SP-2) all the while SP is being pointed to sprite graphics. In that case, when an interrupt comes, you know that (SP) will contain the return address, and DE will hold two bytes of the sprite data that are the previous contents of (SP). So it's just a matter of putting those two bytes back into (SP) and getting the return address (EX (SP),HL might be is useful here). As a general rule, this operation will do no damage if an interrupt occurs outside of sprite routines.

Anything else I'd probably attempt to tackle it from another angle, like separating the amounts of work differently across the frames and so on.
Inactive account
User avatar
1024MAK
Bugaboo
Posts: 3104
Joined: Wed Nov 15, 2017 2:52 pm
Location: Sunny Somerset in the U.K. in Europe

Re: Missed Interrupts with DI+IM2 in assembly

Post by 1024MAK »

The ULA in a ZX Spectrum generates a 64us (32 T-states) pulse at the being of the (non-visible section of the) TV/video field. Hence the frequency being 50Hz. The ULA does not hold the interrupt line active if the CPU ignores it and it does not provide any other interrupt facilities.

This interrupt from the ULA always occurs. It's operation is hard wired and so there are no configuration settings.

The Z80 CPU will only detect a maskable (normal) interrupt when it samples the /INT pin at the end of an instruction (assuming that /RESET, /BUSRQ and /NMI are all inactive and maskable interrupts are enabled and the instruction is not DI, EI or a instruction prefix). So if the interrupt pulse from the ULA ends before maskable interrupts are enabled, yes, your program will miss that interrupt.

Mark
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :dance
Looking forward to summer later in the year.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Missed Interrupts with DI+IM2 in assembly

Post by Ast A. Moore »

1024MAK wrote: Sun Nov 26, 2017 12:27 pm The Z80 CPU will only detect a maskable (normal) interrupt when it samples the /INT pin at the end of an instruction (assuming that /RESET, /BUSRQ and /NMI are all inactive
Tut-tut. Use the Force (of BBCode), Mark. It’s INT, RESET, BUSRQ, and NMI. :D
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.
krt17
Drutt
Posts: 7
Joined: Wed Nov 22, 2017 6:54 pm

Re: Missed Interrupts with DI+IM2 in assembly

Post by krt17 »

Method 2
The basic idea is to store the checksums for all the blocks in which the reading through the stack is used. The interrupt routine considers the block checksum (add as a rule) and restores the value on the stack. Requires a little more memory (for checksums) and spends more tacts (~1400) in each interrupt. Usually blocks of 128 bytes are used. If it's not clear I can write a sample code.
Ralf
Rick Dangerous
Posts: 2279
Joined: Mon Nov 13, 2017 11:59 am
Location: Poland

Re: Missed Interrupts with DI+IM2 in assembly

Post by Ralf »

And I'd like to add one more, maybe obvious thing - you don't have to play music in interrupt routine :)

You can do it anywhere in your code, just do it during each frame. Some purists may say that if you call music player sometimes at frame beginning and sometimes at frame end then there would be loss of music quality. But I did it in my games before and nobody noticed and complained ;)
User avatar
1024MAK
Bugaboo
Posts: 3104
Joined: Wed Nov 15, 2017 2:52 pm
Location: Sunny Somerset in the U.K. in Europe

Re: Missed Interrupts with DI+IM2 in assembly

Post by 1024MAK »

Ast A. Moore wrote: Sun Nov 26, 2017 12:46 pm
1024MAK wrote: Sun Nov 26, 2017 12:27 pm The Z80 CPU will only detect a maskable (normal) interrupt when it samples the /INT pin at the end of an instruction (assuming that /RESET, /BUSRQ and /NMI are all inactive
Tut-tut. Use the Force (of BBCode), Mark. It’s INT, RESET, BUSRQ, and NMI. :D
Yeah, I know :?
But I composed this post off-line in a text editer. Then had to post in a rush, as channel 4's formula 1 coverage was about to start and I had a few other things to do before sitting down to watch it and eat lunch...

Mark
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :dance
Looking forward to summer later in the year.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Missed Interrupts with DI+IM2 in assembly

Post by Ast A. Moore »

1024MAK wrote: Sun Nov 26, 2017 7:12 pm
Ast A. Moore wrote: Sun Nov 26, 2017 12:46 pm Tut-tut. Use the Force (of BBCode), Mark. It’s INT, RESET, BUSRQ, and NMI. :D
Yeah, I know :?
But I composed this post off-line in a text editer. Then had to post in a rush, as channel 4's formula 1 coverage was about to start and I had a few other things to do before sitting down to watch it and eat lunch...

Mark
You humans are so weird. You watch TV and each lunch. So bizarre.
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.
Post Reply