Jump to content
IGNORED

Playfield lines vs object lines


Karl G

Recommended Posts

It seems like this situation must come up all the time, but somehow I've not dealt with it.

 

How does one deal with the situation where e.g. the playfield changes every 8 scanlines, but one is using a 2-line kernel? I have enough time to use the scanline number as an index and read from a table, but not enough time to divide it by 4 before using it as an index. The only real solution I can think of is increasing my playfield data tables by 4, but I'm wondering if there's a more elegant solution.

 

Here's my current kernel code for reference:

 

    lda #arena_height-1
    sta Scanline
    lda #0
    ldx #0
VisibleScreen
    sta WSYNC               ; 3     (0)
    sta PF0                 ; 3     (3)
    tay                     ; 2     (5)
    sta ENAM0               ; 3     (8)
    lsr                     ; 2     (10)
    sta ENAM1               ; 3     (13)
    lsr                     ; 2     (15)
    sta ENABL               ; 3     (18)
    inx                     ; 2     (20)
    lda DataPF1,x           ; 4     (24*)
    sta PF1                 ; 3     (27)
    lda DataPF2,x           ; 4     (31)
    sta PF2                 ; 3     (34)


    ldy P0Draw              ; 3     (37)
    lda P0Height            ; 3     (40)
    dcp P0Draw              ; 5     (45)
    bcs ____draw_p0         ; 2     (47)
    ldx #0                  ; 2     (49)
    jmp ____done_p0         ; 3     (52)
____draw_p0 
    lax (P0Ptr),y           ; 5     (53)
____done_p0


    ldy P1Draw              ; 3     (56)
    lda P1Height            ; 3     (59)
    dcp P1Draw              ; 5     (64)
    bcs ____draw_p1         ; 2     (66)
    lda #0                  ; 2     (68)
    jmp ____done_p1         ; 3     (71)
____draw_p1 
    lda (P1Ptr),y           ; 5     (72)
____done_p1

; Cycles actually between 70-72 depending on which branches taken, but evened out by the WSYNC


Line2    
    sta WSYNC               ; 3     (0)
    stx GRP0                ; 3     (3)
    sta GRP1                ; 3     (6)
    lda M0Height            ; 3     (9)
    dcp M0Draw              ; 5     (14)
    bcs ____draw_m0         ; 2     (16)
    ldy #0                  ; 2     (18)
    jmp ____done_m0         ; 3     (21)
____draw_m0
    ldy #2                  ; 2     (19)
    sleep 2                 ; 2     (21)
____done_m0

    lda M1Height            ; 3     (24*)
    dcp M1Draw              ; 5     (29)
    bcs ____draw_m1         ; 2     (31)
    sleep 4                 ; 4     (35)
    jmp ____done_m1         ; 3     (38)
____draw_m1
    tya                     ; 2     (34)
    ora #4                  ; 2     (36)
    tay                     ; 2     (38)
____done_m1

    lda BallHeight          ; 3     (41)
    dcp BallDraw            ; 5     (46)
    bcs ____draw_ball       ; 2     (48)
    tya                     ; 2     (50)
    jmp ____done_ball       ; 3     (53)
____draw_ball 
    tya                     ; 2     (51)
    ora #8                  ; 2     (53)
____done_ball
    ; Scanline should be divided by 4, but there's not enough time
    ldx Scanline            ; 3     (56)
    lda DataPF0,x           ; 4     (60)
    dec Scanline            ; 5     (65)
    bpl VisibleScreen       ; 3     (68)

 

Link to comment
Share on other sites

Instead of your current Scanline counter, have two counters:  one for counting the playfield rows, and the other for counting scanlines within the playfield rows.

 

Then change the end of your loop code (starting with LDX Scanline...) to something like:


dec lineCnt                 ;5  [58]
bpl VisibleScreen           ;3  [60/61]

lda #3                      ;2  [62]
sta lineCnt                 ;3  [65]

dec pfLineCnt               ;5  [70]
bpl VisibleScreenAfterWSYNC ;3  [73]

 

The only thing I didn't add was the "lda DataPF0,x".... if you can find some way to squeeze that in (get rid of the unnecessary? TAY and the need for INX near the beginning of the loop), that might work :)

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

38 minutes ago, splendidnut said:

have two counters

 

Yep, that's what I show in the Collect Tutorial.

 

I used Y for the scanline and X for the playfield when I added the playfield routines in step 7.

 

ArenaLoop:                  ;   27 - (currently 7 from bpl ArenaLoop)
        tya                 ; 2 29 - 2LK loop counter in A for testing
        and #%11            ; 2 31 - test for every 4th time through the loop,
        bne SkipX           ; 2 33 (3 34) branch if not 4th time
        inx                 ; 2 35 - if 4th time, increase X so new playfield data is used
SkipX:                      ;   35 - use 35 as it's the longest path here
...
    ; start of line 1 of the 2LK
        sta GRP1            ; 3  3 - @0-22, update player1 graphics
        lda ArenaPF0,x      ; 4  7 - get current scanline's playfield pattern
        sta PF0             ; 3 10 - @0-22 and update it
        lda ArenaPF1,x      ; 4 14 - get current scanline's playfield pattern
        sta PF1             ; 3 17 - @71-28 and update it
        lda ArenaPF2,x      ; 4 21 - get current scanline's playfield pattern
        sta PF2             ; 3 24 - @60-39

 

When I added the ball in step 11 I needed to use X for it, so added a RAM variable ArenaIndex that gets loaded into X when its time to update the PFxx registers.

 

ArenaLoop:                  ;   37 - (currently 11 from bpl ArenaLoop)
        tya                 ; 2 39 - 2LK loop counter in A for testing
        and #%11            ; 2 41 - test for every 4th time through the loop,
        bne SkipX           ; 2 43 - (3 44) branch if not 4th time
        inc ArenaIndex      ; 5 48 - if 4th time, increase index so new playfield data is used
SkipX:                      ;   48 - use 48 as it's the longest path here
...
        ldx ArenaIndex      ; 3  6
        lda ArenaPF0,x      ; 4 10 - get current scanline's playfield pattern
        sta PF0             ; 3 13 - @0-22 and update it
        lda ArenaPF1,x      ; 4 17 - get current scanline's playfield pattern
        sta PF1             ; 3 20 - @71-28 and update it
        lda ArenaPF2,x      ; 4 24 - get current scanline's playfield pattern
        sta PF2             ; 3 27 - @60-39

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

In case it's useful to anyone, I got it to work with the suggested two counters after some rearranging and enabling VDELP1. I was also able to "upgrade" to pointers for the 3 playfield registers.

 

VisibleScreen
    sta ENAM0               ; 3     (3)
    lsr                     ; 2     (5)
    sta ENAM1               ; 3     (8)
    lsr                     ; 2     (10)
    sta ENABL               ; 3     (13)
VSEntry

    ldy P0Draw              ; 3     (16)
    lda P0Height            ; 3     (19)
    dcp P0Draw              ; 5     (24*)
    bcs ____draw_p0         ; 2     (26)
    ldx #0                  ; 2     (28)
    .byte $2C               ; 4     (32)
____draw_p0 
    lax (P0Ptr),y           ; 5     (32)
____done_p0

    ldy P1Draw              ; 3     (35)
    lda P1Height            ; 3     (38)
    dcp P1Draw              ; 5     (43)
    bcs ____draw_p1         ; 2     (45)
    lda #0                  ; 2     (47)
    .byte $2C               ; 4     (51)
____draw_p1
    lda (P1Ptr),y           ; 5     (51)
____done_p1
    sta GRP1                ; 3     (54) ; VDEL

    ldy PFline              ; 3     (57)
    lda (PF2Ptr),y           ; 5     (62)
    sta PF2                 ; 3     (65)
    lda (PF1Ptr),y           ; 5     (70)
    sta PF1                 ; 3     (73)

Line2    
    
    lda (PF0Ptr),y           ; 5     (2)
    sta PF0                 ; 3     (5)
    stx GRP0                ; 3     (8)
    lda Scanline            ; 3     (11)
    and #3                  ; 2     (13)
    beq ____do_4th          ; 2     (15)
    sleep 3                 ; 3     (18)
    jmp ____skip_4th        ; 3     (21)
____do_4th
    dec PFline              ; 5     (21)
____skip_4th

PM0
    lda M0Height            ; 3     (24*)
    dcp M0Draw              ; 5     (29)
    bcs ____draw_m0         ; 2     (31)
    ldy #0                  ; 2     (33)
    jmp ____done_m0         ; 3     (36)
____draw_m0
    ldy #2                  ; 2     (34)
    sleep 2                 ; 2     (36)
____done_m0

PM1
    lda M1Height            ; 3     (39)
    dcp M1Draw              ; 5     (44)
    bcs ____draw_m1         ; 2     (46)
    sleep 4                 ; 4     (50)
    jmp ____done_m1         ; 3     (53)
____draw_m1
    tya                     ; 2     (49)
    ora #4                  ; 2     (51)
    tay                     ; 2     (53)
____done_m1

PBL
    lda BallHeight          ; 3     (56)
    dcp BallDraw            ; 5     (61)
    bcs ____draw_ball       ; 2     (63)
    tya                     ; 2     (65)
    jmp ____done_ball       ; 3     (68)
____draw_ball 
    tya                     ; 2     (66)
    ora #8                  ; 2     (68)
____done_ball
    dec Scanline            ; 5     (73)
    bpl VisibleScreen       ; 3     (0)

 

Link to comment
Share on other sites

20 hours ago, Karl G said:

enabling VDELP1

 

With that you can update GRP1 at any time in the scanline, but need to update GPR0 and ENABL during the time critical horizontal blank.

 

If you turn that around, and enable VDELP0 and VDELBL instead, you'll make timing in your Kernel a little more flexible: GRP1 is now in horizontal blank, but can update both GRP0 and ENABL at any time.

  • Like 1
Link to comment
Share on other sites

7 minutes ago, SpiceWare said:

 

With that you can update GRP1 at any time in the scanline, but need to update GPR0 and ENABL during the time critical horizontal blank.

 

If you turn that around, and enable VDELP0 and VDELBL instead, you'll make timing in your Kernel a little more flexible: GRP1 is now in horizontal blank, but can update both GRP0 and ENABL at any time.

Ahh, thanks. I got the timings to work for this kernel already, but that's good to know for future kernels.

  • Like 1
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...