Jump to content
IGNORED

skipDraw and graphics


johnnywc

Recommended Posts

Hello all,

 

I've been working on a game and I'm using TJ's skipDraw routine to draw the player graphics. It's a great routine, but the one drawback is that all graphics have to be located in the upper portion of a page for the dcp to work correctly. This doesn't leave too much room for graphics (I need about 16 8x8 sprites). How do people get around this limitation (if I understand it correctly)? Is the only solution to store graphics in the upper portion of mulitple pages? I was hoping to have all my graphics on one page (so I would only have to store the lower byte for my graphics pointers) but I can't seem to figure a way around this.

 

Any help is greatly appreciated!

 

Thanks,

Link to comment
Share on other sites

I've been working on a game and I'm using TJ's skipDraw routine to draw the player graphics.  It's a great routine, but the one drawback is that all graphics have to be located in the upper portion of a page for the dcp to work correctly.

Not for the dcp to work correctly, but so that the 'lda (),Y' always takes 5 cycles (i.e., so it doesn't cross a page boundary). Has nothing to do with the 'dcp' opcode.

This doesn't leave too much room for graphics (I need about 16 8x8 sprites).  How do people get around this limitation (if I understand it correctly)?  Is the only solution to store graphics in the upper portion of mulitple pages?

Yup. In Go Fish! I had fish graphics spread across 5 pages.

 

Or you can use Manuel's FlipDraw routine, which AFAIK doesn't require any special alignment of your graphics data, other than that they can't cross page boundaries (I think).

Link to comment
Share on other sites

Hello all,

I've been working on a game and I'm using TJ's skipDraw routine to draw the player graphics.  It's a great routine, but the one drawback is that all graphics have to be located in the upper portion of a page for the dcp to work correctly.  This doesn't leave too much room for graphics (I need about 16 8x8 sprites).  How do people get around this limitation (if I understand it correctly)?  Is the only solution to store graphics in the upper portion of mulitple pages?  I was hoping to have all my graphics on one page (so I would only have to store the lower byte for my graphics pointers) but I can't seem to figure a way around this.

Any help is greatly appreciated!

Thanks,

927636[/snapback]

 

I'm not sure why you can't fit them in. Assuming you are using a 2 line kernel (96 lines), then you will have 256-96 bytes free. This leaves space for 20 8-pixel high sprites unless my math is wrong? Some other things to bear in mind:

  • You only need the full 96 byte offset if your sprites can appear right at the top of the screen. If some of your sprites are restricted to the bottom area of the screen, then you don't need such a large offset for them.
  • The colour data can be stored in a different page as it will be using another pointer.
  • If the sprites are similar, you might be able to overlap the sprite data.

Chris

Link to comment
Share on other sites

Not for the dcp to work correctly, but so that the 'lda (),Y' always takes 5 cycles (i.e., so it doesn't cross a page boundary).  Has nothing to do with the 'dcp' opcode.

 

Thanks for that info. I guess I never really understood why the graphics had to be in the upper region of a page. I always thought it was because the subtraction and carry being set, etc. Now it makes sense!

 

 

Or you can use Manuel's FlipDraw routine, which AFAIK doesn't require any special alignment of your graphics data, other than that they can't cross page boundaries (I think).

927663[/snapback]

Hmmm.. i'm not familiar with that routine - I'll check the Stella archives and see what it's all about.

 

Thanks!!

Link to comment
Share on other sites

I'm not sure why you can't fit them in.   Assuming you are using a 2 line kernel (96 lines), then you will have 256-96 bytes free.   This leaves space for 20 8-pixel high sprites unless my math is wrong?   Some other things to bear in mind:


  •  
     
  • You only need the full 96 byte offset if your sprites can appear right at the top of the screen.   If some of your sprites are restricted to the bottom area of the screen, then you don't need such a large offset for them.
     
     
  • The colour data can be stored in a different page as it will be using another pointer.
     
     
  • If the sprites are similar, you might be able to overlap the sprite data.
     
     

Chris

927694[/snapback]

 

Chris - thanks for enlightening me. This is my first 2600 program and I was doing it wrong. Even though i have a 2LK, I was stepping my scanlines down from 192 to 0 (in the Y register), decrementing Y on each scanline when I can simply step down from 96 to 0 and decrement Y every other scanline. I think originally I was experimenting with single line resolution in movement with 2L graphic resolution (hope that makes sense). By stepping Y from 192 to 0, I was cutting my graphics window in half. I really don't need the single line movement resolution so I can abandon that method.

 

Thanks for the tip!!

Edited by johnnywc
Link to comment
Share on other sites

Chris - thanks for enlightening me.  This is my first 2600 program and I was doing it wrong.  Even though i have a 2LK, I was stepping my scanlines down from 192 to 0 (in the Y register), decrementing Y on each scanline when I can simply step down from 96 to 0 and decrement Y every other scanline.  I think originally I was experimenting with single line resolution in movement with 2L graphic resolution (hope that makes sense).  By stepping Y from 192 to 0, I was cutting my graphics window in half.  I really don't need the single line movement resolution so I can abandon that method. 

Thanks for the tip!!

928168[/snapback]

 

I am glad to hear that you got it working. Note that the skipdraw routine won't work for a full screen 1LK as it can only take Y values up to 127. I will be interested to see what you are working on once it is done.

 

Chris

 

EDIT: D'oh - that should be SWITCHdraw and not SKIPdraw - I am always getting those names confused (though I always use switchdraw in my code).

Edited by cd-w
Link to comment
Share on other sites

I am glad to hear that you got it working.  Note that the skipdraw routine won't work for a full screen 1LK as it can only take Y values up to 127.  I will be interested to see what you are working on once it is done.

 

Chris

928177[/snapback]

:!: :!:

SwitchDraw only works with Y values < 128 - SkipDraw works with any Y value.

 

EDIT: Oh, and here are some links:

FlipDraw: http://atari2600.org/pipermail/stella/2005...ust/000169.html

SkipDraw: http://atari2600.org/pipermail/stella/2003...ber/004271.html (among others)

SwitchDraw: http://atari2600.org/pipermail/stella/2005...ary/000875.html and http://atari2600.org/pipermail/stella/2005...ary/000857.html

Edited by vdub_bobby
Link to comment
Share on other sites

I am glad to hear that you got it working.   Note that the skipdraw routine won't work for a full screen 1LK as it can only take Y values up to 127.   I will be interested to see what you are working on once it is done.

 

Chris

928177[/snapback]

:!: :!:

SwitchDraw only works with Y values < 128 - SkipDraw works with any Y value.

928207[/snapback]

Can someone explain to me the difference between Skipdraw and Switchdraw (in words not in code?). I may be able to sue switchdraw since my y values happen to be exactly betwee 0 and 127. :)

Link to comment
Share on other sites

Chris - thanks for enlightening me.  This is my first 2600 program and I was doing it wrong.  Even though i have a 2LK, I was stepping my scanlines down from 192 to 0 (in the Y register), decrementing Y on each scanline when I can simply step down from 96 to 0 and decrement Y every other scanline.  I think originally I was experimenting with single line resolution in movement with 2L graphic resolution (hope that makes sense).  By stepping Y from 192 to 0, I was cutting my graphics window in half.  I really don't need the single line movement resolution so I can abandon that method. 

Thanks for the tip!!

928168[/snapback]

 

I am glad to hear that you got it working. Note that the skipdraw routine won't work for a full screen 1LK as it can only take Y values up to 127. I will be interested to see what you are working on once it is done.

 

Chris

928177[/snapback]

 

Thanks for the help - I'm currently working on 2 projects. This first is Realsports Hockey (my first game), but the game is a bit too complicated for my first game (I'm still trying to figure stuff out like this) so I've switched gears to a rewrite of Wizard of Wor. I'm implementing intelligent flicker (the flicker in the original is horrendous) and hope to add more levels (like the Arena, Pit, Warlord levels), improve the sound (that monotone music could use some polyphony! :)), add a title screen and the in between intermissions (DOUBLE SCORE DUNGEON, etc). I'm using it more as an exercise but hope to finish it sooner than later. ;)

 

Thanks again!

Link to comment
Share on other sites

Can someone explain to me the difference between Skipdraw and Switchdraw (in words not in code?).  I may be able to sue switchdraw since my y values happen to be exactly betwee 0 and 127.  :)

I'm not sure exactly what you mean...

 

SwitchDraw.

Pros: faster and a little more flexible. Takes 15 cycles for single-colored sprite, 21 cycles for a multi-colored sprite. Also, the sprite's height can be variable.

Cons: only can use with Y values between 0 and 127. Don't save any RAM by having fixed-height sprites. Kind of a pain to setup the pointers and accompanying variables. Requires graphic data to be carefully placed in ROM.

 

SkipDraw:

Pros: takes a little (1 byte) less RAM. Can use with any Y value.

Cons: takes a little longer. Takes 17 cycles for a single-colored, fixed-height sprite. Takes 25 cycles for a multi-colored, fixed-height sprite. Add one cycle (and 1 byte RAM) for a variable-height sprite. Kind of a pain to setup the pointers and accompanying variables. Requires graphics data to be carefully placed in ROM.

 

FlipDraw:

Pros: Doesn't require a line counter. Easy pointer setup. Graphics data can be put anywhere in ROM; just can't cross page boundaries. Can use with any Y value.

Cons: Takes the longest. 20 cycles for single-colored, fixed-height sprite. 28 cycles for multi-colored, fixed-height sprite. Again, add 1 cycle (and 1 byte RAM) for variable-height sprites.

 

Note that all of these require branches outside your main kernel loop which then jump almost immediately back into your main kernel loop; these branches canNOT cross page boundaries because that would mess up the timing.

 

So, here is another method which doesn't require any branches in and out of your kernel loop.

I call it...DoDraw:

   lda #SPRITEHEIGHT
  dcp SpriteEnd
  bcs DoDraw
  lda #0
  .byte $2C
DoDraw
  lda (SpriteDataPtr),Y
  sta GRP0

Pros: No branches in and out of main kernel loop. Hits GRP0 every scanline (useful if you are using VDELxx).

Cons: Slower than everything except FlipDraw. Takes 18 cycles for fixed-height, single-color sprites. Add 1 cycle (and 1 byte RAM) for variable-height sprites. Requires somewhat major modifications to work with multi-color sprites.

Edited by vdub_bobby
Link to comment
Share on other sites

Here is a version of DoDraw for multi-colour sprites (untested):

 

  lda #SPRITEHEIGHT
  dcp SpriteEnd
  bcs DoDraw
  SLEEP 9
  lda #0
  beq EndDraw
DoDraw
  lda (SpriteColorPtr),Y
  sta COLUP0
  lda (SpriteDataPtr),Y
EndDraw
  sta GRP0

 

It takes 26 cycles though, so probably not what you want!

 

Chris

Edited by cd-w
Link to comment
Share on other sites

Pros: faster and a little more flexible.  Takes 15 cycles for single-colored sprite, 21 cycles for a multi-colored sprite.  Also, the sprite's height can be variable.

Cons: only can use with Y values between 0 and 127.  Don't save any RAM by having  fixed-height sprites.  Kind of a pain to setup the pointers and accompanying variables.  Requires graphic data to be carefully placed in ROM.

928232[/snapback]

 

IIRC, some of ET's graphics are stored with alternate scan lines in different pages of memory. I wonder if it's using something like Switchdraw twice in a 2lk, to yield single-line resolution on the non-ET sprite?

 

Also, another approach which is a bit RAM and ROM hungry but may at times be useful is to have the screen divided into 'zones' and keep track of what sprites belong in which zones. If the sprite shapes are separated by (zoneheight-1) blanks, there's no need to check whether a sprite should be displayed on any particular line. Just go ahead and do it regardless.

Link to comment
Share on other sites

FWIW: I use Flipdraw in the current batari Basic kernel due to its ease of pointer setup and flexibility in where the GFX data can go. In terms of ease of use, Flipdraw is a winner. In the case of bB, the compiler is responsible for putting the GFX data in the correct place, so with Flipdraw this is basically a non-issue.

 

Though in the future I will try to get a skip/switchdraw style kernel working, but efficient organization of graphics data is not exactly trivial...

Link to comment
Share on other sites

IIRC, some of ET's graphics are stored with alternate scan lines in different pages of memory.  I wonder if it's using something like Switchdraw twice in a 2lk, to yield single-line resolution on the non-ET sprite?

This is what I'm doing in my M-4 kernel to get single-line resolution on the sprites while using a 2LK. It definitely makes it a pain to change the sprite graphics. :)

Link to comment
Share on other sites

Hi there!

 

IIRC, some of ET's graphics are stored with alternate scan lines in different pages of memory.  I wonder if it's using something like Switchdraw twice in a 2lk, to yield single-line resolution on the non-ET sprite?

This is what I'm doing in my M-4 kernel to get single-line resolution on the sprites while using a 2LK. It definitely makes it a pain to change the sprite graphics. :)

 

You're definitely better off with Flipdraw for tasks like this, as it doesn't require a line counter. Just call it in both lines of a 2LK.

 

Greetings,

Manuel

Link to comment
Share on other sites

Hi there!

 

IIRC, some of ET's graphics are stored with alternate scan lines in different pages of memory.  I wonder if it's using something like Switchdraw twice in a 2lk, to yield single-line resolution on the non-ET sprite?

This is what I'm doing in my M-4 kernel to get single-line resolution on the sprites while using a 2LK. It definitely makes it a pain to change the sprite graphics. :)

 

You're definitely better off with Flipdraw for tasks like this, as it doesn't require a line counter. Just call it in both lines of a 2LK.

 

Greetings,

Manuel

930475[/snapback]

Yeah, but...calling SwitchDraw twice takes 30 cycles total. Calling FlipDraw twice takes 40. There is no way I could fit FlipDraw into the kernel.

 

EDIT: In the M-4 kernel I used a 2LK; in each 2-line section I draw the ball once, missile1 once, player1 twice, player0 4 times, and make four playfield (PF2) writes. Using FlipDraw for the sprite writes would take 120 of the available 152 cycles. There is just no way.

Edited by vdub_bobby
Link to comment
Share on other sites

Hi there!

 

Yeah, but...calling SwitchDraw twice takes 30 cycles total.  Calling FlipDraw twice takes 40.  There is no way I could fit FlipDraw into the kernel.

 

EDIT: In the M-4 kernel I used a 2LK; in each 2-line section I draw the ball once, missile1 once, player1 twice, player0 4 times, and make four playfield (PF2) writes.  Using FlipDraw for the sprite writes would take 120 of the available 152 cycles.  There is just no way.

 

You're right, it only makes sense for one sprite. (As in your 30/40 cycle example you don't take the additional overhead for securing the *right* Y content into account). I definitely wish I'd known about this technique earlier, it'd have done an amazing job for drawing the Crazy Balloon balloon ;)

 

Greetings,

Manuel

Link to comment
Share on other sites

Hi there!

 

(As in your 30/40 cycle example you don't take the additional overhead for securing the *right* Y content into account).
What do you mean by that?

 

Now, for switchdraw you need to have a proper line counter in Y, no?

 

Or in other words, for a 2LK with 1LK switchdraw sprites you need to handle 2 different line counters with some lsr/asl/tya/tay/temp/whatever overhead.

 

With FlipDraw you only need to take care of the 2LK counter, while the 1LK line counter is sorta selfcontained in the flipdraw method, requiring no additional overhead for a second counter.

 

Greetings,

Manuel

Link to comment
Share on other sites

(As in your 30/40 cycle example you don't take the additional overhead for securing the *right* Y content into account).
What do you mean by that?

 

Now, for switchdraw you need to have a proper line counter in Y, no?

 

Or in other words, for a 2LK with 1LK switchdraw sprites you need to handle 2 different line counters with some lsr/asl/tya/tay/temp/whatever overhead.

 

With FlipDraw you only need to take care of the 2LK counter, while the 1LK line counter is sorta selfcontained in the flipdraw method, requiring no additional overhead for a second counter.

Ok; thanks for the explanation; that makes sense.

 

However...in M-4 I just used one line counter; I just called SwitchDraw on each line but with a different pointer for each line. So, like supercat mentioned above, my graphics are in two different spots - the even lines in one table, the odd lines in another table.

 

Makes it a royal pain in the arse to edit the graphics.

 

EDIT: Plus it takes twice the RAM for pointers and twice the time/ROM to setup those pointers.

Edited by vdub_bobby
Link to comment
Share on other sites

Thanks for the help - I'm currently working on 2 projects.  This first is Realsports Hockey (my first game), but the game is a bit too complicated for my first game (I'm still trying to figure stuff out like this) so I've switched gears to a rewrite of Wizard of Wor.  I'm implementing intelligent flicker (the flicker in the original is horrendous) and hope to add more levels (like the Arena, Pit, Warlord levels), improve the sound (that monotone music could use some polyphony! :)), add a title screen and the in between intermissions (DOUBLE SCORE DUNGEON, etc).  I'm using it more as an exercise but hope to finish it sooner than later.  ;)

 

Thanks again!

928215[/snapback]

 

AtariVox for 1P mode??

Link to comment
Share on other sites

  • 16 years later...
On 9/9/2005 at 12:03 PM, cd-w said:

Here is a version of DoDraw for multi-colour sprites (untested):

 

 

  lda #SPRITEHEIGHT
  dcp SpriteEnd
  bcs DoDraw
  SLEEP 9
  lda #0
  beq EndDraw
DoDraw
  lda (SpriteColorPtr),Y
  sta COLUP0
  lda (SpriteDataPtr),Y
EndDraw
  sta GRP0
 

 

 

It takes 26 cycles though, so probably not what you want!

 

Chris

26 cycles is a dream to me. Fastest I can usually achieve is 34! Sometimes 32, other times 29.

Link to comment
Share on other sites

Here is my first example of drawing a sprite- Superdraw.

It takes 26 cycles.

The pros:

- Faster than most anything (Multicolor-wise)

- No Ytemp needed

- Multicolor sprites!

The cons:

- It can't handle a sprite on it's own, requires you to set the spriteheight (Or temporary value, a Temp byte works too) to a non 0 value before it works

- Requires a 0 at beginning of GFX data

 

Superdraw    ldy Spriteheight; 3
                    beq Endraw; 5
                    dey; 7
                     sty Spriteheight; 10


                      lda (P0col),y; 15
                      sta COLUP0; 18
Endraw            lda (P0ptr),y; 23

                       sta GRP0; 26

 

If you remove the code for color sprites you can get down to 18 cycles. So, if you wanted a color sprite and a non-color sprite, you can get a one-scanline kernal with 

32 cycles left do do your

DEX sta WSYNC bne Count

and trigger your counters.

Here's an easy method to trigger counters:

         cpx Ypos

         bne No

         lda ????? <--- do a variable or number here!

         sta Spriteheight

No     

 

This only takes 10 or 11 cycles. ( 11 for non-static, 10 for static height)

 

So, you could get a 1 scanline kernal with 2 static-height sprites with 5 cycles to spare, or 2 flexible height sprites with 3 cycles to spare with flexible-height sprites, assuming you have a color sprite and a non-color sprite.

This is best for a 2 scanline kernal as you get enough time to do 2 multicolor sprites and some extras (Asymetric PF1, Draw missiles, etc)

 

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...