Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
 Welcome to our latest new user jmi ! (Registered 2024-09-15) You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > SEI considered harmful.
2023-10-30 05:16
ChristopherJam

Registered: Aug 2004
Posts: 1402
SEI considered harmful.

Once more for the people at the back:

Don't wrap your interrupt initialisation with SEI/CLI.

It's a bad way to avoid interrupts being dispatched while you're changing the IRQ pointer, because it then requires additional code to acknowledge any pending CIA IRQs that might trigger between the SEI being executed and you turning off the CIA timer or interrupt enable.

If you're coming from BASIC, just do this instead:
    lda #$7f
    sta $dc0d

..then change $01, set your IRQ pointer(s), and init your own raster and/or timer IRQ(s)


If you're coming from a previous part, ask your teammate to turn off any IRQs and acknowedge any requests before they pass the baton (cf 'IRQ recovery' link below) - then all you need to do is set up your own IRQ.


As previously flogged to death at
TIL: The instruction after SEI can be executed before a pending IRQ is handled
C-64 coding cargo cults
Best practice IRQ recovery
2023-10-30 09:06
Oswald

Registered: Apr 2002
Posts: 5074
no way I'm leaving my cargo cult


sei
lda #$01
sta $d01a
lda #$3b
sta $d011
lda #ras1
sta $d012

lda #24
sta 53272
lda #$7f
sta $dc0d
sta $dd0d
lda $dc0d
lda $dd0d

lda #<irq1
sta $fffe
lda #>irq1
sta $ffff

lda #$35
sta $01
cli
2023-10-30 09:45
ChristopherJam

Registered: Aug 2004
Posts: 1402
I mean, those two loads from DC0D/DD0D are the 'additional code' I was referring to in the post above.

They're easy to forget because 99% of the time they don't do anything, but I guess that's not an issue if they're in your boiler plate. Such a waste of bytes though :)
2023-10-30 09:52
spider-j

Registered: Oct 2004
Posts: 482
I do it like Christopher said for years now. Never had a problem.
                    *= code_start
                    lda #0x7F
                    sta 0xDC0D
                    lda #0x35
                    sta 0x01
                    lda #0x1B
                    sta 0xD011
                    ...
2023-10-30 11:01
Cruzer

Registered: Dec 2001
Posts: 1048
Quoting ChristopherJam
If you're coming from BASIC, just do this instead:
    lda #$7f
    sta $dc0d
I never got around to study how BASIC and KERNAL works. But does this mean that I can be sure there are no IRQs or CIA2 NMIs, including from all kinds of cartridges that people might have plugged in?
2023-10-30 12:11
MagerValp

Registered: Dec 2001
Posts: 1065
Quoting Cruzer
I never got around to study how BASIC and KERNAL works. But does this mean that I can be sure there are no IRQs or CIA2 NMIs, including from all kinds of cartridges that people might have plugged in?

The only thing that's enabled at the basic prompt is the CIA1 timer irq. None of the cartridges I know of enable anything else, and if they did it'd break a shit ton of software.
2023-10-30 13:45
JackAsser

Registered: Jun 2002
Posts: 2014
Better safe than sorry during init, but between parts you know what happens. No need to clear anything.
2023-10-30 15:29
chatGPZ

Registered: Dec 2001
Posts: 11290
I tend to store $7f to $dd0d as well, knowing that it isnt really required at all. And indeed, once you link stuff together, those SEI/CLI things become a super annoying source of occasional bugs. Just don't.
2023-10-30 21:13
JackAsser

Registered: Jun 2002
Posts: 2014
Exacly Groepaz.
2023-10-30 21:32
Cruzer

Registered: Dec 2001
Posts: 1048
Quoting MagerValp
The only thing that's enabled at the basic prompt is the CIA1 timer irq. None of the cartridges I know of enable anything else, and if they did it'd break a shit ton of software.
Nice to know, thanks! It's gonna be hard to change the habit of copy/pasting the same cargo cult code I've been using forever, but I'll try.
2023-10-30 21:52
Burglar

Registered: Dec 2004
Posts: 1066
y'all make it sound too easy, there's music sync to worry about too, frameskips are fugly.
2023-10-30 22:17
JackAsser

Registered: Jun 2002
Posts: 2014
Quote: y'all make it sound too easy, there's music sync to worry about too, frameskips are fugly.

That’s what you avoid by NOT doing SEI/CLI
2023-10-30 22:40
Burglar

Registered: Dec 2004
Posts: 1066
Quote: That’s what you avoid by NOT doing SEI/CLI

yes, but it's not the full story, u dont know when (rasterline) u arrive, so u also dont know if music played this frame or not, there may be multiple irqs.

and u dont want to modify the rasterline the music is playing at too much (or at least not at once).
2023-10-30 22:49
Cruzer

Registered: Dec 2001
Posts: 1048
Quoting Burglar
yes, but it's not the full story, u dont know when (rasterline) u arrive, so u also dont know if music played this frame or not, there may be multiple irqs.

and u dont want to modify the rasterline the music is playing at too much (or at least not at once).
Whatcha talking about? Not doing SEI/CLI fixes all this. Just remove SEI/CLI from your code and it automatically becomes a perfectly linked and sync'ed trackmo. :D
2023-10-30 23:17
chatGPZ

Registered: Dec 2001
Posts: 11290
Just use a proper dubstep soundtrack
2023-10-30 23:27
Krill

Registered: Apr 2002
Posts: 2940
Is it this time of the year again. But lemme try to add a twist to this very old discussion.

A more or less interesting detail is that when coming from BASIC, the VIC raster interrupt flag is ALWAYS set.
Meaning that when you don't clear the latch by writing a 1-bit to $D019 bit 0, the interrupt will trigger immediately after unmasking it via LDA #1 : STA $D01A.

Take note that a raster interrupt may be flagged in the 3 (or 4?) cycles between clearing the latch and unmasking the interrupt.

I'll stop here and let yous dwell on this for a bit as to what this might or might not mean for timing-sensitive routines like stable-raster clockslides. =)
2023-10-31 02:40
Martin Piper

Registered: Nov 2007
Posts: 698
I think, in the C64 world, the SEI is there because the IRQ level interrupt can have a trigger that comes from more than one source, it's not just the CIA it's also the VIC, for example.

This means that technically it's not possible to completely stop all IRQ sources with just one store to $dc0d. It's not an atomic operation because you also need to stop the VIC trigger as well.

In theory it could be the case that even if the $dc0d source is disabled in the mainline (outside the IRQ), a raster IRQ could be triggered which then enables the $dc0d source before it returns, which then means a mainline VIC trigger disable would not guarantee the IRQs are really off.

The SEI then basically is an atomic way of guaranteeing that IRQs are stopped before then having to disable their triggers, and acknowledge those potential triggers, before continuing.

Of course this doesn't handle the case when an NMI could enable a raster or CIA IRQ trigger. However at least for NMI triggers then don't happen because of the VIC and their control is via $dd0d.
2023-10-31 06:50
ChristopherJam

Registered: Aug 2004
Posts: 1402
So yes, SEI guarantees atomicity, but that doesn't make a difference coming from BASIC, and while it does defend against the following hypothetical:
Quoting Martin Piper
In theory it could be the case that even if the $dc0d source is disabled in the mainline (outside the IRQ), a raster IRQ could be triggered which then enables the $dc0d source before it returns, which then means a mainline VIC trigger disable would not guarantee the IRQs are really off.

..it doesn't defend against the same hypothetical with dd0d substituted for dc0d - especially if the ISR also overrides RTI restoring I. Really, if a previous part is messing with those sorts of techniques, it needs to shut itself down properly before handing over control to the next part.

Excellent point from Krill about how you really should be acknowledging prior VIC interrupts before you set up your own - I nearly added to my initial post that you should also ensure that your interrupt setup code isn't getting in the way of when you expect your first IRQ to hit too (eg by waiting on $d012 before you start writing to d011/12/19/1a).

And yes, music handover is important if you don't want to fuck with the timing - it's just as important to avoid double calling as it is to avoid frameskip, and either way it's probably a bigger discussion than just "do this magic at init time" (eg, what happens if you need to spend a couple of frames unrolling some code or data? Who is responsible for continuing to play the tune, while not trashing other things?)
2023-10-31 07:00
Martin Piper

Registered: Nov 2007
Posts: 698
I think for the first part of a multi-part demo, the initial load, boot or whatever, there needs to be a very robust init which would include the "large" SEI/kill stuff/CLI arrangement.
But for all subsequent parts, as long as a IRQ/NMI contract can be agreed, then there doesn't need to be such a robust init. Actually in such situations there might even be sections of memory that are kept consistent with their IRQ/NMI carrying on things like music etc.
2023-10-31 07:19
ChristopherJam

Registered: Aug 2004
Posts: 1402
Yes, basically big productions need team-wide guidelines on handover.

But for simple one-filers or intros? Just poke $dc0d,127, wait for $d012 to go negative, then set up your raster IRQ.


(ok ok, and if you must insist on SEI, don't forget to lda $dc0d after you write to it)
2023-10-31 08:34
spider-j

Registered: Oct 2004
Posts: 482
Quoting Krill
Meaning that when you don't clear the latch by writing a 1-bit to $D019 bit 0, the interrupt will trigger immediately after unmasking it via LDA #1 : STA $D01A.

This here should be okay then – writing #1 to $D019 first, then $D01A:
init_irq:           lda irq_lines
                    sta 0xD012
                    sta irq_plus_cmp+1
                    inc irq_plus_cmp+1
                    lda #<irq
                    sta 0xFFFE
                    lda #>irq
                    sta 0xFFFF
                    lda #0x0B
                    sta 0xD011
                    lda #0x01
                    sta 0xD019
                    sta 0xD01A
                    rts

Or isn't it?
2023-10-31 08:49
Krill

Registered: Apr 2002
Posts: 2940
My point was that the raster interrupt...
                    lda #0x01
                    sta 0xD019
                    ; ... may trigger here
                    sta 0xD01A
                    ; ... and then fire only here
                    rts
Should usually not be a problem, but... =)
2023-10-31 09:11
spider-j

Registered: Oct 2004
Posts: 482
Okay. But I guess in my typical setup:
    init mem –> 
    basicfade that ends with screen off (bit 4 of $D011 = 0) –> 
    setup IRQ chain –>
    screen is turned on within the IRQs

that should never be a problem, because you can't turn on the screen in the middle of a frame. So if the IRQ chain is messed up in the first frame, it wouldn't matter, because screen is at the earliest turned on in the second frame anyway.

Or can you somehow trigger one of those "illegal" graphics mode while having bit 4 / $D011 zero in the middle of a frame? *scratchesHead*
2023-10-31 10:04
MagerValp

Registered: Dec 2001
Posts: 1065
Some of you seem to be conflating initial basic startup, and linking a multipart demo. Basic startup can be reduced to a short piece of boiler plate, that yes, doesn't include sei/cli. Demo linking is however a completely different beast where anything goes and it's hard to make any authoritative statements. Linking without music skipping and hard to debug race conditions is an artform.

And good point about there being an unacknowledged raster irq waiting for you at startup, pretty sure that one has messed with me before. Initial state, state changes, and order of operations are critical when setting up irqs. For raster irqs I usually do a simple wait for $d012 to $ff before setting up.
2023-10-31 10:39
spider-j

Registered: Oct 2004
Posts: 482
Quoting MagerValp
Linking without music skipping and hard to debug race conditions is an artform.

That's correct. But I feel it would be less of a challenge if everyone in your group would properly setup and exit their parts as you instructed them to :-)
2023-10-31 11:07
ChristopherJam

Registered: Aug 2004
Posts: 1402
Quoting Krill
My point was that the raster interrupt...
                    lda #0x01
                    sta 0xD019
                    ; ... may trigger here
                    sta 0xD01A
                    ; ... and then fire only here
                    rts
Should usually not be a problem, but... =)


True, but given that Spider Jerusalem already set $d012 to his desired raster line, that will only happen if that line starts just after the sta $d019 - which means it'll be happening at close enough to the desired time anyway. No need to fear for midscreen weirdness from an interrupt triggered on the wrong line altogether, as can happen without the Krill Precaution™ :D

(interestingly, according to some experiments I've just been doing, the RTS is executed before the interrupt service routine!)
2023-10-31 11:48
spider-j

Registered: Oct 2004
Posts: 482
Just found this looking through our old trackmo framework documentation:



XD
2023-10-31 11:59
Krill

Registered: Apr 2002
Posts: 2940
Okay then! =)
php
pla
ora #$04
pha
plp
2023-10-31 12:13
Martin Piper

Registered: Nov 2007
Posts: 698
Quote: Okay then! =)
php
pla
ora #$04
pha
plp


You beat me to it. :)
2023-10-31 12:36
spider-j

Registered: Oct 2004
Posts: 482
Quoting Krill
Okay then! =)
php
pla
ora #$04
pha
plp

*lol* Thank you Krill. Made my day :-)
2023-10-31 13:30
Cruzer

Registered: Dec 2001
Posts: 1048
Wait a second... If the Kernal/Basic only uses NMIs, how come you can disable them with sei? I mean, if you do something like this:
!:	inc $d020
	jmp !-
You will see the code getting interrupted when pressing down keys. But start out with a sei, and there are no interruptions:
	sei
!:	inc $d020
	jmp !-
2023-10-31 13:43
ChristopherJam

Registered: Aug 2004
Posts: 1402
KERNAL/BASIC only uses IRQs

CIA#1 ($dc00) - IRQ
CIA#2 ($dd00) - NMI

(and, lol @ Krill :D)
2023-10-31 14:34
Cruzer

Registered: Dec 2001
Posts: 1048
Ah, CIA1 produces IRQs? Wow, how didn't I know this? Probably because you don't learn anything from just copy/pasting the same old block of code when doing interrupts. Glad I checked this thread so I won't forever be one of them people in the back. \o/
2023-10-31 15:54
Oswald

Registered: Apr 2002
Posts: 5074
Quote: KERNAL/BASIC only uses IRQs

CIA#1 ($dc00) - IRQ
CIA#2 ($dd00) - NMI

(and, lol @ Krill :D)


hitting restore (key) triggers an NMI, so no both are used.
2023-10-31 16:20
ChristopherJam

Registered: Aug 2004
Posts: 1402
Cruzer - glad something good came out of the thread :)

Oswald - ok ok, "KERNAL/BASIC doesn't use CIA#2 or VIC as interrupt sources"
2023-10-31 22:15
Copyfault

Registered: Dec 2001
Posts: 468
Quoting Krill
My point was that the raster interrupt...
                    lda #0x01
                    sta 0xD019
                    ; ... may trigger here
                    sta 0xD01A
                    ; ... and then fire only here
                    rts
Should usually not be a problem, but... =)
Really? Didn't some testprog show that it's more like
                 lda #0x01
                 sta 0xD019
                     ; ... may trigger here
                 sta 0xD01A
                     ; ... is ack'd here
                 rts ; ... next opcode is ececuted
                     ; ... and irq routine starts here
? Thought this was the "result" of the TIL: The instruction after SEI can be executed before a pending IRQ is handled thread, no? In post #99 of this thread MagerValp linked the testprog I have in mind.
2023-10-31 23:10
Krill

Registered: Apr 2002
Posts: 2940
Quoting Copyfault
Quoting Krill
My point was that the raster interrupt...
                    lda #0x01
                    sta 0xD019
                    ; ... may trigger here
                    sta 0xD01A
                    ; ... and then fire only here
                    rts
Should usually not be a problem, but... =)
Really? Didn't some testprog show that it's more like
                 lda #0x01
                 sta 0xD019
                     ; ... may trigger here
                 sta 0xD01A
                     ; ... is ack'd here
                 rts ; ... next opcode is ececuted
                     ; ... and irq routine starts here
? Thought this was the "result" of the TIL: The instruction after SEI can be executed before a pending IRQ is handled thread, no? In post #99 of this thread MagerValp linked the testprog I have in mind.
Maybe. But that would just underline my point. =)
2023-10-31 23:34
spider-j

Registered: Oct 2004
Posts: 482
Can this happen to CIA2 NMI too? In the latest version of my framework I switched to that for playing music to get rid of the "SEI problem".

Of course: you can break it by pressing RESTORE. But are there any sideeffects without user interaction that can happen, once you setup the timer for a PAL frame?
2023-11-01 00:43
Krill

Registered: Apr 2002
Posts: 2940
Quoting spider-j
Can this happen to CIA2 NMI too? In the latest version of my framework I switched to that for playing music to get rid of the "SEI problem".

Of course: you can break it by pressing RESTORE. But are there any sideeffects without user interaction that can happen, once you setup the timer for a PAL frame?
What is the SEI problem, specifically?

And playing regular music (no samples) via NMI? Dunno, i'd rather prefer restore-proof blocked NMI. =)
2023-11-01 01:16
spider-j

Registered: Oct 2004
Posts: 482
Quoting Krill
What is the SEI problem, specifically

My group mates ignoring the "coding guidelines" ;-) And I must admit, after switching to the NMI solution I also found everything easier to handle. You can just do with raster IRQs what you want to do and yes there is a NMI "somewhere" that will steal you cycles but it is way easier to handle than let's say moving your IRQ lines for one effect and caring about the music (avoiding frame drops or too long player call "distances"). Yeah of course the user can destroy that by pushing RESTORE, but after all tests I did even if your NMI is nothing more than "RTI" mindlessly hitting RESTORE will make problems anyway. So I decided that pressing RESTORE shouldn't be considered a "real use case".
2023-11-01 04:15
ChristopherJam

Registered: Aug 2004
Posts: 1402
A few minor points.

Firstly, my understanding is that NMIs can be prevented altogether (like, not even the single byte RTI called) if you just trigger an NMI from CIA#2 and never acknowledge it. Not something I've ever bothered with, but it's a solid option.

Secondly, minor quibble about the comments here:
                 lda #0x01
                 sta 0xD019
                     ; ... may trigger here
                 sta 0xD01A
                     ; ... is ack'd here
                 rts ; ... next opcode is ececuted
                     ; ... and irq routine starts here


The write to d019 clears the latch ('acknowledges' previous raster matches), d01a enables interrupts, doesn't acknowledge.

But yes, Copyfault is correct - going to read TIL: The instruction after SEI can be executed before a pending IRQ is handled properly I see that I missed the tail end of the discussion last time round, and it indeed confirms my experiments from yesterday. Even if the interrupt condition latch is already set, the instruction after the write to $d01a is still executed before the interrupt occurs.

(for a hot minute I thought Copyfault was erroneously drawing a connection between the post-SEI prefetch and the $d01a thing, but I was just misled by that other post changing topics partway down the page. My bad.)
2023-11-01 08:32
oziphantom

Registered: Oct 2014
Posts: 488
when doing the initial set up and not a 4K/16K release I just clobber everything

ClearInterupts .macro
	sei
	lda #$7f
	sta $dc0d		 ;turn off all types of cia irq/nmi.
	sta $dd0d
	lda $dc0d
	lda $dd0d
	lda #$00
	sta $D01a
	lda #$ff
	sta $D019
	sta $dc0e
	sta $dc0f
	sta $dd0e
	sta $dd0f
	lda $d01e
	lda $d01f
.endm

But then I also make my code C64 and C128 compatible, the C128 doesn't use the CIA timer but actually uses the VIC Raster. But also read the Sprite collision values to clear and event on them, as sometimes d015 can be set by some menus, other tools and then you move the screen and VIC bank you can get some random collision triggers. Well okay it happened to me once, but eh never again...

The nice thing about SEI is it lets me set up the rasters I want at any point in the code and then CLI when it is ready for primetime without having to think about where and when I init things.
2023-11-01 09:37
ChristopherJam

Registered: Aug 2004
Posts: 1402
Nice "clobber all the things" there, oziphantom.

Quoting oziphantom

The nice thing about SEI is it lets me set up the rasters I want at any point in the code and then CLI when it is ready for primetime without having to think about where and when I init things.


Wait, doesn't that mean that your first raster interrupt can occur on the wrong line? (eg if you set up the rasters, then spend a frame doing some other init stuff, then do the CLI on some other line than the one where the interrupt should happen)
2023-11-01 09:41
oziphantom

Registered: Oct 2014
Posts: 488
yeah but that generally isn't a massive problem, GoatTracker takes 4 frames to warm up music etc. Maybe the colour splits will be wrong for part of a frame etc But having it fire in the middle of initing the SID routine for example could potentially be a disaster. Or if on the 128 with the wrong ZP and SP register a total disaster.
2023-11-01 14:56
chatGPZ

Registered: Dec 2001
Posts: 11290
As for "clobber all the things" - in trackmo startups i also had disabling of AR and FC3 - as those can cause weird shit too (due to longer system irq).
2023-11-02 00:20
Copyfault

Registered: Dec 2001
Posts: 468
Quoting ChristopherJam
[...]
Secondly, minor quibble about the comments here:
                 lda #0x01
                 sta 0xD019
                     ; ... may trigger here
                 sta 0xD01A
                     ; ... is ack'd here
                 rts ; ... next opcode is ececuted
                     ; ... and irq routine starts here


The write to d019 clears the latch ('acknowledges' previous raster matches), d01a enables interrupts, doesn't acknowledge.
Oh my bad! Yes, I fooled around with the wording and "ack'ing" is indeed done by writing to $D019, while setting $D01A serves as an IRQ-enabler. Thanks for putting that straight!

Quoting ChristopherJam
But yes, Copyfault is correct - going to read TIL: The instruction after SEI can be executed before a pending IRQ is handled properly I see that I missed the tail end of the discussion last time round, and it indeed confirms my experiments from yesterday. Even if the interrupt condition latch is already set, the instruction after the write to $d01a is still executed before the interrupt occurs.

(for a hot minute I thought Copyfault was erroneously drawing a connection between the post-SEI prefetch and the $d01a thing, but I was just misled by that other post changing topics partway down the page. My bad.)
No, no, it was just me being confused why the IRQ should start _before_ the following opcode is executed, but my world's order has just been reinstated ;)

Quoting Krill
Quoting Copyfault
[...]? Thought this was the "result" of the TIL: The instruction after SEI can be executed before a pending IRQ is handled thread, no? In post #99 of this thread MagerValp linked the testprog I have in mind.
Maybe. But that would just underline my point. =)
Yes, it indeed does :)
2023-11-03 09:40
Perplex

Registered: Feb 2009
Posts: 255
You don't SEI! https://www.youtube.com/watch?v=hyMM8WP5XFk
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
deetsay
bugjam
kbs/Pht/Lxt
TheRyk/MYD!
The Syndrom/TIA/Pret..
Freeze/Blazon
Scooby/G★P/Light
rexbeng
pby/HF/Acrise
Thierry
dstar/Fairlight
Brush/Elysium
lucommodore
Matt
Guests online: 135
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Coma Light 13  (9.7)
4 Edge of Disgrace  (9.6)
5 Mojo  (9.6)
6 Uncensored  (9.6)
7 Wonderland XIV  (9.6)
8 Comaland 100%  (9.6)
9 No Bounds  (9.6)
10 Unboxed  (9.6)
Top onefile Demos
1 Layers  (9.6)
2 Party Elk 2  (9.6)
3 Cubic Dream  (9.6)
4 Copper Booze  (9.6)
5 Rainbow Connection  (9.5)
6 It's More Fun to Com..  (9.5)
7 Dawnfall V1.1  (9.5)
8 Onscreen 5k  (9.5)
9 Daah, Those Acid Pil..  (9.5)
10 Morph  (9.5)
Top Groups
1 Booze Design  (9.3)
2 Oxyron  (9.3)
3 Nostalgia  (9.3)
4 Censor Design  (9.3)
5 Triad  (9.2)
Top Crackers
1 Mr. Z  (9.9)
2 Antitrack  (9.8)
3 OTD  (9.8)
4 Fungus  (9.7)
5 S!R  (9.7)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.109 sec.