| | ChristopherJam
Registered: Aug 2004 Posts: 1409 |
Stablising raster IRQ with DMA
I was a little surprised not to see this method on codebase64, as it's really quite old. It's most useful at the top of the screen, where you can do the DMA forcing in the border, but for that very reason I find it a useful prelude to (e.g.) line crunch and other HW scrolling techniques.
The concept's fairly simple; you start a character row above the visible area, set an interrupt for a subsequent non-badline, and force a DMA to absorb the unknown number of cycles between then and end-of-row. Set $d011 back to $1b, and the screen appears as normal!
A simple example:
#define poke(addr,val) .(:lda #val:sta addr:.)
#define doke(addr,val) .(:lda #<val:sta addr:lda #>val:sta addr+1:.)
#define endIRQ pla:tay:pla:tax:pla:rti
#define ackIRQ pha:lda $d019:sta $d019:txa:pha:tya:pha
*= $0801-2
.word *+2 ; load address
.byt $0b,$08,$0a,$00,$9e,$32,$30,$36,$31,0,0,0 ; 10 sys2061
main:
poke($d021,$04)
sta 646
lda#147
jsr $ffd2
poke($d021,0)
poke($0400,1) ;something to see
poke($0428,2)
jsr IRQstart
loop:
inc $7e7 ; a nice untidy main loop to ensure instability!
bpl loop
jmp loop
IRQstart
poke($dc0d,$7f) ; kill CIA irq
sei
poke($01, $35) ; disable ROM
poke($d01a,$01) ; enable VIC irq
poke($d011,$1b) ; clear high bit of irq rasterline
poke($d012,$32) ; last invisible line
doke($fffe,irq1 ) ; set irq vector
cli
rts
irq1:
ackIRQ
poke($d020,$0f) ; this is unstable!
poke($d011,$1a) ; force partial badline before screen starts
poke($d020,$0b) ; this is stable ^_^
poke($d011,$1b) ; trigger normal re-fetch of first row of chars
poke($d012,$ff) ; set end-of-screen irq
doke($fffe,irq2 )
endIRQ
irq2:
ackIRQ
;ensure first row of chars is already being displayed when badline forced by irq1
poke($d011,$18)
poke($d012,$32 )
doke($fffe,irq1 )
endIRQ
(build with Fachat's xa)
Does anyone know why this technique is so rarely mentioned?
|
|
... 37 posts hidden. Click here to view all posts.... |
| | Mace
Registered: May 2002 Posts: 1799 |
"You can even busy loop to..." WHATYAMEAN?! :-) |
| | chatGPZ
Registered: Dec 2001 Posts: 11386 |
Quote:using a CIA timer is much less trouble.
actually if you consider the setup it requires, the CIA timer stuff is the most involved method of them all. and it really only makes sense when you need to sync more than once per frame. in pretty much all other cases some other method is nicer (i usually use double irq, and occasional dma forcing) |
| | Oswald
Registered: Apr 2002 Posts: 5094 |
my bad, I didnt read it fully, so I thought this would use merely the sprites for stabilization without timer.
gpz: if you make a demo, you can just copy paste the timer setup, and run it at the start, then you are set. Now for going like this imho it doesnt really matter how you init the timer. I use a routine by Ninja which does it in about 100 lines including irq setup
clever innovative method still, tho. easyer to code from scratch, than waiting for $d012 change and then add cycles accordingly. |
| | MagerValp
Registered: Dec 2001 Posts: 1078 |
Quote: Quote:using a CIA timer is much less trouble.
actually if you consider the setup it requires, the CIA timer stuff is the most involved method of them all. and it really only makes sense when you need to sync more than once per frame. in pretty much all other cases some other method is nicer (i usually use double irq, and occasional dma forcing)
If you only stabilize once per frame and speedcode or busywait from thereon, then yes, double IRQ is all you need. It costs about 80 cycles though, so when you need to stabilize every N raster lines, there's a huge gain from using CIA timers since you can stabilize anywhere on a line. Hermit's init code on codebase64 is nice and compact and can be generalized to give you a 63 or 65 cycle counter, and it's smooth sailing after that. Conceptually I don't think it's much more complicated than the double IRQ, and not as crazy as putting a jmp instruction at $dc02-$dc04. |
| | ChristopherJam
Registered: Aug 2004 Posts: 1409 |
Mace wrote:
Quote:I tried the DMA method, but results vary.
How come that it sometimes jitters while with a different timing, it's stable?
And the single cycle I change, is at a point where I'd expect it to have no effect on the stabilization.
I just had a look, and the issue is you're not writing to $d011 until you're in the right hand border - too late to force DMA.
Try replacing
and #$07
ora #$18
sta $d011
with
and #$07
ora #$18
sta $d021
sta $d011
dec $d021
and you'll see where your d011 write is occurring. Drop timeloop1's iterations by two (ie ldx#$06) and it should be fine. |
| | Rastah Bar Account closed
Registered: Oct 2012 Posts: 336 |
Quote: Quote:using a CIA timer is much less trouble.
actually if you consider the setup it requires, the CIA timer stuff is the most involved method of them all. and it really only makes sense when you need to sync more than once per frame. in pretty much all other cases some other method is nicer (i usually use double irq, and occasional dma forcing)
When I was learning to make a stable raster routine, I had some difficulty understanding some of the other methods (DMA forcing in particular). So I thought about a way to directly observe/measure the beam position.
For inexperienced coders (like me) this method could be a bit easier to visualize then some of the others, even though some of these other methods are more efficient, nicer, faster, etc. Once you understand one simple method, it becomes way easier to understand more complicated ones too.
Personally, I find it always interesting to learn about different methods to achieve the same thing. That is why I started my post with "For the sake of completeness". |
| | robo
Registered: Nov 2012 Posts: 9 |
I have a question regarding the cia-timer method:
When setting $dc04 to #8, will the timer really count only from 7..1?
Because otherwise, hermit's Routine would fail (but I guess it does not...)
In the opposite, the Manual http://archive.6502.org/datasheets/mos_6526_cia.pdf
says, that CIA counts from the latched value (#8) to Zero. That would be 9 values, and so this setup not usable to correct a 7 cycle-jitter..
What am I missing? |
| | Rastah Bar Account closed
Registered: Oct 2012 Posts: 336 |
Correct me if I'm wrong: If you set it to 8, the counter will go like this: 8,7,6,5,4,3,2,1,8,8,7,6,...
So instead of 0 it will take on the value 8. |
| | robo
Registered: Nov 2012 Posts: 9 |
I already thought about something like that.
But with #8 the eor #7 will result in branch-offset = #0f.
That would be wrong, since there are only 7 adresses to branch to, so the Offset has to be 0..6. |
| | robo
Registered: Nov 2012 Posts: 9 |
Color Bar, its exactly like you wrote.
I did a short test in vice by setting up a timer and watching the values in the monitor.
So, is it a bug or what is going on? |
Previous - 1 | 2 | 3 | 4 | 5 - Next | |