Jump to content
IGNORED

Am I going the right way with this?


Recommended Posts

Truthfully, the 32 pixel, 48 pixel and sprite-reuse are probably more advance that what a "Newbie" should be worried about.

 

I see where you're coming from, but I've sort of learned things out of order. I'm a newbie to the TIA but not 6502 assembly, and that is probably the most frustrating part! ;)

 

I'm working on a sprite demo right now and I have been playing with repositioning all morning and have had success doing exactly what you and others have described here. Next I'm going to try a 32 pixel mockup based on my current understanding. If I'm offbase, perhaps at that point you could review my source :)

Link to comment
Share on other sites

So, this is very odd. I've managed to get this to work, however I don't know how it works exactly. As you can see I have 4 unique sprites going on. I have set the NUSIZx to #%00000010 to allow 2 close copies. I've attached screenshots as well as source code.

 

I originally tried positioning using HMPx and HMOVE, however it would reposition both sets of sprites. From what I gather from SpiceWare's source example, we are trying to change the GRPx registers at exactly the right moment when we start drawing the second copy. Somehow my wasted cycles match up at '34' and '42'?

;-------------------------------------------------------------
;  3 part Kernel
;-------------------------------------------------------------   
            
            LDX     #90
Top         
            DEX
            STA     WSYNC
            BNE     Top


Layout            
            NOP                 ; 2 | 2
            NOP                 ; 2 | 4
            NOP                 ; 2 | 6
            NOP                 ; 2 | 8
            NOP                 ; 2 | 10
            NOP                 ; 2 | 12
            NOP                 ; 2 | 14
            NOP                 ; 2 | 16
            NOP                 ; 2 | 18
            NOP                 ; 2 | 20
            NOP                 ; 2 | 22
            NOP                 ; 2 | 24
            NOP                 ; 2 | 26
            NOP                 ; 2 | 28
            NOP                 ; 2 | 30
            NOP                 ; 2 | 32
            NOP                 ; 2 | 34
            
            STA     RESP0              
            STA     RESP1
            STA     WSYNC
            
            
            ; --- kernel ---
            LDY     #13
Kernel   
            LDA     SPRITE1,Y   ; 4 | 4     
            STA     GRP0        ; 3 | 7         
            LDA     SPRITE2,Y   ; 4 | 11
            STA     GRP1        ; 3 | 14
            LDA     SPRITE3,Y   ; 4 | 18
            TAX                 ; 2 | 20
            LDA     SPRITE4,Y   ; 4 | 24
            
            NOP                 ; 2 | 26
            NOP                 ; 2 | 28
            NOP                 ; 2 | 30
            NOP                 ; 2 | 32
            NOP                 ; 2 | 34
            NOP                 ; 2 | 36
            NOP                 ; 2 | 38
            NOP                 ; 2 | 40
            NOP                 ; 2 | 42
            
            STX     GRP0
            STA     GRP1
            DEY
            STA     WSYNC
            BNE     Kernel
            ; --- end ---
            
            
            ; quickly turn off the player
            LDA     #0
            STA     GRP0
            STA     WSYNC       ; kill 1 line
            STA     WSYNC       ; kill 2nd 

            
            LDX     #86
Bottom         
            DEX
            STA     WSYNC
            BNE     Bottom

post-36643-0-42206800-1394736363_thumb.png

post-36643-0-01457500-1394736364_thumb.png

Link to comment
Share on other sites

Upload your source file and the resulting BIN.

A minor tip. For labels, get in the habit of adding a :

Top:         
            DEX
            STA     WSYNC
            BNE     Top
 
 
Layout:            
            NOP                 ; 2 | 2
            NOP                 ; 2 | 4
...

When your programs get larger you'll be able to jump directly to the routine by finding "label:", whereas finding "label" can take a while because it will also show you every time you reference the label.

Link to comment
Share on other sites

Get familiar with Stella's debugger. Enter the debugger then type scanline 81 in the prompt. Hit RETURN, then switch to the TIA tab.

At this point repeatedly hit the STEP button in the upper right corner and watch what happens, instruction by instruction.

 

post-3056-0-96172500-1394743172_thumb.png

The white dot in the TIA Display (upper-left) is where the video been is currently at. Watch the updates to GRP0 and GRP1 (in the TIA tab) in relation to the movement of the white dot.

Edited by SpiceWare
Link to comment
Share on other sites

That is very useful. I've tried to compare notes from the details in this thread with the details in http://atariage.com/forums/topic/222918-horizontal-placement-multiple-sprites/

 

I've taken a stab at calculating the timing, but I must be missing a thing or two. Here's what I've come up with so far. Where you see "CC +n" is just the notation I came up with on the fly to assess how far to the right the NOPs in the "Layout" section move the players. I fine position HMP1 to get it to line up as well, but didn't add those clocks as I wasn't sure if that is part of the equation. I also didn't add the clocks for the indirect Y loads as I didn't know if that was a factor. Is there a simple equation when using this technique? Like +n color clocks, +n HMPx = 32 pixel sprites?

Layout       
           
            NOP                     ; 2 | 2
            NOP                     ; 2 | 4
            NOP                     ; 2 | 6
            NOP                     ; 2 | 8
            NOP                     ; 2 | 10
            NOP                     ; 2 | 12
            NOP                     ; 2 | 14
            NOP                     ; 2 | 16
            NOP                     ; 2 | 18
            NOP                     ; 2 | 20
            NOP                     ; 2 | 22 - HBLANK stops here
            NOP                     ; 2 | 24 | CC +6
            NOP                     ; 2 | 26 | CC +12
            NOP                     ; 2 | 28 | CC +18
            NOP                     ; 2 | 30 | CC +24
            NOP                     ; 2 | 32 | CC +30
            NOP                     ; 2 | 34 | CC +36
            NOP                     ; 2 | 36 | CC +42
            
            
            STA     RESP0           ; 3 | 39| CC +51 after written     
            STA     RESP1           ; 3 | 42| CC +60 after written
            
            STA     WSYNC

            
            LDA     #%00010000
            STA     HMP1
            STA     HMOVE                
            
            ; --- kernel 1 ---
            LDY     #13
Kernel   
            LDA     (SP2),Y  
            STA     GRP1          
            LDA     (SP1),Y  
            STA     GRP0      
            
            LDA     (SP3),Y        
            TAX                    
            LDA     (SP4),Y
            
            NOP                     ; 2 | 2 | CC +6     
            NOP                     ; 2 | 4 | CC +12
            NOP                     ; 2 | 6 | CC +18
            NOP                     ; 2 | 8 | CC +24
            NOP                     ; 2 | 10| CC +30
            NOP                     ; 2 | 12| CC +36

            STX     GRP0            ; 3 | 15| CC +44 after written               
            STA     GRP1            ; 3 | 18| CC +53 after written
            DEY
            STA     WSYNC
            BNE     Kernel
            ; --- end ---
Link to comment
Share on other sites

Your VSYNC is not good. You should start VSYNC following after a WSYNC otherwise the cycle it starts on is variable.

 

This is good:

;do three lines of VSYNC

    lda    #2
    sta    WSYNC   ; <-- use a WSYNC before VSYNC
;---------------------------------------
    sta    VSYNC   ; vsync starts
    lda    #0
    sta    WSYNC   ;1 scanline
    sta    WSYNC   ;2 scanlines
    sta    WSYNC   ;3 scanlines
;---------------------------------------
    sta    VSYNC   ; vsync ends...

.

.

But this is even better (saves bytes), if you are not doing anything inside those 3 scanlines. This is from Macro.h, and written by Edwin Blink.

    lda    #$0E
.loopVsync:
    sta    WSYNC
;---------------------------------------
    sta    VSYNC
    lsr
    bne    .loopVsync

.

.

You have probably noticed that I didn't touch VBLANK register in either routine. You've already wrote to the VBLANK register at the start of Overscan, and there is no need to update it here again. That's generally what I do too. I like to start VBLANK right after I draw the screen, and then stop VBLANK right before I start drawing the screen again.

Link to comment
Share on other sites

You should set HMP1 before you strobe WSYNC again, so you can strobe HMOVE right after WSYNC. In your code HMOVE is getting strobed too late, which will affect the number of pixels that you can shift the players left or right, as well as changing what each value represents (i.e., $10 won't represent "move the sprite left 1 pixel" as you are expecting). Also, setting HMP1 before strobing RESP0 and RESP1 will save a few bytes of ROM:

 

 

Layout
 
   NOP ; 2 | 2
   NOP ; 2 | 4
   NOP ; 2 | 6
   NOP ; 2 | 8
   NOP ; 2 | 10
   NOP ; 2 | 12
   NOP ; 2 | 14
   NOP ; 2 | 16
   NOP ; 2 | 18
   NOP ; 2 | 20
   NOP ; 2 | 22 - HBLANK stops here
   NOP ; 2 | 24 | CC +6
   NOP ; 2 | 26 | CC +12
   NOP ; 2 | 28 | CC +18
 
   LDA #%00010000 ; 2 | 30
   STA HMP1 ; 3 | 33
   STA HMP1 ; 3 | 36
 
   STA RESP0 ; 3 | 39 | CC +51 after written
   STA RESP1 ; 3 | 42 | CC +60 after written
 
   STA WSYNC ; 3 | 0
 
   STA HMOVE ; 3 | 3

Note that I used "STA HMP1" twice. That's just to waste 3 more cycles to keep the timing as desired. You could also use "NOP 0" which is a 2-byte, 3-cycle instruction-- but since "NOP 0" is technically a so-called "illegal" 6502 instruction, and takes exactly the same number of bytes and cycles as "STA HMP1," I decided to just write to HMP1 twice in a row since that's a "legal" instruction.

 

As for counting cycles, different programmers have their own formats of choice. The format I like to use would look something like the following:

 

 

Layout
 
   SLEEP 28  ; +28   ; 28
   LDA #$10  ; +02   ; 30
   STA HMP1  ; +03   ; 33
   STA HMP1  ; +03   ; 36
   STA RESP0 ; +03   ; 39 ; 117 ; 049 ; 054
   STA RESP1 ; +03   ; 42 ; 126 ; 058 ; 063
 
   STA WSYNC ; +03   ; 00
   STA HMOVE ; +03   ; 03

I use leading 0s to help keep the numbers lined up nicely in columns, depending on how large the values in a particular column can be-- 2 digits for machine cycles (maximum 76 per line), or 3 digits for color clocks (228 per line) or screen positions (160 per line).

The columns after the instructions are as follows:

- machine cycles used by the instruction, written with a plus sign since they add to the cycle count; the extra spaces are for asterisks where appropriate (e.g., for a branch instruction I would write +02** since a branch instruction uses 2 cycles if the branch is not taken, plus 1 more cycle if the branch is taken, plus 1 more cycle on top of that if the branch crosses a page boundary)

- the current running total of machine cycles used on the given scan line

- the current running total of color clocks elapsed on the given scan line (equal to the current machine cycles times 3)

- the current screen position on the given scan line (equal to the current color clock minus 68, written with a negative if it's within the HBLANK-- e.g., -68, or -04, or 007, or 029, or 159, etc.)

- the screen position where the sprite will appear if it isn't shifted left or right by HMOVE (equal to the current screen position plus 4 if the sprite is a missile or the ball, or plus 5 if the sprite is a player)

I omit any columns that aren't pertinent-- for instance, if all I need to know is what the running total of machine cycles happens to be, then I just give the cycles added by the instruction followed by the running total. But if the instruction is related to graphics and it would be helpful to know the corresponding screen position, then I include the current color clock and the current screen position. And if the instruction is resetting a sprite's position, I also include the column showing the sprite's new screen position after the reset instruction has completed.

You can simplify the appearance of your code if you use the SLEEP macro instead of writing a bunch of NOP instructions. The assembler will expand the SLEEP instruction into the appropriate number of NOP instructions, so it doesn't actually save you any ROM; but it does look more concise and is more convenient to code.

Another thing I like to do is put a blank line before I strobe WSYNC, since that can help make it more clear when reading the code where one scan line ends and another begins. But then I also sometimes like to insert blank lines to group related instructions together for increased legibility, as in the following example:

   LDA #1
   STA $80
 
   LDX #2
   STX $81
 
   LDY #3
   STY $82

But you should develop whatever format and style works best for you. :)

Link to comment
Share on other sites

Thanks a lot SeaGTGruff. That's a good practice and makes more sense than what I had going on.

I think everyone has done a great job explaining how horizontal placement and 32 \ 48 pixel sprites can be accomplished. And based on that, I'm sure I could get something to work if I tried enough combinations (like my sprite32p.bin example above)

 

But, I would really like to understand why it works. I've attempted to used SeaGTGruff's notation here to see if someone can explain the SLEEP portion, and why we are wasting cycles there to begin with:

Kernel:
    LDA (SP2),Y     ; +5  ; 5  
    STA GRP1        ; +3  ; 8
    LDA (SP1),Y     ; +5  ; 13
    STA GRP0        ; +3  ; 16
    LDA (SP3),Y     ; +5  ; 21
    TAX             ; +2  ; 23
    LDA (SP4),Y     ; +5  ; 28

    SLEEP 12        ; +12 ; 40 ; 120; 52; 57 <-- ???
 
    STX GRP0        ; +3  ; 43
    STA GRP1        ; +3  ; 47  
    DEY
    STA WSYNC
    BNE Kernel

So, the wasted SLEEP cycles between the write to SP4 and the write to GRP0 eludes me. It is 12 cyles, which puts our line MC count to 40, which puts our CC count to 120. If we subtract 68, this means that the color clock gap comes to 52.

 

Since we're not writing to RESPx, I didn't know if 52 + 5 should be notated, thus the question marks.

 

Ultimately, the goals seems to be to write to GRP0 at the exact moment that the beam reaches the first instance of GRP1. This would update the serial data right before the beam starts drawing the second copy of GRP0.

 

I've ran the Stella debugger, and watched the CC counter right when GRP0 is written to. It is at CC 129 when we write GRP0. If we subtract 68, this equals 61. Now, if we do add +5 to the delay above which is 52, that would equal 57.

 

Does this work because 61 and 57 are "close enough"?

 

 

ALSO:

I find it odd that the 48 pixel examples I've seen don't waste cycles between writes to GRPx. Is this because the horizontal positions aren't a factor because you are using VDELPx ?

Edited by johnnystarr
Link to comment
Share on other sites

I've been digging through the archives on this site, and I can only find topics related to 48 pixel sprites and not so much 32. Is this one of those tricks that has a technical / mathematical equation? Or is it simply a hack that you have to fine-tune until it works and there isn't an exact formula?

 

I've gotten it to work for me pretty well, but until I know why it's going to bug me! :)

 

Updated the .bin to that mean old dragon. Haven't begun to figure out the "red eye" trick though. I'm assuming it involves changing the COLUBK register on certain clocks.

sprite32p.bin

Link to comment
Share on other sites

Thanks a lot SeaGTGruff. That's a good practice and makes more sense than what I had going on.

I think everyone has done a great job explaining how horizontal placement and 32 \ 48 pixel sprites can be accomplished. And based on that, I'm sure I could get something to work if I tried enough combinations (like my sprite32p.bin example above)

 

But, I would really like to understand why it works. I've attempted to used SeaGTGruff's notation here to see if someone can explain the SLEEP portion, and why we are wasting cycles there to begin with:

Kernel:
    LDA (SP2),Y     ; +5  ; 5  
    STA GRP1        ; +3  ; 8
    LDA (SP1),Y     ; +5  ; 13
    STA GRP0        ; +3  ; 16
    LDA (SP3),Y     ; +5  ; 21
    TAX             ; +2  ; 23
    LDA (SP4),Y     ; +5  ; 28

    SLEEP 12        ; +12 ; 40 ; 120; 52; 57 <-- ???
 
    STX GRP0        ; +3  ; 43
    STA GRP1        ; +3  ; 47  
    DEY
    STA WSYNC
    BNE Kernel

So, the wasted SLEEP cycles between the write to SP4 and the write to GRP0 eludes me. It is 12 cyles, which puts our line MC count to 40, which puts our CC count to 120. If we subtract 68, this means that the color clock gap comes to 52.

 

Since we're not writing to RESPx, I didn't know if 52 + 5 should be notated, thus the question marks.

 

Ultimately, the goals seems to be to write to GRP0 at the exact moment that the beam reaches the first instance of GRP1. This would update the serial data right before the beam starts drawing the second copy of GRP0.

 

I've ran the Stella debugger, and watched the CC counter right when GRP0 is written to. It is at CC 129 when we write GRP0. If we subtract 68, this equals 61. Now, if we do add +5 to the delay above which is 52, that would equal 57.

 

Does this work because 61 and 57 are "close enough"?

 

 

ALSO:

I find it odd that the 48 pixel examples I've seen don't waste cycles between writes to GRPx. Is this because the horizontal positions aren't a factor because you are using VDELPx ?

 

Regarding the format used for counting cycles, use whatever you like or come up with your own style-- what matters is that it makes sense to you. I'm sure some programmers look at my style and say "WTF?" ;) Some people like a very simple, basic style-- and worrying about lining everything up with leading zeros or extra spaces, and/or showing the color clock and screen position counts, may not be worth the extra effort in cases where all you need is to keep a running total of the machine cycles.

 

In the SLEEP 12, there's no need to add 5 to the screen position-- that would be relevant only for a RESP0 or RESP1 instruction (or add 4 for a RESM0, RESM1, or RESBL instruction).

 

There are only two or three reasons I can think of why you'd ever want or need to waste cycles:

 

(1) In 2600 programming, timing can be very important because of the way registers are often updated in the middle of a scan line so as to squeeze the most out of the 2600's limited graphics abilities. (After all, if you had a dozen sprites, or a dozen color registers and fancy multicolor graphics mode at your disposal, there'd be no need to "recycle" any of the graphics registers by changing their values partway through a scan line.) So in order to make some change at just the right point on a scan line, you might need to waste some cycles so that a particular instruction can be executed at a specific cycle.

 

(2) Typically a kernel will be designed to use a loop for drawing one or maybe two scan lines during each pass through the loop. But since the 2600 is so slow-- each machine cycle corresponding to 3 color clocks, and only 76 machine cycles per scan line-- sometimes (or really, just about every time) you don't have quite enough cycles available to do all the things you want, so you have to start making compromises, or else find creative ways to shave off a cycle here and there so you have a little more time to do things. One of the ways that programmers might reclaim a few cycles is to get rid of the WSYNC command-- but since strobing WSYNC is the main way that you keep the instructions lined up nicely from line to line (e.g., so that a graphics change will always occur at a specific cycle on the line), getting rid of WSYNC means you might have to pad the loop so that it takes up exactly 76 cycles (including the cycles used by the comparison and branch instruction). You might even need to "unroll the loop," which means getting rid of the comparison and branch instruction, and drawing the scan lines one after another without using a loop, either for the entire screen or maybe for just a section of the screen.

 

(3) Another possible reason for wasting cycles (and bytes) might be if you have some code in ROM that you want to copy into RAM so you can execute it from RAM. This allows you to modify the code dynamically as the program is executing. This isn't nearly as common as the first two reasons, but it isn't unheard of. In such a case you might conceivably want to pad parts of the code so there's room to change the code as needed-- i.e., you might use filler code such as NOPs, or change the addressing mode used by some of the instructions, so that the code always occupies the same number of bytes in RAM, and/or executes in the same number of cycles, even though portions of the code are being modified as the program executes. Note that it's more common when you execute code from RAM to just change the operands, in which case there's no reason to pad the code by wasting bytes or cycles.

 

I haven't looked at the full code you've quoted from-- I assume this is from Dragonfire-- but in this case the cycles are being wasted for reason 1, to make sure the GRP0 and GRP1 registers get changed at just the right times. I'm not sure whether or not the VDELxx registers are being used for the dragon, but I'm guessing they aren't. That means GRP0 and GRP1 can be loaded much earlier on the scan line for the left half of the dragon (the first copy of player0 and the first copy of player1), but then the program needs to wait until it's safe to change GRP0 and GRP1 for the right half of the dragon, otherwise the graphics would change while the left half is still being drawn and the dragon wouldn't look right. There's a little bit of leeway for updating GRP0 and GRP1 for the right half of the dragon, since GRP0 can be updated any time while the first copy of player1 is being drawn, and then GRP1 can be updated any time while the second copy of player0 is being drawn. I assume the entry into the loop occurs on different cycles based on the position of the dragon, that way the same number of cycles can be wasted each time before updating GRP0 and GRP1 for the right half of the dragon.

 

As for the 48-pixel "score trick," it must be programmed differently than this example because it has more stringent requirements. The 6502/6507 has only 3 data registers-- A, X, and Y-- so that means if you preload them with the desired data then you can write their values to page 0 one after the other and it will take 9 cycles (3 cycles per write). Since 1 cycle equals 3 color clocks, the scanning beam moves 9 color clocks during each write. If you weren't using the VDELP0 and VDELP1 registers, you could preload GRP0 and GRP1 for the first copies of player0 and player1, then write to GRP0, GRP1, and GRP0 at just the right moment for the next 24 pixels. But then you'd need to load another value into A, X, or Y so you can update GRP1 again for the last 8 pixels, and there simply isn't enough time. But if you turn on VDELP0 and VDELP1, you can preload GRP0 twice, since there are really two copies of GRP0 and two copies of GRP1 inside the TIA-- an "old" register and a "new" register. Whenever you write to GRP0, the new data you've written doesn't get displayed until you write to GRP1, and vice versa-- the new data you write to GRP1 isn't displayed until you write to GRP0. So at some early point on the line, you write the first value to GRP0 (but it doesn't display yet), then write the next value to GRP1 (but it doesn't display yet, although it does cause the first value of GRP0 to be displayed), then you write another value to GRP0 (but it doesn't display yet, although it does cause the first value of GRP1 to be displayed). That means you've preloaded the first 3 sprites but only the first 2 have been displayed (by which I mean their graphics are "active," whether or not they've been drawn onscreen yet). Thus, you have only 3 more sprites left to worry about, so you can load up A, X, and Y, then quickly write to GRP1, GRP0, and GRP1 one after the other, causing the third, fourth, and fifth sprites to be displayed. To get the sixth sprite to display you must write to GRP0 one more time, but it doesn't matter what you write to it since the new data won't be displayed, it will merely trigger the data for the sixth sprite (copy 3 of player1) to be displayed.

 

If you're drawing a 40-pixel sprite (2 copies of one player positioned between 3 copies of the other player), or anything less than that-- 32 pixels, 24 pixels, or 16 pixels-- then you generally don't need to use VDELP0 and VDELP1, although they're sometimes used in other cases (apparently they were originally intended to be used in conjunction with "2-line kernels," but then some clever 2600 programmer came up with the idea for the "score trick").

 

As for "the red eye trick," I haven't looked at the code, but one thing that comes to mind is positioning the ball behind the dragon's head and setting COLUPF to red so the red ball can be seen through the eye hole.

Link to comment
Share on other sites

Updated the .bin to that mean old dragon. Haven't begun to figure out the "red eye" trick though. I'm assuming it involves changing the COLUBK register on certain clocks.

Use Stella's Debugger Mode + Fixed Debug Colors.

 

As for "the red eye trick," I haven't looked at the code, but one thing that comes to mind is positioning the ball behind the dragon's head and setting COLUPF to red so the red ball can be seen through the eye hole.

Yep, the eye's drawn using the ball. Difficult to see, so I changed the close-up section to use 4X zoom by right-clicking on it:

post-3056-0-05320300-1394839750_thumb.png

Link to comment
Share on other sites

I haven't looked at the full code you've quoted from-- I assume this is from Dragonfire...

 

The code was actually my own, however I updated it to SpiceWare's specifications earlier in this thread. That and I copied the dragon sprites from the Dragonfire source.

I think that I understand the 32p example a lot more now.

 

I spent the rest of the afternoon going over SpiceWare's sourcecode for Medieval Mayhem. I was actually able to modify my 32 pixel code and I've ALMOST got the 48 pixel code to work.

What I mean by almost is that I got it to work, all but the first graphic has a small "tear" at the bottom. Here's what I would like to know. I totally grasp the VDELPx method, and the pipeling

makes sense. I understand the delay in the 32 pixel example because you are basically synchronizing the writes between GRP0 and GRP1. But, all the 48p examples I've seen everywhere

all seem to have just about the same timing. I imagine that using indirect Y for each write has something to do with the time formula. Maybe you could take a look at the .bin and .asm for me

and help me determine what needs to be changed.

 

I've done my best to line up the sprite pairs and they seem to be lined up perfectly. I have attempted to modify the delay right before RESPx. If I reduce the "SLEEP" count just a bit, the tear

goes away, but the sprites aren't in order.

 

 

I feel like I'm 99% there, and have really enjoyed learning this stuff.

sprite48p.bin

sprite48p.asm

Link to comment
Share on other sites

What I mean by almost is that I got it to work, all but the first graphic has a small "tear" at the bottom.

 

You don't need to use EQU *-1 with your sprite labels. That is screwing up your pointers. Just do:

SPRITE1:
    .BYTE #%11111111
    .BYTE #%11111111
    .BYTE #%11011011
    .BYTE #%11011011
    .BYTE #%11011011
    .BYTE #%11011011
    .BYTE #%11011011
    .BYTE #%11011011
    .BYTE #%11000011
    .BYTE #%11000011
    .BYTE #%11011011
    .BYTE #%11011011
    .BYTE #%11100111
    .BYTE #%11111111
    .BYTE #%11111111
    .BYTE #%11111111
Link to comment
Share on other sites

Dude! That's awesome. I didn't realize that doing that would screw up the pointer. I had to reduce my loop by one to factor for the fact that it started at 0. I started using EQU *-1 some time back because

it made my loops easier to manage. Now I guess I need to understand the BigMove routine to see how it handles movement. Thanks for all the info, you guys have probably taught me in a week what would

have taken years!

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...