+Propane13 Posted May 2, 2008 Share Posted May 2, 2008 Hi everybody, I thought this would be a good question to post in the newbie forum. I am aware of an algorithm that Joe Decuir wrote up "back in the day" (I believe for Combat), where you could take a value between say, 1 and 150, and based on that value, set RESP0 and HMP0 appropriately. However, if I remember right, this position algorithm happens during VBLANK. I need something like this to happen during the kernel. So, I'm looking for a routine that say... in 2-3 scanlines during the kernel does the calculations based on a horizontal position variable in Ram. Does anyone have any code like this that they would be willing to share? For new programmers, this is useful code for the case that you have multiple things going on in the kernel (say, at the top of the screen you use P0 for a score, at the middle, you use P0 as a character that can move left and right on the screen, and at the bottom of the screen, you have a "lives" counter). Regards, -John Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted May 2, 2008 Share Posted May 2, 2008 (edited) Here's my version, starting with horizontal position in A and sprite number (0 = P0, 1 = P1, 2 = M0, etc.) in X: sec sta HMCLR sta WSYNC DivideLoop sbc #15 bcs DivideLoop eor #7 asl asl asl asl sta.wx HMP0,X sta RESP0,X sta WSYNC sta HMOVE This will run in constant time, which is almost necessary for in-kernal use. Starting after the first STA WSYNC, it will end exactly 79 cycles later for all horizontal positions <= 160. Plus it's general, compact, and very easy to use. I've use this routine, or variations, in every 2600 program I've written. There is also a table version, something like this: sta WSYNC sec sta HMCLR DivideLoop sbc #15 bcs DivideLoop tay lda HMPxTable,Y;not crossing page boundary sta HMP0,X sta RESP0,X sta WSYNC sta HMOVE You have to set up the table carefully so that either you always cross a page boundary when you read it or so that you never do (since Y will hold -1 through -15). Just make sure that the STA RESP0,X instruction ends at cycle 23 when the BCS branch is not taken (i.e., the horizontal position < 15) for the timing to work. Edited May 2, 2008 by vdub_bobby Quote Link to comment Share on other sites More sharing options...
+Propane13 Posted May 5, 2008 Author Share Posted May 5, 2008 This code works perfectly, and is more efficient than I realized you could possibly get (I was expecting 3 scanlines, not less). Thank you for sharing! -John Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted May 5, 2008 Share Posted May 5, 2008 (edited) I used a variation of this in Stay Frosty so that Frosty's sprite and color could still be updated on scan lines that the fireballs were positioned on. There is a tradeoff, the X range is 4-147. The range can be expanded if only the sprite(and not the color) is updated, but for Stay Frosty it didn't matter as the platforms are only drawn using PF1 and PF2, so the fireballs couldn't travel that afar (well, they could on the bottom level). PosPlayer1: ; A holds X position for player 1 sec ; X holds GRP0 sta WSYNC; Y holds COLUP0 stx GRP0 ; 3 sty COLUP0; 3 6 DivideLoop1: sbc #15 ; 2 8 bcs DivideLoop1; 2 10 eor #7 ; 2 12 asl ; 2 14 asl ; 2 16 asl ; 2 18 asl ; 2 20 sta RESP1 ; 2 23 <- set object position sta HMP1 ; 3 26 sta WSYNC sta HMOVE rts Edited May 5, 2008 by SpiceWare Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted May 5, 2008 Share Posted May 5, 2008 Since you weren't using Y as a scanline counter - at least for that line - you could have saved a few cycles by using the table method I posted above (at the expense of a 15-byte table). Could have an X-range of 4-159. Of course, if you don't need the range, no point in changing what works. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted May 5, 2008 Share Posted May 5, 2008 I'll have to remember that for next time Quote Link to comment Share on other sites More sharing options...
Wickeycolumbus Posted May 25, 2008 Share Posted May 25, 2008 (edited) I still don't get this code. Can someone help me? I posted my code. processor 6502 include "vcs.h" include "macro.h" org $F000 START CLEAN_START lda #$FF sta GRP0 lda #$F0 sta COLUP0 STARTFRAME lda #0 sta VBLANK lda #2 sta VSYNC sta WSYNC sta WSYNC sta WSYNC lda #0 sta VSYNC ldy #37 ldx #0 lda #0 VERT sta WSYNC sec sta HMCLR sta WSYNC DivideLoop sbc #15 bcs DivideLoop eor #7 asl asl asl asl sta.wx HMP0,X sta RESP0,X sta WSYNC sta HMOVE dey bne VERT ldy #192 picture sta WSYNC dey bne picture ldy #30 over dey sta WSYNC bne over jmp STARTFRAME org $FFFA .word START .word START .word START Edited May 25, 2008 by Wickeycolumbus Quote Link to comment Share on other sites More sharing options...
supercat Posted May 25, 2008 Share Posted May 25, 2008 I used a variation of this in Stay Frosty so that Frosty's sprite and color could still be updated on scan lines that the fireballs were positioned on. One approach you could use if you want to 'do stuff' on scan lines where you perform horizontal positioning would be to execute different routines when the object to be places is near the right of the screen than when it's near the left; in the former scenario, you'll have time to do stuff after the RESPX; in the latter scenario you'll have time before. Two caveats with this approach: -1- You'll probably end up updating a sprite mid-line. Provided you have a choice of two times at least three cycles apart where the update can take place, this needn't pose a problem; simply use whichever one won't overlap the display of the sprite, and adjust the position up or down a scan line based upon whether your update happens before or after the sprite. -2- Although this approach could be used to maintain a full-width non-symmetric playfield (using non-reflected mode), hitting PF2 at the right cycle for using reflected mode would mean that certain sprite positions could not be reached with a single HMOVE. Still, the approach would offer the ability to offer some nice flexibility in a game with mid-frame horizontal repositioning. 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.