Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > Stablising raster IRQ with DMA
2012-01-08 19:49
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....
 
2014-01-16 15:48
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.
2014-01-16 16:11
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.
2014-01-16 17:04
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?
2014-01-16 17:35
chatGPZ

Registered: Dec 2001
Posts: 11386
Quote:
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.

IMHO in pretty much all cases that justify using this timer method you'd also want to use the mentioned "ninja method" (best term ever :=)) for ACKing the interrupt, because every single cycle counts in these cases :)
2014-01-16 17:38
Rastah Bar
Account closed

Registered: Oct 2012
Posts: 336
Quote: 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?


Maybe you should check this thread:
http://csdb.dk/forums/?roomid=11&topicid=65658&showallposts=1

There the same thing is noticed by ready. and Copyfault.
2014-01-16 18:06
Rastah Bar
Account closed

Registered: Oct 2012
Posts: 336
Quote: Quote:
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.

IMHO in pretty much all cases that justify using this timer method you'd also want to use the mentioned "ninja method" (best term ever :=)) for ACKing the interrupt, because every single cycle counts in these cases :)


haha ... It just HAD to be a guy named "ninja" to invent this. Make crazy jumps and land perfectly every time :-)
2014-01-17 14:51
Rastah Bar
Account closed

Registered: Oct 2012
Posts: 336
Quoting Color Bar

Therefore, in my code I did not use a raster interrupt but just waited in the main routine for $d01f to become unequal to zero:

sei
...
;Place sprites
...
lda $d01f ;Clear sprite-to-background collision register
lda #$ff ; Turn sprites on
sta $d015
lda $d01f ; Wait for nonzero collision bits
beq *-3 ;
;Add delay depending on number of zero bits
asl
bcc *+2
...
...
;Set timer
;Continue main program
cli
rts


I peeked into my code and saw that I had put an "ora #$01" after the "beq *-3". It seems that reading $d01f clears it, but with some delay, so it can happen that you read $d01f while the beam is just before the sprites and then you branch back, read it again and the higher bits are set, but bit 0 is not. This should not happen if you read $d01f in the raster IRQ version (since you read $d01f only once then).

Or maybe the bits of $d01f are set with some delay. I do not really know.
2014-01-17 18:57
MagerValp

Registered: Dec 2001
Posts: 1078
Quoting Groepaz
Quote:
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.

IMHO in pretty much all cases that justify using this timer method you'd also want to use the mentioned "ninja method" (best term ever :=)) for ACKing the interrupt, because every single cycle counts in these cases :)

Ninja's method is impractical in some cases, since there's effectively no vector if you need to switch between several handlers, and it clobbers low ram. But if you need every last cycle, go for it.
2014-01-17 19:02
MagerValp

Registered: Dec 2001
Posts: 1078
Quoting robo
I have a question regarding the cia-timer method:

When setting $dc04 to #8, will the timer really count only from 7..1?


As others pointed out, it's 8..0 (sort of), but consider setting dc04 to 62 or 64 instead. This effectively gives you free NTSC fixing and an inverted x counter that lets you stabilize anywhere on the line.
2014-01-18 09:53
Rastah Bar
Account closed

Registered: Oct 2012
Posts: 336
Quote: 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?


It't not a bug, it's a feature :-)
Previous - 1 | 2 | 3 | 4 | 5 - Next
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
Epyx/TSA
Stone/Prosonix/Offence
Steffan/BOOM!
cba
Case/Padua
MCM/ONSLAUGHT
Andy/AEG
rikib80
Guests online: 99
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Mojo  (9.7)
4 Coma Light 13  (9.6)
5 Edge of Disgrace  (9.6)
6 What Is The Matrix 2  (9.6)
7 The Demo Coder  (9.6)
8 Uncensored  (9.6)
9 Comaland 100%  (9.6)
10 Wonderland XIV  (9.6)
Top onefile Demos
1 No Listen  (9.6)
2 Layers  (9.6)
3 Cubic Dream  (9.6)
4 Party Elk 2  (9.6)
5 Copper Booze  (9.6)
6 Dawnfall V1.1  (9.5)
7 Rainbow Connection  (9.5)
8 Onscreen 5k  (9.5)
9 Morph  (9.5)
10 Libertongo  (9.5)
Top Groups
1 Performers  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Triad  (9.3)
5 Censor Design  (9.3)
Top Fullscreen Graphicians
1 Joe  (9.7)
2 Sulevi  (9.6)
3 The Sarge  (9.6)
4 Veto  (9.6)
5 Facet  (9.6)

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