| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
Mixing multiple effects is messing up stuff
I am doing a small and very lowtech demo but I seem to be confused about the raster timing - probably like any other C64 newbie out there(?).
I know(?) this is related to the raster interrupt I am using plus my routines and that everyone will shout out "learn to code before you do a demo" and you are right but I really need some directions or hints here as I cannot get my head around this problem. I have read a lot on the C64 Codebase and here in the forum but still I don't get it (no hope for me!?).
I am trying to get a static (not moving) rasterbar below a 2x2 scroll plus some music - this must be "demo programming day 1". I have done each part individually and they work but together they are screwing up things (of course!?). Well, the music and the 2x2 scroll I can get working but introducing the raster gets ne problems.
What I have is a rasterbar... fired up at raster pos #$80 (as an example). A few lines below I am starting my scroll and this is totally messing up things... the scroll is veeery slow and shifting between the 2x2 charset and the system charset and when playing music I can hear it is slowing down to 1/4 of the normal pace or alike. This must be because the rasters are overlapping but how can I overcome this?
This is not a matter of getting the rasterbars looking nice but a more fundamental problem I think - then the prettyness of the bars will be a problem for later on.
If anyone would explain me how or point me to a fool-proof-dummy-guide on how I might can solve this I would really appreciate it as I am getting really frustrated now and I don't see any solutions for it (though there obvioulsy is one). |
|
| |
Stainless Steel
Registered: Mar 2003 Posts: 966 |
wrap your routines in inc/dec $d020 to visualize the rasterusage in the frame and adjust accordingly. |
| |
Frantic
Registered: Mar 2003 Posts: 1648 |
Post a link to your code and someone may be able to make a quick peek into the code and give some advice on obvious improvements or comments on errors in your way of understanding how things work on the c64. |
| |
terric Account closed
Registered: Feb 2009 Posts: 47 |
What Stainless and Frantic sad and ---->
It sounds like you are firing the irq at line 70 and
tries to play music and scroll until raster 80.
This may not be rastertime enough for your routines and music.
Instead i suggest fire-off irq at raster 80, make the rasterbar, scroll the scroll and play the music at last.
terric |
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
I have put my code here, http://cobrakid.dk/asm/mydmo1-asm.txt - this one here is actually working (with HEAVY flickers but that's not my concern for now) as it doesn't take correct rasterbar position into consideration. If I change this in the main section:
lda #$03
sta $d020
jsr raster ; show raster
lda #$00
sta $d020 to this (this has the rasterbar in the correct pos):
lda #$7a
w1 cmp $d012
bne w1
lda #$03
sta $d020
jsr raster ; show raster
lda #$00
sta $d020 .. then everything is going crazy - due to overlapping raster lines.
I have also tried to put this in to multiple interrupts with this:int1
..mycode.. (raster+music)
lda #<int2
sta $0314
lda #>int2
sta $0315
jmp $ea81
int2
..mycode.. (scroll2x2)
lda #<int1
sta $0314
lda #>int1
sta $0315
lda #$ff
sta $d019 ; clear irq
jmp $ea81 .. but I am not sure I fully understand this as it still looks to be running sequentially to me (not correct irq routine probably?)? Isn't it just setting the IRQ addr to either one of the labels - it doesn't state when it should fire it off?
I hope I can get some hints to solve this - thanks a lot in advance. |
| |
ready.
Registered: Feb 2003 Posts: 441 |
try to avoid this:
lda #$7a
w1 cmp $d012
bne w1
instead use:
lda #$7a
w1 cmp $d012
bcs w1
since if you have a bad line you don't always see $d012 incrementing by one, but it increments by 2.
not sure this will help, but give it a try.
|
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
@ready - this actually helped... at least the music is playing normally and the scroll is moving on top of the rasterbar. The scroll is though now a hardscroll (not smooth) and the charset is the system charset but I suspect I am messing up the $d016 and $d018 registers(?).
OK, so to understand this, then BCS will continue if the carry flag is set... which means if it has surpassed the value? |
| |
ready.
Registered: Feb 2003 Posts: 441 |
glad it worked!
Subtraction:
x-y=z, carry=1 if y>x; carry=0 if y<=x
remeber how you did the subtraction in first grade, by hand? the carry works exactly like that!
example given:
carry 1
100-
98=
----
002
|
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
OK, I get it - this is also translated into (lda=x, cmp=y): lda #122
w1 cmp $d012 ($d012=#121)
bcs w1
(this one loops 2 times)
---
lda #122
w1 cmp $d012 ($d012=#122)
bcs w1
(this one loops 1 time)
---
lda #122
w1 cmp $d012 ($d012=#123)
bcs w1
(this one continues right away) OK, I get the idea, that I need to check for bad-lines also when polling $d012. |
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
Now I just solved this so everything is stable and looks good. The only thing I don't fully understand is the double-interrupt. Here is my code:int1
jsr raster ; starts at pos #$7a
lda #<int2
sta $0314
lda #>int2 ; start the
sta $0315 ; second IRQ
jmp $ea81
int2
jsr scroll2x2 ; awaits raster pos #$82
jsr $1003 ; play music afterwards
lda #<int1
sta $0314
lda #>int1
sta $0315
lda #$ff
sta $d019 ; clear our irq
jmp $ea81 1) Why shouldn't I clear the IRQ in "int1"?
2) Does this generates two IRQs or is it just running sequentially? I may be misunderstanding this.
3) Is this stable because of pure luck(!) or because I have moved the scroll and music into its own IRQ and thereby they get their own timing?
4) Can I have many more interrupts... fx. "int3" for a second scroll (if the timing mess up things having it in "int2")? |
| |
ready.
Registered: Feb 2003 Posts: 441 |
could you please post all your code for us to understand? What is "jsr raster" doing?
and I don't see why you shouldn't clear the IRQ flag in irq1. |
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
Full code here, http://cobrakid.dk/asm/mydmo2-asm.txt
When clearing the IRQ in "int1" I get into the same problems as in the beginning - everything goes 1/4 of the normal speed. |
| |
ready.
Registered: Feb 2003 Posts: 441 |
as far as I see you have a problem in rolltxt, the code seems to get stuck there.
Furthermore, I understand you want to have 2 IRQs per frame: one for the raster bars, one for setting the scroll. Thus each irq call should write the new irq entry raster for the next irq:
int1
jsr raster
lda #<int2
sta $0314
lda #>int2
sta $0315
lda #int2_irq_entry_point
sta $d012
lda #$01
sta $d019 ; clear our irq
jmp $ea81
int2
jsr scroll2x2
jsr musplay
lda #<int1
sta $0314
lda #>int1
sta $0315
lda #int1_irq_entry_point
sta $d012
lda #$01
sta $d019 ; clear our irq
and also #$01 is enough for $d019.
Bebug the code using VICE monitor, it helps a lot :)
|
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
I don't see it gets stuck in "rolltxt"? If you are referring to this:rolltxt lda scrtxt ; read next char
cmp #$00 ; stopchar? "@"
bne nextchar ; if not then jmp
lda #<scrtxt ; restart scroll
sta rolltxt+1
lda #>scrtxt
sta rolltxt+2
jmp rolltxt ; continue scroll
nextchar sta $0400+(10*40)+39
CUT.. This is just reinitializing the scrolltext in case of the stopchar has been reached. Or else please let me know what you mean.
Your code with the IRQ raster point makes perfectly good sense to me as it then would work in the same way as the initial "setup" IRQ. But... I cannot get it working. If I have your code I am back at the 1/4 speed problem. This is because of the "sta $d019" in "int1" - without it, it runs in the normal speed but then I cannot get the rasterbars stable. Please see this picture, http://cobrakid.dk/asm/mydmo3.png. There you can see there is a black line between the two yellow colors... there is no black line there in my colors so I don't see how I can tweak that with NOP or anything else?
The code which is not working:
http://cobrakid.dk/asm/mydmo3-asm.txt
Running with the initial code it works fine.
Debug in VICE? You mean reset and check memory? I guess it is not possible to do a trace frame-by-frame? |
| |
j0x
Registered: Mar 2004 Posts: 215 |
There *are* black lines (value 0) in your colours. In fact, every 8th colour is black.
There's also another problem:
You begin at raster line $7a, then make numcols=59 rastercolour lines, and then trigger the next IRQ at raster line $8a. Since, after drawing the raster colours, you've passed line $8a, this next IRQ won't trigger until the frame after, which is why your entire screen is flashing.
Once you get the individual routines to work together, you still have the job of getting the raster colour timing right, most notably synchronizing your "8,8,8,8,8,8,8,1" delay tables to your badlines.
I look forward to seeing the end result.
|
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
Ahhh, and the black line in the middle was because of the badline - got it.
OK, I now think I have got rid of the badline. As I understand it, this is only needed to be fixed once so I did it in the setup part where I added a 21 cycles delay (7 x "bit #$ff"). It is not pretty but it works.
Is this the correct way of dealing with the badline?
Furthermore I cannot get it working when having a "sta $d019" in the first interrupt (then it does the 1/4 of the speed). Am I doing something wrong? I know it works but this could still be pure luck?
See the source:
http://cobrakid.dk/asm/mydmo4-asm.txt
The next thing must be a 1x1 scroll but I assume this can fit in the "int2" section without too much problems. |
| |
TWW
Registered: Jul 2009 Posts: 545 |
Forget the bit $ffff's they do you no good.
You should study up on how your interrupt ruitine is buildt up and how it works. As it looks now it seems like a cut and paste garble from several different sources. You mix up methods on how to position the code vs. the raster.
If you are using the $d011/$d012 raster position to trigger an interrupt at some point, why begin with a polling loop (cmp $d012) in the middle of this? Secondly, you have to ack. a interrupt ($d019) if you wish it to become ready again.
As stated above, your raster routine spews out 59 raster lines which is too much, you only have 16 available before your next interrupt occurs ($7a-8a).
In your first post you said you wanted some rasters below a scroller so why bother splitting up with IRQ's in the first place.
what you need to do is:
#1: Determine where you want your scroller
#2: Make a single IRQ trigger on the rasterline you want your raster-collors to begin
#3: draw raster collors
#4: Scroll the scroll
#5: Play the music
#6: Set up for the next IRQ ($0314/0315) and ack.
then the VIC will tell the CPU when to begin all over again.
if this isn't clear enough, do this:
SEI
LDA #WhereTheFuckYouWantIt
STA $d012
BLABLABLA (this part is correct)
CLI
JMP *
irq:
DEC $d019
JSR Raster
JSR Scroller
JSR Music
LDA #WhereTheFuckYouWantIt
STA $d012
LDA #<irq
sta $0314
lda #>irq
sta $0315
jmp $ea81 |
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
Well, maybe I have not made this clear enough but I want the raster and scroller to be on top of eachother... naturally with the scroller in front (maybe that's why I said the raster should be "below" the scroller - I meant "behind" it).
So I do need the splitscreen and the "cmp $d012" to end it (as far as I know).
I do understand your method but I don't see how I can do this without having the two interrupts as I cannot draw it all in one go?
I will try your approach tomorrow but if you look at the web (which is how I learn + old tutorials) then you see sooo many different ways of doing this. Some says "sta $d019" other says "inc" or "dec" so it is not easy to know what exactly is the correct way of doing it. If you can recommend some good learning tutorials on interrupts I really want to read them. |
| |
Mr. SID
Registered: Jan 2003 Posts: 424 |
That's because there is no correct way. There are multiple possible solutions. You have to be able to substitute that on the fly.
inc $d019
dec $d019
asl $d019
etc.
all do the same thing, i.e. acknowledging the IRQ has been handled (otherwise it will trigger again immediately).
What you need to do is understand how the system works, before writing the code. For me, a piece of paper and a pencil is a useful tool to do that.
And then you need to get an idea how long your code is in raster lines. You need to measure that (with inc $d020/dec $d020) or count cycles, to understand what will happen if you execute that code at a specific line on the screen.
It's almost never possible to just copy/paste parts from different sources together. Use Codebase64 not as a code repository, but as a learning tool. |
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
If you have any good readings for me, then please let me know. What I have found so far is reference books (not very good ones), Ghouls Assembly Course (really good and in danish but doesn't cover the irq routine) and then too many different methods on the internet without proper explanation.
What I really would love to see is a good book that gets me from A-Z... or at least covers the basics like frames, cycles, irqs and badlines etc. This source I cannot find so I am doomed to read thousands of different methods out there and piece together that info into how I think it works.
So... please let me know of good reading materials - especially on the irq routine as I would like to get that right. |
| |
Frantic
Registered: Mar 2003 Posts: 1648 |
Maybe some of this would be helpful?
http://codebase64.org/doku.php?id=base:demo_coding_introduction
http://codebase64.org/doku.php?id=magazines:chacking3#rasters_-.. |
| |
ready.
Registered: Feb 2003 Posts: 441 |
this will help also:
http://unusedino.de/ec64/technical/aay/c64/
as a reference for hardware registers involved with IRQs |
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
@Frantic and ready - thanks for the links.
I have just tried doing the most simple piece of code - with two interrupts and flashing the border. There I can trigger the "sta $d019" so I must (naturally) be doing something wrong in my other part but I cannot see what.
What I still don't get is when something takes (for example) 50 raster lines (as seen with flashing $d020) and I need to place something else in that area (for example a scroll in front of a rasterbar)... how the h... is this done correctly with IRQ?
If you see this picture:
http://cobrakid.dk/asm/mydmo5.png
The yellow is the raster time for the rasterbar and the green is for the splitscreen for the scroll.
I cannot get this working in a way which I understand (currently I don't ACK the IRQ in my first interrupt - see previously posted code). I would appreciate some phseudo code or alike to get it right? |
| |
Oswald
Registered: Apr 2002 Posts: 5094 |
the problem is you dont have the basic understanding of what a(n raster) interrupt is, how the screen is drawn and how it is timed with the cpu, whats is drawn with the help of the cpu / gfx chip. You dont see the whole picture only some very small fragments of it.
for example, placing a scroller in front of a rasterbar is no problem, because you D O N ' T need any timing / raster irqs to do that. You simply set up the screen memory and the video chip will display the scroller, you dont need timed raster irqs to do that ! ! !
You have to start out with very basic stuff and experiment. Do the scroller / rasterbar individually first, understand them fully, then put them together, etc.
|
| |
ready.
Registered: Feb 2003 Posts: 441 |
for the effect you want, you need only 1 IRQ that triggers always at raster $70 (not #70!!! # means it's a number and not an address in assembly code, $ means it's hexadecimal).
So the steps you need are:
- enter IRQ at raster $70
- set screen x position ($d016 bits 0,1,2)
- change $d020/$d021 for raster bars until line $80+$16
- exit IRQ
then inside the background program (outside IRQ) you do the scrolling and prepare the screen position (written inside the IRQ to $d016). Don't do the scrolling in the IRQ. Now your background program is just "jmp *" |
| |
Oswald
Registered: Apr 2002 Posts: 5094 |
pseudocode for your Q:
raster irq starts:
-> setup X fine scroll
for x=0 to number of lines
get rastercolor: poke $d020, rastercolor: poke $d021, rastercolor
next x
-> reset X fine scroll to default value
-> redraw scroller
-> play music
raster irq stops. |
| |
Oswald
Registered: Apr 2002 Posts: 5094 |
Quote: for the effect you want, you need only 1 IRQ that triggers always at raster $70 (not #70!!! # means it's a number and not an address in assembly code, $ means it's hexadecimal).
So the steps you need are:
- enter IRQ at raster $70
- set screen x position ($d016 bits 0,1,2)
- change $d020/$d021 for raster bars until line $80+$16
- exit IRQ
then inside the background program (outside IRQ) you do the scrolling and prepare the screen position (written inside the IRQ to $d016). Don't do the scrolling in the IRQ. Now your background program is just "jmp *"
No. Do the scroller _IN_ the irq, after the rasterbars have been drawn. Some stuff are timing critical, some are not. Doing the scroller is not timing critical, but you have to do it once per frame exactly, so simply you execute it after having draw the rasters. |
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
But Oswald - how do I then setup the splitscreen? This splitscreen has to be within the rasterbar area!?
I do want a splitscreen as I am getting another 1x1 scroll or maybe some text in the top. |
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
@ready - THIS I get... of course... it is so simple. As I don't care for other characters in the rasterbar I just start the splitscreen the same time as the rasterbar starts... and end it afterwards.
That was simple (and I have fixed it). I need to tweak it for a badline but I know how to do that (hmmm.. my method with x number of "bit $ff").
Well, in my case the problem was not the technical part... hmmm OK, it was that too, but it was the "ahhhhhh" I got from seeing your phseudo code that solved it and I guess I am just not meant for being a programmer since I had a much more complex approach for doing this.
Thanks (all) for your help. I suspect I will write again some day (maybe sooner than I hope) :-)
BTW @ready - I do know the diff on #70 and $#70 ;-) It is completely diff positions (line 70 vs 112). |
| |
Cobrakid
Registered: Oct 2011 Posts: 23 |
Just a followup on this one - the code can be seen here, http://cobrakid.dk/asm/mydmo5-asm.txt. Maybe someone else can benefit from it.
I am not too proud of this one (in the start if the IRQ):; Prevent badline (by having
; bad code!? Hmmm...)
; This is the only(?) part
; which I do not fully
; understand - why cant this
; part be in the setup irq?
bit $ff ; 3 cycles
bit $ff ; 3 cycles
bit $ff ; 3 cycles
bit $ff ; 3 cycles
nop ; 2 cycles
nop ; 2 cycles It clearly states I am not in full control but I hope to get there - I need to study more and maybe even ask a few questions here yet. |
| |
tlr
Registered: Sep 2003 Posts: 1790 |
The irq always triggers when the raster counter changes. You cannot alter that by "setting up" the raster irq differently so if you need a different starting point in the raster line you have to add a delay like you do.
There are ways to do it more compact though. Consider jsr-ing directly to an rts for wasting 12 cycles for instance. |
| |
Stainless Steel
Registered: Mar 2003 Posts: 966 |
I'm really not an expert, but i took the liberty to modify your code a bit. how about this :
(ACME format. Rasterbar timingtable unfixed. Also this is is not the best way to do things but it works. Note for the wiseguys : yeah $d012 polling is slow and all but its an easier concept to grasp for beginners i think)
!TO "test.prg"
*=$0ffe
!BIN "tune.dat"
scrltxt = $5000
*= $4000
jsr $e544
sei
lda #$01
sta $d01a
lda #$7f
sta $dc0d
lda #<split1
sta $0314
lda #>split1
sta $0315
cli
ldx #$00
jsr $1000
jmp *
split1
lda #$00
cmp $d012
bne *-3
lda #$00
sta $d020
sta $d021
split2
lda #$7a
cmp $d012
bne *-3
lda #$15
sta $d018
lda smooth ; move the scroll
sta $d016 ; to the left dep.
; on the smooth-bit
jsr raster ; draw the rasterbar
split3
lda #$9d
cmp $d012
bne *-3
dec $d020 ;<- visualize rasterusage
jsr scroll2x2 ; print the
; scrolltext
inc $d020 ;<- visualize rasterusage
lda #$08 ; set normal
sta $d016 ; screen
split4
lda #$c0
cmp $d012
bne *-3
lda #$03
sta $d020
sta $d021
dec $d020 ;<- visualize rasterusage
jsr $1003
inc $d020 ;<- visualize rasterusage
inc $d019
jmp $ea31
; ======================================
scrspeed !byte $02 ; speed of scr.(1-8)
smooth !byte $07 ; smooth bit
half !byte $02
char !byte $00
scroll2x2
; ---------------------------
; Routine mostly from Ghouls
; Maskinkode Kursus as seen
; on CSDb (release id=8646)
; ---------------------------
lda smooth
sec
sbc scrspeed ; substract speed
and #$07 ; AND it with 7
; to get the
; smooth effect
sta smooth ; save the new
; smooth val
bcs quit ; quit the scroll
; if we dont need
; to update the
; screen
ldy #$00 ; black text color
ldx #$00
repeat1 lda $0401+(10*40),x ; move the
sta $0400+(10*40),x ; two lines
lda $0401+(11*40),x ; one to
sta $0400+(11*40),x ; the left
tya
sta $d800+(10*40),x ; set char
sta $d800+(11*40),x ; color
inx
cpx #39 ; move 39 chars
bne repeat1
; ---
; Only put a new char from the
; scrolltxt on the screen for
; every second frame/move
dec half
bne rolltxt ; jump to display
; a new char if
; we have ended
; the 2nd half of
; this char
lda #$02 ; reset the val
sta half ; that tells if
; this is the 2nd
; half of the
; char
lda char ; get the char
; that we are
; working on
ora #$40 ; shift it
sta $0400+(10*40)+39 ; and dis-
; play it
; on the
; 1st line
ora #$80 ; invert
sta $0400+(11*40)+39 ; it and
; display
; on 2nd
jmp quit
; ---
; Display a new char from the
; scrolltxt - it will only show
; the 1st half of the char
rolltxt lda scrltxt ; read next char
cmp #$00 ; stopchar? "@"
bne nextchar ; if not then jmp
lda #<scrltxt ; restart scroll
sta rolltxt+1
lda #>scrltxt
sta rolltxt+2
jmp rolltxt ; continue scroll
nextchar sta $0400+(10*40)+39 ; print
; the next char in the raster
; border (pos 39) on both lines
sta char ; set the working
; char
ora #$80 ; invert it
sta $0400+(11*40)+39
inc rolltxt+1 ; incr the scrtxt
; addr (low-byte)
bne quit
inc rolltxt+2 ; incr the scrtxt
; if it is longer
; than 256 bytes
quit rts ; return to my irq
; ======================================
raster
; Fine-tune raster position
; to avoid flickers
nop
nop
nop
nop
nop
ldx #0
loopcol lda colors,x
sta $d020
sta $d021
ldy delays,x
loopdel dey
bne loopdel
inx
cpx #numcols
bne loopcol
lda #$00
sta $d020
sta $d021
rts
; ----------------------------
indexcol !BYTE $00
numcols = 33
*= $5a00
colors
!BYTE $0a,$02,$0a,$0a,$0a,$07
!BYTE $0a,$00
!BYTE $07,$0a,$07,$07,$07,$0d
!BYTE $07,$00
!BYTE $0d,$07,$0d,$0d,$0d,$03
!BYTE $0d,$00
!BYTE $03,$0d,$03,$03,$03,$00
!BYTE $03,$00
!BYTE $00,$00,$00,$00,$00,$00
!BYTE $00,$00
!BYTE $00,$00,$00,$00,$00,$00
!BYTE $00,$00
!BYTE $01,$00,$00,$00,$00,$00
!BYTE $00,$00
!BYTE $00,$00,$01
*= $5b00
delays !BYTE $08,$08,$08,$08,$08,$08
!BYTE $08,$01
!BYTE $08,$08,$08,$08,$08,$08
!BYTE $08,$01
!BYTE $08,$08,$08,$08,$08,$08
!BYTE $08,$01
!BYTE $08,$08,$08,$08,$08,$08
!BYTE $08,$01
!BYTE $08,$08,$08,$08,$08,$08
!BYTE $08,$01
!BYTE $08,$08,$08,$08,$08,$08
!BYTE $08,$01
!BYTE $08,$08,$08,$08,$08,$08
!BYTE $08,$01
!BYTE $08,$08,$08
; ============================
scrolltext
*=$5000
!SCR "hi i am a scrolltext"
Oh yeah and you wont get the jitters away with this easily. Use delays where necessary to move them out of visual areas. |