Jump to content
IGNORED

Fastest way to display missiles/ball (2600)


vdub_bobby

Recommended Posts

Redundancy?  It seems to me that if your sprite is #N lines, you could just execute a routine that produces #N lines.  The check is being done once before you need it, and no time is being wasted checking in lines that do need it.

I don't follow this exactly...could you explain a little further?

Link to comment
Share on other sites

Maybe if I understood it's use a bit clearer :lol:

 

You need:

To save cycles when dealing with variable heights.

 

Solution:

Write specific kernal portions dealing with each specific height.

 

Getting there via indirect jumps maybe?

 

Makes a lotta rom overhead, but it's one way of saving cycles.

Link to comment
Share on other sites

  

lda BallHeight

dcp BallY

rol

sta ENABL

 

maybe?

 

Greetings,

Manuel

Don't you need two 'rol's?

So are you using the carry bit to enable the ball? If you were able to use the Z status you could use the old Combat trick of pointing the stack to the ENABL register and php the status after the subtraction.

Link to comment
Share on other sites

Maybe if I understood it's use a bit clearer :lol:

 

You need:

To save cycles when dealing with variable heights.

 

Solution:

Write specific kernal portions dealing with each specific height.

 

Getting there via indirect jumps maybe?

 

Makes a lotta rom overhead, but it's one way of saving cycles.

I think we are talking past each other :)

 

I need to draw the ball like you normally draw a player - it can show up on any scanline and can be any height. I.e., I am drawing a line (not a point, so I can't do what DEBRO suggested, 'cpy BallY php' - at least I haven't figured out a way to do it). I am drawing a vertical line that can be of variable length (varying between 1 and ~8 scanlines tall) and it can appear anywhere on the screen.

 

Some other possibilities I have come up with are the code cybergoth suggested (15 cycles) and, if I can restrict my variable heights to intervals of four, this:

lda BallHeight

dcp BallY

sbc #ADJUSTER

sta ENABL    ;+13

Where, for example, if BallHeight = 0, 3, 7, 11, etc. then ADJUSTER = 0.

 

And I don't have time to do jumps, indirect or otherwise :), in my kernel. This is specifically for the Prince of Persia kernel I am messing around with where I am drawing an asymmetrical PF every scanline and the ball and both players every other scanline; I have zero extra cycles in my kernel right now. As far as I know, the SkipDraw routine is the fastest way to draw a sprite (assuming you need constant cycles and without giant tables as tall as the screen) anyone has come up with, but I haven't ever read anything about the fastest way to draw a ball/missile when it is taller than one scanline.

Link to comment
Share on other sites

I knew I didn't describe that well enough ;)

What I was trying to describe is unrolling a display loop. You no longer would need to CPY and such because that specific kernal already "knows" the height and already has the ball sprite enabled. You save cycle time because no loop is used and no tests are needed. The indirect jump I was referring to happens on the scanlines above the player (where you have the time to do the test, because the sprites aren't being drawn there).

 

Could you post the attempted routine for your "draw player+sword" loop (the one that's using too many cycles)?

Link to comment
Share on other sites

Is there a faster way to display a variable-height ball/missile in the 2600 than this:
  lda BallHeight

 dcp BallY

 sbc BallHeight

 sta ENABL    ;+14

Clever code!

 

Hm, I did something like this in Cave1K:

  tya                    

 sbc     yWall1        

 adc     hWall1       

 lda     #$00         

 adc     #$01        

 sta     ENABL  ; = 15   

But your code is faster.

Link to comment
Share on other sites

I knew I didn't describe that well enough ;)

What I was trying to describe is unrolling a display loop.  You no longer would need to CPY and such because that specific kernal already "knows" the height and already has the ball sprite enabled.  You save cycle time because no loop is used and no tests are needed.  The indirect jump I was referring to happens on the scanlines above the player (where you have the time to do the test, because the sprites aren't being drawn there).

 

Could you post the attempted routine for your "draw player+sword" loop (the one that's using too many cycles)?

Well, it isn't taking too many cycles now...but if I could cut a few cycles off I could maybe squeeze one of the missiles into the loop somewhere.

So here's the code.

Actually, I'm not currently using the 'fastest' routine I posted above, I'm using the one Cybergoth suggested.

   sta WSYNC

  nop

  

  ldy #PLAYAREAHEIGHT-1  ;+2    4

  ldx #PLAYAREAHEIGHT-2  ;+2    6



  lda (PFColorPtr),Y

  sta COLUPF             ;+8   14

  

  SLEEP 5



  lda (PF1Ptr),Y

  sta PF1                ;+8   27

  lda (PF2Ptr),Y

  sta PF2                ;+8   35



  dec SwordYPosition     ;+5   40



PlayAreaLoop

  lda (PF3Ptr),Y

  sta PF2                ;+8   48

  lda (PF4Ptr),Y

  sta PF1                ;+8   56



  lda #P1HEIGHT-1        ;+2   58

  dcp P1YPosition        ;+5   63

  bcs DoDraw2            ;+2/3 65/66

  lda #0                 ;+2   67

  .byte $2C              ;-1   66

DoDraw2

  lda (PlayerPtrR),Y     ;+5   71

  sta GRP1               ;+3   74



  lda (Player2ColorPtr),Y

  sta COLUP1             ;+8    6





  lda SwordHeight

  cmp SwordYPosition

  rol

  rol

  sta ENABL              ;+13   19





  lda (PF1Ptr),Y

  sta PF1                ;+8   27

  lda (PF2Ptr),Y

  sta PF2                ;+8   35

  dec SwordYPosition     ;+5   40

  lda (PF3Ptr),Y

  sta PF2                ;+8   48

  lda (PF4Ptr),Y

  sta PF1                ;+8   56





  lda #P0HEIGHT-1        ;+2   58

  dcp P0YPosition        ;+5   63

  bcs DoDraw1            ;+2/3 65/66

  lda #0                 ;+2   67

  .byte $2C              ;-1   66

DoDraw1

  lda (PlayerPtrL),Y     ;+5   71

  sta GRP0               ;+3   74

  dey

  sta HMOVE              ;+3    3

  

  lda (PlayerColorPtr),Y ;+5

  sta COLUP0             ;+3   11



  lda (PFColorPtr),Y

  sta COLUPF             ;+8   19



  lda (PF1Ptr),Y

  sta PF1                ;+8   27

  lda (PF2Ptr),Y

  sta PF2                ;+8   35

  dex

  bpl PlayAreaLoop       ;+4/5 40

Link to comment
Share on other sites

Maybe it's time to share my code too? ;)

.skipDraw1:                ; 5         @30

   sec                    ; 2

   sbc     yP0            ; 3

   adc     #PLAYER_H      ; 2 =  7



   SLEEP   4              ; 4 =  4



   lda     pf2RLst0,x     ; 4

   sta     PF2            ; 3         @48 *!*

   lda     pf1RLst0,x     ; 4

   sta     PF1            ; 3 = 14    @55



   SLEEP   6              ; 6 =  6



   lda     #0             ; 2

   sta     GRP1           ; 3

   sta     ENAM1          ; 3         @69

   bcs     .contDraw1a    ; 2³= 10/11

   bcc     .skipDraw0a    ; 3



.skipDraw0:                ;10         @60

   lda     (ptrC1),y      ; 5

   sta.w   COLUP1         ; 4         @69

   adc     #$fc           ; 2

   sta     ENAM1          ; 3 = 13    @74

.skipDraw0a:

   sec                    ; 2
;---------------------------------------

   sta.w   HMOVE          ; 3         @04

   lda     #0             ; 2

   sta     GRP0           ; 3

   beq     .contDraw0     ; 3         @12



.nextRow:

   SLEEP   4              ; 4 =  4

.nextBlock:                ;           @63

   sbc     yP1            ; 3

   adc     #ENEMY_H       ; 2 =  5



   lda     colLst0,x      ; 4

   sta     COLUPF         ; 3 =  7    @75
;---------------------------------------

   SLEEP   12             ;12                     12 free cycles



   lda     pf1LLst0,x     ; 4

   sta     PF1            ; 3         @18

   lda     pf2LLst0,x     ; 4

   sta     PF2            ; 3 = 14    @25



   tya                    ; 2

   bcc     .skipDraw1     ; 2³=  4/5



   sbc     yP0            ; 3

   adc     #PLAYER_H      ; 2 =  5



   lda     pf1RLst0,x     ; 4

   sta     PF1            ; 3         @41

   lda     pf2RLst0,x     ; 4

   sta     PF2            ; 3 = 14    @48 *!*



   lda     (ptrP1),y      ; 5

   sta.w   GRP1           ; 4 =  9    @VDEL!      1 cycle to optimize!



   bcc     .skipDraw0     ; 2³=  9/10



   lda     (ptrC1),y      ; 5

   sta     COLUP1         ; 3         @67         >=@70!

   adc     #$fc           ; 2

   sta     ENAM1          ; 3 = 13    @72         >=@70!

.contDraw1a:



   lda     (ptrP0),y      ; 5 =  5
;---------------------------------------

   sta     HMOVE          ; 3         @04

   sta     GRP0           ; 3         @07

   lda     (ptrC0),y      ; 5 = 11

.contDraw0:                ;           @12

   sta     COLUP0         ; 3         @15

   adc     #$fc           ; 2

   sta     ENAM0          ; 3 =  8    @20



   lda     pf1LLst0,x     ; 4

   sta     PF1            ; 3         @27

   lda     pf2LLst0,x     ; 4

   sta     PF2            ; 3         @34

   lda     pf1RLst0,x     ; 4

   sta     PF1            ; 3         @41

   lda     pf2RLst0,x     ; 4

   sta     PF2            ; 3 = 28    @48 *!*



   dey                    ; 2

   tya                    ; 2

   cmp     BlockTbl,x     ; 4

   bne     .nextRow       ; 2³

   dex                    ; 2

   bpl     .nextBlock     ; 2³= 15

Link to comment
Share on other sites

Actually, I'm not currently using the 'fastest' routine I posted above, I'm using the one Cybergoth suggested.

 

Thanks for posting it. This is an example of redundancy below. Notice how the loop is no longer a loop...but just a string of code. What this does is free 5 cycles from the bottom of each group, in addition to freeing up the X register (so you should be able to come up with a better use for it). I didn't look at the variables too closely, but eliminating the compare in each group will also be possible now that the X register is free to use.

 

 

   sta WSYNC

  nop

  

  ldy #PLAYAREAHEIGHT-1  ;+2    4

  ldx #PLAYAREAHEIGHT-2  ;+2    6



  lda (PFColorPtr),Y

  sta COLUPF             ;+8   14

  

  SLEEP 5



  lda (PF1Ptr),Y

  sta PF1                ;+8   27

  lda (PF2Ptr),Y

  sta PF2                ;+8   35



  dec SwordYPosition     ;+5   40


;changes begin here...
;PlayAreaLoop ... label not needed

  lda (PF3Ptr),Y

  sta PF2                ;+8   48

  lda (PF4Ptr),Y

  sta PF1                ;+8   56



  lda #P1HEIGHT-1        ;+2   58

  dcp P1YPosition        ;+5   63

  bcs DoDraw2_1          ;+2/3 65/66

  lda #0                 ;+2   67

  .byte $2C              ;-1   66

DoDraw2_1

  lda (PlayerPtrR),Y     ;+5   71

  sta GRP1               ;+3   74



  lda (Player2ColorPtr),Y

  sta COLUP1             ;+8    6





  lda SwordHeight

  cmp SwordYPosition

  rol

  rol

  sta ENABL              ;+13   19





  lda (PF1Ptr),Y

  sta PF1                ;+8   27

  lda (PF2Ptr),Y

  sta PF2                ;+8   35

  dec SwordYPosition     ;+5   40

  lda (PF3Ptr),Y

  sta PF2                ;+8   48

  lda (PF4Ptr),Y

  sta PF1                ;+8   56





  lda #P0HEIGHT-1        ;+2   58

  dcp P0YPosition        ;+5   63

  bcs DoDraw1_1          ;+2/3 65/66

  lda #0                 ;+2   67

  .byte $2C              ;-1   66

DoDraw1_1

  lda (PlayerPtrL),Y     ;+5   71

  sta GRP0               ;+3   74

  dey

  sta HMOVE              ;+3    3

  

  lda (PlayerColorPtr),Y ;+5

  sta COLUP0             ;+3   11



  lda (PFColorPtr),Y

  sta COLUPF             ;+8   19



  lda (PF1Ptr),Y

  sta PF1                ;+8   27

  lda (PF2Ptr),Y

  sta PF2                ;+8   35

  NOP   ;2 free

  STA    $2D;3 free      40






;next group

  lda (PF3Ptr),Y

  sta PF2                ;+8   48

  lda (PF4Ptr),Y

  sta PF1                ;+8   56



  lda #P1HEIGHT-1        ;+2   58

  dcp P1YPosition        ;+5   63

  bcs DoDraw2_2          ;+2/3 65/66

  lda #0                 ;+2   67

  .byte $2C              ;-1   66

DoDraw2_2

  lda (PlayerPtrR),Y     ;+5   71

  sta GRP1               ;+3   74



  lda (Player2ColorPtr),Y

  sta COLUP1             ;+8    6





  lda SwordHeight

  cmp SwordYPosition

  rol

  rol

  sta ENABL              ;+13   19





  lda (PF1Ptr),Y

  sta PF1                ;+8   27

  lda (PF2Ptr),Y

  sta PF2                ;+8   35

  dec SwordYPosition     ;+5   40

  lda (PF3Ptr),Y

  sta PF2                ;+8   48

  lda (PF4Ptr),Y

  sta PF1                ;+8   56





  lda #P0HEIGHT-1        ;+2   58

  dcp P0YPosition        ;+5   63

  bcs DoDraw1_2          ;+2/3 65/66

  lda #0                 ;+2   67

  .byte $2C              ;-1   66

DoDraw1_2

  lda (PlayerPtrL),Y     ;+5   71

  sta GRP0               ;+3   74

  dey

  sta HMOVE              ;+3    3

  

  lda (PlayerColorPtr),Y ;+5

  sta COLUP0             ;+3   11



  lda (PFColorPtr),Y

  sta COLUPF             ;+8   19



  lda (PF1Ptr),Y

  sta PF1                ;+8   27

  lda (PF2Ptr),Y

  sta PF2                ;+8   35

  NOP   ;2 free

  STA    $2D;3 free      40






;next group



  lda (PF3Ptr),Y

  sta PF2                ;+8   48

  lda (PF4Ptr),Y

  sta PF1                ;+8   56



  lda #P1HEIGHT-1        ;+2   58

  dcp P1YPosition        ;+5   63

  bcs DoDraw2_3          ;+2/3 65/66

  lda #0                 ;+2   67

  .byte $2C              ;-1   66

DoDraw2_3

  lda (PlayerPtrR),Y     ;+5   71

  sta GRP1               ;+3   74



  lda (Player2ColorPtr),Y

  sta COLUP1             ;+8    6





  lda SwordHeight

  cmp SwordYPosition

  rol

  rol

  sta ENABL              ;+13   19





  lda (PF1Ptr),Y

  sta PF1                ;+8   27

  lda (PF2Ptr),Y

  sta PF2                ;+8   35

  dec SwordYPosition     ;+5   40

  lda (PF3Ptr),Y

  sta PF2                ;+8   48

  lda (PF4Ptr),Y

  sta PF1                ;+8   56





  lda #P0HEIGHT-1        ;+2   58

  dcp P0YPosition        ;+5   63

  bcs DoDraw1_3          ;+2/3 65/66

  lda #0                 ;+2   67

  .byte $2C              ;-1   66

DoDraw1_3

  lda (PlayerPtrL),Y     ;+5   71

  sta GRP0               ;+3   74

  dey

  sta HMOVE              ;+3    3

  

  lda (PlayerColorPtr),Y ;+5

  sta COLUP0             ;+3   11



  lda (PFColorPtr),Y

  sta COLUPF             ;+8   19



  lda (PF1Ptr),Y

  sta PF1                ;+8   27

  lda (PF2Ptr),Y

  sta PF2                ;+8   35

  NOP   ;2 free

  STA    $2D;3 free      40




;next group
;etc...etc...

Link to comment
Share on other sites

Actually, I'm not currently using the 'fastest' routine I posted above, I'm using the one Cybergoth suggested.

 

Thanks for posting it. This is an example of redundancy below. Notice how the loop is no longer a loop...but just a string of code. What this does is free 5 cycles from the bottom of each group, in addition to freeing up the X register (so you should be able to come up with a better use for it). I didn't look at the variables too closely, but eliminating the compare in each group will also be possible now that the X register is free to use.

Ok, now I understand what you mean! :D

 

Unfortunately, since I loop 64 times, that solution probably isn't feasible.

Link to comment
Share on other sites

Unfortunately, since I loop 64 times, that solution probably isn't feasible.

 

You wouldn't need 64 copies if a test is done before the top WSYNC to decide when to jump to this section (this is designed to display the players...none of that code is needed if the players don't exist on the scanlines) ;) Since those cycles would be free, there's plenty of time to check when players are coming up...and then branch to this.

Link to comment
Share on other sites

Is there a faster way to display a variable-height ball/missile in the 2600 than this:
  lda BallHeight

 dcp BallY

 sbc BallHeight

 sta ENABL    ;+14

Well, I got around to actually using this in a program, and it doesn't work :P

 

Turns out I had the carry states backwards in my head. This will work though:

lda BallHeight

dcp BallY

sbc BallAdjuster

sta ENABL      ;+14

Where BallAdjuster = BallHeight - 2

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