Avram Posted June 28, 2011 Share Posted June 28, 2011 Does this code look as if it should work during the vertical blank interrupt? I want to use the VBI time to cycle through some character animation and right now the x-register works but the y-register doesn't. The strange part is that if I separate the code and run it as it's own program then it works fine. I don't think it's necessary (though correct me if I'm wrong) to save the x, y, and accumulator on the stack, but I did to be safe. I also have some DLIs running too. My feeling is that somewhere in the main body of the code is a bug but, just in case I'm missing something obvious, I've posted it below. Thanks! Avram ;vbi routine *=$9000 pha txa pha tay pha dec vbi_timr ; vbi timer lda vbi_timr bne vbi_exit lda #10 sta vbi_timr ; reset timer ; begin main VBI routine ldy #16 ; number of chars to change, x8 ldx vbi_char cpx #80 bne char_anim ;character animate reset lda #0 sta vbi_char char_anim lda $7000,x ;read frame sta $6020,x ;copy to character set inx dey bne char_anim clc lda vbi_char adc #16 sta vbi_char vbi_exit pla tay pla tax pla jmp $E462 ;exit VBI ;vbi set-up vbi_test ldy #$0 ; lo-byte of vbi routine ldx #$90 ; hi-byte of vbi routine lda #7 ; deferred vector jsr $E45C ; go to SETVBV rts Quote Link to comment Share on other sites More sharing options...
Bryan Posted June 28, 2011 Share Posted June 28, 2011 (edited) So, this copies from $7000,x to $6020,x 16 times. This won't copy anything new, since the index is the same for source and destination. It will always copy: $7000->6020 $7001->6021 $7002->6022 ... $7050->6070 (80 decimal is 50 hex) ... ... and it will keep going until vbi_char=#80 on entry into the routine, doing 16 bytes per VBL. Don't you want to copy different information to the destination table each time? And oh wait, you do an exact compare with #80 but #80 isn't divisible by 16. maybe you mean #$80 (128). A quick way to test for 128 or more is to test for minus. I'd need to know more about the data being moved. And you're right, a deferred VBLANK routine doesn't need to push anything. If you're trying to update two characters at $6020 using 8 frames at $7000, then this is probably what you want: ; begin main VBI routine ldy #15 ; number of bytes to change -1 (two characters) ldx vbi_char ; get index into table bpl char_anim ; at the end of the table? ;character animate reset ldx #0 ; yes, reset index char_anim lda $7000,x ; read frame sta $6020,y ; copy to character set inx ; next byte to read dey ; write from offset 15 to 0 (copies upside down, though) bpl char_anim ; if Y wrapped from 0 to FF, we're done. stx vbi_char ; whatever X is, save it for next time Edited June 28, 2011 by Bryan Quote Link to comment Share on other sites More sharing options...
Avram Posted June 28, 2011 Author Share Posted June 28, 2011 (edited) Hi Brian I'm attempting to cycle through 4 different frames of two antic #4 characters (16 bytes per vbi visit) so it creates some simple animation. It could be I've bungled up the code but I think that using char_anim lets me jump around my data, so that I'm reading from $7000 + 0/16/32/48/64 (80 is the flag to reset back to zero and loop the animation). Avram *edit* Just saw your extra code there Bryan. I'll give that a shot and see how it works. Edited June 28, 2011 by Avram Quote Link to comment Share on other sites More sharing options...
Bryan Posted June 28, 2011 Share Posted June 28, 2011 (edited) Hi Brian I'm attempting to cycle through 4 different frames of two antic #4 characters (16 bytes per vbi visit) so it creates some simple animation. It could be I've bungled up the code but I think that using char_anim lets me jump around my data, so that I'm reading from $7000 + 0/16/32/48/64 (80 is the flag to reset back to zero and loop the animation). Avram *edit* Just saw your extra code there Bryan. I'll give that a shot and see how it works. Okay, 4 frames at $7000, $7010, $7020 and $7030 ($703F is the last byte used). Since vbi_char appears to be your X index storage place, we'll need to test it for $40(64) ; begin main VBI routine ldy #15 ; number of bytes to change -1 (two characters) ldx vbi_char ; get index into table cpx #64 ; are we at the end of the table bne char_anim ; nope, copy from current index ;character animate reset ldx #0 ; yes, reset index char_anim lda $7000,x ; read frame sta $6020,y ; copy to character set inx ; next byte to read dey ; write from offset 15 to 0 (copies data upside down, though) bpl char_anim ; if Y wrapped from 0 to FF, we're done. stx vbi_char ; whatever X is, save it for next time ; (due to the post-increment, X will be at the start of the next frame) Here's another take on it which reverses the frame order, but doesn't copy the data upside-down since X and Y are both decremented: ; begin main VBI routine ldy #15 ; number of bytes to change -1 (two characters) ldx vbi_char ; get index into table bne char_anim ; index is okay (not 0) ;character animate reset ldx #64 ; otherwise, reset index char_anim dex ; pre-decrement X lda $7000,x ; read frame sta $6020,y ; copy to character set dey ; write from offset 15 to 0 bpl char_anim ; if Y wrapped from 0 to FF, we're done. stx vbi_char ; whatever X is, save it for next time in both cases, vbi_char should be initialized to 0 at startup. Edited June 29, 2011 by Bryan Quote Link to comment Share on other sites More sharing options...
+Stephen Posted June 29, 2011 Share Posted June 29, 2011 Does this code look as if it should work during the vertical blank interrupt? I want to use the VBI time to cycle through some character animation and right now the x-register works but the y-register doesn't. The strange part is that if I separate the code and run it as it's own program then it works fine. I don't think it's necessary (though correct me if I'm wrong) to save the x, y, and accumulator on the stack, but I did to be safe. I also have some DLIs running too. My feeling is that somewhere in the main body of the code is a bug but, just in case I'm missing something obvious, I've posted it below. Thanks! Avram ;vbi routine *=$9000 pha txa pha tay ;THIS SHOULD BE TYA - the accumulator holds X at this point, and you then put that in y pha ;SNIP See the note above - you have a tay when you needed a tya. Quote Link to comment Share on other sites More sharing options...
Bryan Posted June 29, 2011 Share Posted June 29, 2011 That is a bug, but it shouldn't affect anything since he pushed and pulled 3 times and he's not required to save the registers anyway. The routine at $E462 (XITVBV) will restore the values saved by the OS. Quote Link to comment Share on other sites More sharing options...
Avram Posted June 29, 2011 Author Share Posted June 29, 2011 See the note above - you have a tay when you needed a tya. It wouldn't be my code if there weren't any stupid mistakes in it. Quote Link to comment Share on other sites More sharing options...
Avram Posted June 29, 2011 Author Share Posted June 29, 2011 Okay - the code works again. Bryan and Stephen - thanks so much for the corrections! Avram Quote Link to comment Share on other sites More sharing options...
Bryan Posted June 29, 2011 Share Posted June 29, 2011 (edited) See the note above - you have a tay when you needed a tya. It wouldn't be my code if there weren't any stupid mistakes in it. Cool, glad you got it working. It just takes a while to 'think' in 6502. After a while, you'll be building various structures from memory, and remembering all the little tricks. I wish I had more time for it nowadays. Edited June 29, 2011 by Bryan Quote Link to comment Share on other sites More sharing options...
Avram Posted June 29, 2011 Author Share Posted June 29, 2011 One more thing. I don't think I'll need to but if I have more than 256 bytes of character data to move is there an easy way to modify the routine to make it so? Quote Link to comment Share on other sites More sharing options...
Bryan Posted June 29, 2011 Share Posted June 29, 2011 (edited) One more thing. I don't think I'll need to but if I have more than 256 bytes of character data to move is there an easy way to modify the routine to make it so? Sure. Make more than one data table (one for the 1st char, and one for the 2nd) and do 8 passes through the loop rather than 16. This gives you twice the data with the same index range. Dividing your data into more and more separate tables can give you a lot of indexing ability with 8-bits. This method doubles the number of frames to 8 using the same maximum index (64) and an additional data table at $7040. ; begin main VBI routine ldy #7 ; number of bytes to change /2 -1 (two characters) ldx vbi_char ; get index into table cpx #64 ; are we at the end of the table bne char_anim ; nope, copy from current index ;character animate reset ldx #0 ; yes, reset index char_anim lda $7000,x ; read frame from table 1 sta $6020,y ; copy into character 1 lda $7040,x ; read frame from table 2 sta $6028,y ; copy into character 2 inx ; next byte to read dey ; write from offset 7 to 0 (copies data upside down, though) bpl char_anim ; if Y wrapped from 0 to FF, we're done. stx vbi_char ; whatever X is, save it for next time ; (due to the post-increment, X will be at the start of the next frame) Edited June 29, 2011 by Bryan Quote Link to comment Share on other sites More sharing options...
Avram Posted June 29, 2011 Author Share Posted June 29, 2011 Thanks again Bryan. It's especially elegant compared to what I had written. Avram Quote Link to comment Share on other sites More sharing options...
Bryan Posted June 29, 2011 Share Posted June 29, 2011 (edited) You're welcome. I've had situations where I separated a character sets into 8 tables, one for each byte. That way, I had a table of 256 byte 1's, 256 byte 2's etc... Then I could retrieve any of 256 characters with an index: ;X = the character to read ;$4000 is the destination character lda char_table0,x sta $4000 lda char_table1,x sta $4001 lda char_table2,x sta $4002 lda char_table3,x sta $4003 lda char_table4,x sta $4004 lda char_table5,x sta $4005 lda char_table6,x sta $4006 lda char_table7,x sta $4007 Here a simple technique to put one of 256 characters into one of 32 character set positions. Pick the destination char with Y (char_num*8 ): ;X = the character to read ;Y = destination char position ;$4000 is the first char position ldx source_char lda dest_char asl a asl a asl a ;*8 tay lda char_table0,x sta $4000,y lda char_table1,x sta $4001,y lda char_table2,x sta $4002,y lda char_table3,x sta $4003,y lda char_table4,x sta $4004,y lda char_table5,x sta $4005,y lda char_table6,x sta $4006,y lda char_table7,x sta $4007,y Of course, you can get much fancier with zero-page pointers. Edited June 29, 2011 by Bryan Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.