| |
Partz Account closed
Registered: Jun 2008 Posts: 17 |
Raster corruption
Just after a sanity check here really.... not begging for any deep analysis.
I've set up a simple raster interrupt of the form:
INT SEI ; Disable interrupts
LDA #$7F ; Disable timer interrupts
STA $DC0D
LDA #$01 ; Enable raster interrupts
STA $D01A
LDA #<IRQ ; Set up vector
STA $0314
LDA #>IRQ
STA $0315
LDA #$1B
STA $D011
LDA #$1 ; set up interrupt position
STA $D012
CLI
HALT JMP HALT
... So nothing to elaborate there. In my interrupt routine i have a font shown for about half the screen and then i'm changing font via $d018 further down the screen by busy waiting for $d012 to reach $85 an am also changing the screen colour at this point. What im finding is that 8 times out of ten my initial interrupt seems to trigger half way down the screen not at the top.... so for example, instead of he top half of the screen being white, only 1 raster line (approx) is white at or around position $85.
I haven't yet been able to find anything in my routines that would cause any corruption so was wondering if anyone else had experienced this and if maybe there was something wrong with my (admittedly niaive) set up above? As for code thats called in the interrupt its basically:
LDA #$1
STA $d019
LDA #$02
STA $d021
wait:
LDA $d012
CMP #$85
BNE wait
LDA #$0
STA $d021
JMP $EA31
... im doing a little more than the above - changing fonts, calling some music... but structurally is there any issue with the above in terms of waiting for the raster rather than setting up a second interrupt?
|
|
... 19 posts hidden. Click here to view all posts.... |
| |
Martin Piper
Registered: Nov 2007 Posts: 722 |
Quote: No IRQs happen after lda #<irq. If one occurs just as you disable it, it'll get acknowledged by the kernal IRQ handler before sta $0314, so it's perfectly safe.
You cannot be 100% sure of that because the following code sequence is not atomic:
LDA #$7F ; Disable timer interrupts
STA $DC0D
LDA #$01 ; Enable raster interrupts
STA $D01A
Since it isn't atomic you cannot be 100% sure one IRQ will enable the other kind of IRQ after the first STA turns it off. |
| |
Graham Account closed
Registered: Dec 2002 Posts: 990 |
Has nothing to do with being atomic or not, there's simply something missing.
First disable the CIA A IRQs:
LDA #$7F
STA $DC0D ; disable CIA A IRQs
LDA $DC0D ; acknowledge CIA A IRQs <- important !
Now enable RASTER IRQ:
LDA #$01
STA $D01A ; enable RASTER IRQ
|
| |
MagerValp
Registered: Dec 2001 Posts: 1078 |
lda $dc0d is only needed if it's inside an SEI. If it's not, the kernal IRQ will simply trigger one last time, ack it, and then return to your setup code.
|
| |
Graham Account closed
Registered: Dec 2002 Posts: 990 |
And maybe mess up your stuff because you disabled Kernal or use lot's memory in the first mem pages :) I never CLI after depacking, hehe |
| |
Martin Piper
Registered: Nov 2007 Posts: 722 |
There is a reason why kernal always uses SEI/CLI pairs, it cannot assume what the user has been doing. The same is true of the user, you cannot always assume what the kernal or the previous user has been up to. It just takes someone using a turbo loader, or some other menu system that puts the IRQs into an unknown state before calling your application to cause a crash. Or even whilst moving code around in your own application you forget what IRQ setups have been done in the past. Which is why it is good defensive programming practice to always use SEI/CLI pairs. |
| |
MagerValp
Registered: Dec 2001 Posts: 1078 |
If you're executing after something other than the kernal, you of course need to account for that.
However, if all you're doing is disabling CIA#1 timer IRQs, and enabling raster IRQs, putting SEI/CLI around the code just creates a problem (from IRQs firing during setup), which you then have to add code to deal with.
A prime example is post #1 in this thread - raster IRQs are enabled (on an undefined raster line) 26 cycles before the handler is set up, needlessly creating a state that the IRQ handler might not handle gracefully (and only occuring once every 1000 launches or thereabouts, making it a bitch to debug). |
| |
TWW
Registered: Jul 2009 Posts: 545 |
Quote: If you're executing after something other than the kernal, you of course need to account for that.
However, if all you're doing is disabling CIA#1 timer IRQs, and enabling raster IRQs, putting SEI/CLI around the code just creates a problem (from IRQs firing during setup), which you then have to add code to deal with.
A prime example is post #1 in this thread - raster IRQs are enabled (on an undefined raster line) 26 cycles before the handler is set up, needlessly creating a state that the IRQ handler might not handle gracefully (and only occuring once every 1000 launches or thereabouts, making it a bitch to debug).
Im's sorry to ba a nubb but excactly how does IRQ's fire while code executing between SEI/CLI?
I figgured this for being the 'safe' way to set up a reaster-interrupt!? |
| |
Frantic
Registered: Mar 2003 Posts: 1648 |
@TWW: Not "fire" in the sense that irq handler code will be called, but an irq-flag may be set when in SEI state and precisely because no irq handler code will be executed when in SEI state the irq will not be ack'ed. ...unless one also adds code to acknowledge any irq's that may have fired after the SEI before the previously enabled sources of IRQs are disabled.
Not that it matters a whole lot. In either case, it is not a matter of a tremendous amount of code. :) |
| |
Stone
Registered: Oct 2006 Posts: 172 |
I'm a bit rusty, so I hesitate to join this discussion, but I have to agree with Martin Piper: Unless you are a 100% sure of what you're doing (and the OP clearly isn't), set up your interrupt inside a SEI/CLI block and acknowledge both CIA#1 and raster interrupts before CLI'ing. |
| |
MagerValp
Registered: Dec 2001 Posts: 1078 |
And there precisely is my point: setting it up inside an SEI/CLI block makes the code more complex and much easier to get wrong, especially if you're a beginner.
A good example of when you should use SEI/CLI is if you do non-atomic changes to the IRQ while it's running, such as redirecting the IRQ vector, or changing the IRQ raster line with both d011 and d012.
However, during setup, the procedure is:
1. disabled previous IRQ source
2. acknowledge any old IRQs
3. set up new IRQ source
4. set up new IRQ vectors
5. enable new IRQ source
None of these actions need to be done inside an SEI, and doing so creates an unnecessary step 6 where you have to acknowledge IRQs triggered inside. The only "trick" with my code is that step 2 is handled by the previous IRQ handler, instead of explicitly by the setup code.
|
Previous - 1 | 2 | 3 - Next |