| View previous topic :: View next topic |
| Author |
Message |
Master of C64


Joined: 22 Oct 2004 Age: 39 Posts: 1070 Location: Hixson, TN USA
|
Posted: Sat Nov 19, 2011 4:27 am Post subject: UGH! Double buffer driving me nuts! |
|
|
OK, so I am creating my scroller and for grins and giggles, I thought I would render the map to the SCRBUFFER (characters displayed) and then render to my DBLBUFFER (hidden buffer).
Once maps were rendered on both, I would then flip the two. Granted, nothing appears to happen at that point because both buffers are the same.
I am working on some scroll/copy code but wanted to get these two buffers rendered correctly and able to flip.
Here's the deal. I can render to SCRBUFFER *ONLY* and it looks great. OR, I can render to DBLBUFFER *ONLY* and it renders great. But if I render to BOTH, it shifts the entire screen over as you can see in the shots.
I have attached my entire folder if anyone cares to fire up KickAss and give it a look. Would love some input. I'm still learning the ins/outs of the VIC but I am pushing hard every day to get better.
Ignore the blue border, btw.
I am attempting to use $2000 for chars, $3800 for SCRBUFFER and $3C00 for DBLBUFFER.
However, when I change things around, it gets worse or crashes. Guess I'm too tired to figure out what I'm doing wrong. I appreciate any tips.
I guess I will start again in the AM.
Thanks.
(MAIN FILE IS IN SCROLL CALLED test01.asm)
http://dl.dropbox.com/u/471665/code.7z
PS, just for fun, here is my Ridley that uses four sprites:
 |
|
| Back to top |
|
 |
Forum Junkie

Joined: 17 Jun 2006 Posts: 525
|
Posted: Sat Nov 19, 2011 8:19 am Post subject: Re: UGH! Double buffer driving me nuts! |
|
|
| cbmeeks wrote: |
I have attached my entire folder if anyone cares to fire up KickAss and give it a look. Would love some input. I'm still learning the ins/outs of the VIC but I am pushing hard every day to get better.
|
In general it is a good idea to try to create the minimal repro case that shows your problem. Or at least mention where in the code you think the problem is. For example I'm looking at your code, is the problem in scroll\test01 or in goofs\scroll01?
Looking at your code...SetScreenAndCharLocation changes $d018. D018 should be set at the top of an IRQ, when you want to display the screen, not just prior to setting up data.
You do a LDA var/CMP #0. If you do a LDA you can immedaitely do a BEQ or BNE, you don't need to do a CMP #0. Saves a couple of cycles
lax (MAP_PTRH), y; personally I don't think it is a good idea to use undocumented opcodes. Why not just do ldx (MAP_PTRH),y? Ohh never mind I see thats zp.
DrawMap:
What is the initial lda/ldx for? If the first thing you do in the loop is lda and ldx?
So I don't really know what your problem is. BUT if the problem happens when you call DrawMap twice in a row, my suspicions are that you aren't initializing things properly. Like ColumnNumber and RowNumber and any other variables. You only set CURBUFFER_PTRH/L before calling DrawMap, and the other values are whatever they were before. _________________
|
|
| Back to top |
|
 |
Über Groupie


Joined: 20 Oct 2011 Age: 48 Posts: 342 Location: Netherlands
|
Posted: Sat Nov 19, 2011 10:33 am Post subject: |
|
|
Okay, what I think could be the cause is: you forget to initialize ColNumber and Rownumber. After the 1st call Rownumber is left at 12...
So the next time you use that var it starts at 12, then you inc it and it becomes 13. that is not equal to 12... so it will draw 256 rows before it wraps around and reaches 12 again.
Another thing:
You use a macro. By doing so you will actually generate the loop-code twice. If you use a subroutine, you will only get the screendraw code once:
| Code: |
:SetScreenAndCharLocation(SCRBUFFER, CHARSET)
lda #<SCRBUFFER
sta CURBUFFER_PTRH
lda #>SCRBUFFER
sta CURBUFFER_PTRL
jsr DrawMap
:SetScreenAndCharLocation(DBLBUFFER, CHARSET)
lda #<DBLBUFFER
sta CURBUFFER_PTRH
lda #>DBLBUFFER
sta CURBUFFER_PTRL
jsr DrawMap
.
.
.
// .macro DrawMap() {
DrawMap
lda #12 // so we can use dec and bne instead of inc and compare
sta RowNumber
lda #20 // so we can use dec and bne instead of inc and compare
sta ColNumber
draw:
lda #0
ldx #0
!loop:
ldy #0
lax (MAP_PTRH), y // X now contains tile number (from Map Data) $AF
lda TileCharLookupA, x // A now contains upper left char from tile
sta (CURBUFFER_PTRH), y // draw upper-left of tile
lda TileCharLookupB, x // A now contains upper-right char from tile
iny // instead of ldy #1
sta (CURBUFFER_PTRH), y // draw upper-right char from tile
lda TileCharLookupC, x // A now contains lower-left char from tile
ldy #40 // jump down to next line in screen buffer
sta (CURBUFFER_PTRH), y // draw lower-left char from tile
lda TileCharLookupD, x // A now contains lower-right char from tile
iny // instead of ldy #41
sta (CURBUFFER_PTRH), y // draw lower-right char from tile
lda CURBUFFER_PTRH // screen buffer
// you could do the dec ColNumber here, and depending on its
// outcome do an add with 2 and a jmp, or add 42 and dec
// column, depending on the outcome to prevent a double
// addition at the end of a row (add 2 then add 40).
// may gain a few cycles when speed is needed :-)
clc
adc #2 // add 2 to screen buffer (since our tiles are 2x2)
sta CURBUFFER_PTRH // update the screen buffer pointer
bcc *+4
inc CURBUFFER_PTRL
inc MAP_PTRH
dec ColumnNumber
bne !loop-
lda #20
sta ColumnNumber
lda CURBUFFER_PTRH
clc
adc #40
sta CURBUFFER_PTRH
bcc *+4
inc CURBUFFER_PTRL
dec RowNumber
bne draw
rts
//}
|
Disclaimer: I have no assembler/emulator at hand at the moment, so I can't verify/test and may be completely wrong!
Last edited by Mogwai on Sat Nov 19, 2011 9:55 pm; edited 1 time in total |
|
| Back to top |
|
 |
Master of C64


Joined: 22 Oct 2004 Age: 39 Posts: 1070 Location: Hixson, TN USA
|
Posted: Sat Nov 19, 2011 2:24 pm Post subject: |
|
|
Thanks guys! Both of you helped me out.
First of all, being really tired makes me do dumb things. lol. Working 10+ hours in Java and coming home to 6502 for 4-5 hours is tough sometimes. But the wife and kids were watching the new Twilight movie so I had time alone.
| THEWIZ wrote: | | In general it is a good idea to try to create the minimal repro case that shows your problem. |
Right, I generally try not to do a complete code dump but I was thinking that since I had chars, sprites, etc that it would be easier to give it all. Eventually, I'm going to do a real Github project and report tickets.
| THEWIZ wrote: | | Looking at your code...SetScreenAndCharLocation changes $d018. D018 should be set at the top of an IRQ, when you want to display the screen, not just prior to setting up data. |
Yep. That was an excellent point. I have removed that logic. What I'm doing now is setting a doublebuffer/flip routine at position 0 on every frame. So that I start the frame out with the doublebuffer and flip it next frame.
| THEWIZ wrote: | | You do a LDA var/CMP #0. If you do a LDA you can immedaitely do a BEQ or BNE, you don't need to do a CMP #0. Saves a couple of cycles |
AH! Yeah that's right. Thanks. I fixed that.
| THEWIZ wrote: | | lax (MAP_PTRH), y; personally I don't think it is a good idea to use undocumented opcodes. Why not just do ldx (MAP_PTRH),y? Ohh never mind I see thats zp. |
I remember seeing that opcode for the first time and thinking how it was really cool. But after reading more about them, I will probably get rid of it. I want my stuff to work on real hardware.
| THEWIZ wrote: |
DrawMap:
What is the initial lda/ldx for? If the first thing you do in the loop is lda and ldx?
|
The first lda wasn't needed so I removed it. The ldx was to start the initial position in my TileCharLookup tables so that I can grab the correct char out of the 2x2 tiles.
| THEWIZ wrote: |
So I don't really know what your problem is. BUT if the problem happens when you call DrawMap twice in a row, my suspicions are that you aren't initializing things properly. Like ColumnNumber and RowNumber and any other variables. You only set CURBUFFER_PTRH/L before calling DrawMap, and the other values are whatever they were before. |
That's a good point. I now reset the col/row number correctly.
| Mogwai wrote: | Okay, what I think could be the cause is: you forget to initialize ColNumber and Rownumber. After the 1st call Rownumber is left at 12...
So the next time you use that var it starts at 12, then you inc it and it becomes 13. that is not equal to 12... so it will draw 256 rows before it wraps around and reaches 12 again. |
Yeah, I can't believe I missed that. lol
| Mogwai wrote: |
Another thing:
You use a macro. By doing so you will actually generate the loop-code twice. If you use a subroutine, you will only get the screendraw code once:
|
Right on. That was dumb. Now my draw map is a subroutine. I guess I got too caught up in the ease of macros but I have to remember it duplicates code. So I am going to make sure macros are only for small things where a subroutine wouldn't make sense (like setting a background color).
Also, instead of drawing the map twice I simply draw it to the screen buffer first and do a simple copy to the doublebuffer on the setup.
Thanks guys. I now have a real doublebuffered map drawing routine that is properly flipping the buffers on each frame. Now on to the scroll like before.  |
|
| Back to top |
|
 |
Über Groupie


Joined: 20 Oct 2011 Age: 48 Posts: 342 Location: Netherlands
|
Posted: Sat Nov 19, 2011 9:53 pm Post subject: |
|
|
Good to hear that you're back to adding to the game!
Did you also notice my small optimizations and comments in the sourcecode I posted earlier? |
|
| Back to top |
|
 |
Forum Junkie

Joined: 17 Jun 2006 Posts: 525
|
Posted: Sun Nov 20, 2011 6:13 am Post subject: |
|
|
I think some people in the community have differing views on undocumented opcodes. My opinion is they should be avoided. If you want to write a demo that plays with them, fine. But if you are trying to write a game, stay away from them. Chances are you really won't be gaining much from using them, at the risk of having your code not run.
Macros, as you pointed out are great for small things. Like suppose you have a lot of LDA/STA combos. Or maybe setting the IRQ (you know LDA/STA $314/LDA/STA $315) but try not to use macros for things that a routine would be better off for. BUT also be mindful of the fact that a JSR/RTS take up 12 cycles. Sometimes it might be worth having the code duplicated to save the cycles.
Another point in posting code. Make sure the code you are posting exhibits the bug you are asking about. The code you posted had the bug commented out.
Have fun! _________________ |
|
| Back to top |
|
 |
Master of C64


Joined: 22 Oct 2004 Age: 39 Posts: 1070 Location: Hixson, TN USA
|
Posted: Tue Nov 22, 2011 1:07 am Post subject: |
|
|
OK, going insane again. Don't know what I'm doing wrong. But I've run into a problem calling my flip routine based on a counter. Basically, I don't want the screen to flip SCRBUFFER to DBLBUFFER every frame but instead, every 4th frame.
So here is what I have:
| Code: |
flipbuffer:
:BeginInterrupt()
lda FLIP_COUNTER
beq !start+
dec FLIP_COUNTER
jmp !exit+
!start:
lda #FLIP_BUF_COUNT
sta FLIP_COUNTER
....
|
FLIP_COUNTER is in ZP ($40). FLIP_BUF_COUNT is the number of frames I would like to happen before the flip takes place. Currently, I've set it to 200 just to really slow things down. But it runs at full speed. Flipping every frame. So basically, I should:
1) Load the value of FLIP_COUNTER into A
2) If 0, then start flip (and then RESET)
3) If not 0, then decrement FLIP_COUNTER and exit flip routine.
What am I doing wrong?
Thanks. |
|
| Back to top |
|
 |
Forum Junkie

Joined: 17 Jun 2006 Posts: 525
|
Posted: Tue Nov 22, 2011 4:11 am Post subject: |
|
|
It doesn't look like you've got anything wrong with the code.
But what does exit do? Does it exit the IRQ properly? That is you aren't immediately calling back into the IRQ are you?
By the way, you can rewrite the code:
dec FLIP_COUNTER
beq start
jmp exit
start
lda #flip_buf_count
sta flip_counter
Not that you'll need to store 5 into the counter to skip 4 times. _________________ |
|
| Back to top |
|
 |
Master of C64


Joined: 22 Oct 2004 Age: 39 Posts: 1070 Location: Hixson, TN USA
|
Posted: Wed Nov 23, 2011 1:55 am Post subject: |
|
|
| THEWIZ wrote: | But what does exit do? Does it exit the IRQ properly? That is you aren't immediately calling back into the IRQ are you?
|
Yeah, the exit properly returns from the IRQ. I use the same code elsewhere. I basically pull the registers back off the stack and return.
| THEWIZ wrote: |
By the way, you can rewrite the code:
dec FLIP_COUNTER
beq start
jmp exit
start
lda #flip_buf_count
sta flip_counter
Not that you'll need to store 5 into the counter to skip 4 times. |
Ah. Yeah. Dur. Thanks, that looks nicer.
BTW, I found the problem.
My FLIP_COUNTER used $42 in ZP. But I had another variable DBLBUFFER_PTRH that used $44 and DBLBUFFER_PTRL that used $45.
For some reason, it doesn't like that address. I change DBLBUFFER_PTRH/L to $46/$47 and it works! WTF?
Looking at Mapping the 64, it appears that I was using INPPTR and VARNAM from basic. But what would cause that problem? I verified that nothing else was using $44/$45 so I don't believe there should have been an overlap?
C64...what a strange beast she is.  |
|
| Back to top |
|
 |
Forum Junkie

Joined: 17 Jun 2006 Posts: 525
|
Posted: Wed Nov 23, 2011 5:36 am Post subject: |
|
|
Is this on a real 64? Can you verify the problem on VICE?
I wonder if you have some bad RAM? _________________ |
|
| Back to top |
|
 |
Über Groupie


Joined: 20 Oct 2011 Age: 48 Posts: 342 Location: Netherlands
|
Posted: Wed Nov 23, 2011 12:43 pm Post subject: |
|
|
| cbmeeks wrote: | BTW, I found the problem.
My FLIP_COUNTER used $42 in ZP. But I had another variable DBLBUFFER_PTRH that used $44 and DBLBUFFER_PTRL that used $45.
|
Shouldn't that be DBLBUFFER_PTRL in $44 and DBLBUFFER_PTRH in $45?
As long as you don't call BASIC rom code or have BASIC switched out, all those basic-related ZP locations are freely at your disposal, AFAIK. |
|
| Back to top |
|
 |
Master of C64


Joined: 22 Oct 2004 Age: 39 Posts: 1070 Location: Hixson, TN USA
|
Posted: Wed Nov 23, 2011 2:34 pm Post subject: |
|
|
@THEWIZ
This is VICE.
| Mogwai wrote: |
Shouldn't that be DBLBUFFER_PTRL in $44 and DBLBUFFER_PTRH in $45?
As long as you don't call BASIC rom code or have BASIC switched out, all those basic-related ZP locations are freely at your disposal, AFAIK. |
I tried doing that. Making ZP pointers LOW/HIGH and nothing worked. Not even my render code. So I believe pointers need to be in a HIGH/LOW arrangement? |
|
| Back to top |
|
 |
Über Groupie


Joined: 20 Oct 2011 Age: 48 Posts: 342 Location: Netherlands
|
Posted: Wed Nov 23, 2011 3:17 pm Post subject: |
|
|
Indirect indexed addressing works like this:
If $40 contains $06, $41 contains $04 and Y contains $50 then
LDA ($40),Y will access memory location $0456:
base address is
HIBYTE (from $41 = $04) LOBYTE (from $40 = $06) = $0406
Added to this is the contents of y ($50). That results in $0456.
Note that LDA($40,X) (or Indexed Indirect addressing)does a completely different thing. |
|
| Back to top |
|
 |
Master of C64


Joined: 22 Oct 2004 Age: 39 Posts: 1070 Location: Hixson, TN USA
|
Posted: Thu Nov 24, 2011 1:47 am Post subject: |
|
|
Thanks again.
I'm going to ask another question here and hopefully you (or someone else) might be so inclined to help everyone like me out. I'm having a hard time totally getting all of these addressing modes.
Thanks. |
|
| Back to top |
|
 |
Forum Junkie

Joined: 17 Jun 2006 Posts: 525
|
Posted: Thu Nov 24, 2011 8:47 am Post subject: |
|
|
| cbmeeks wrote: |
I tried doing that. Making ZP pointers LOW/HIGH and nothing worked. Not even my render code. So I believe pointers need to be in a HIGH/LOW arrangement? |
Addressing on the 64 is low byte/high byte. The low byte always comes first.
If you are having a problem using $44/$45 (I thought I saw a message where you solved the problem) then post some code, as it sounds like you are doing something wrong somewhere. _________________
|
|
| Back to top |
|
 |
Newbie

Joined: 27 Nov 2011 Age: 26 Posts: 10 Location: Corbin, KY
|
|
| Back to top |
|
 |
Master of C64


Joined: 22 Oct 2004 Age: 39 Posts: 1070 Location: Hixson, TN USA
|
Posted: Thu Dec 01, 2011 7:01 pm Post subject: Re: UGH! Double buffer driving me nuts! |
|
|
Thanks. Been pleased at what I've been able to copy with the limited colors of the C64. Kraid is looking good and should be able to get a pixel perfect (almost) copy of mother brain. 1/4 th done with her. Hi-res to boot. |
|
| Back to top |
|
 |
|