[stella] Gunfight 2600

Subject: [stella] Gunfight 2600
From: Manuel Polik <manuel.polik@xxxxxxxxxxx>
Date: Tue, 13 Feb 2001 14:16:01 +0100
Hi there!

I just finished an early play-kernel of my current project 'Gunfight
2600'. 
(The reason why I was quit some days now :-))

At the moment, this is a single-line kernel, but I'm 100% sure, that
I've to do a double-line one, when adding the missiles(guns) & the ball
(shots). 
It's just single at the moment, so that I force myself to tight code.
Besides, the cowboys even look better when streched a bit vertically :-)

Uhm, though it doesn't look too bad, I've already a ...uhm... *little*
problem:

I'm already too slow with writing player0. At the moment it works, but
if I start to animate the coboys, I have to switch to indirect sprite
access, needing more cycles than the direct access now. This would ruin
the colors of player0.

I give you the idea how the kernel works at the moment:

I substract the desired vertical postion of the sprite from the current
scannline. 
This result is checked if smaller than the cowboy size and if yes, taken
to index(!) the sprite.
Pretty clever I thought, but too slow.

Here's the part ripped out (& additionally commented) of the complete
source:

-----------------

MainScreen      STA WSYNC       ; Finish current line
                STA VBLANK      ; Stop vertical blank

nextLine    	TYA		; Y holds current scannline
            	SBC verPos0	; the substraction I was talking about
	    	TAX		; Take it as index. Clever I thought :-)
	    	STA WSYNC	; Here we go Start drawing a line
            	BPL sprite1	; positivie value -> sprite possible
	    	NOP		; \
	    	LDA $00		; / 5 useless timing cycles
            	LDA #$00	; no sprite -> clear it
            	BEQ Continue	; Continue

sprite1     	CMP #$13	; Sprite already done with drawing?
            	BMI Sprite2	; N: Draw it!
            	LDA #$00	; Y: Clear it
            	BEQ Continue	; Continue
         
Sprite2     	LDA  p0data,x  	; Load Sprite shape
        
Continue    	STA  GRP0	; We are _always_ on cycle 12 now
            	LDA colordata,x	;
            	STA COLUP0	; Store sprite & color

; [...] 	Repeat everything exactly for player 2

            	INY		; next scanline
            	CPY #$B0	; all done?
            	BNE nextLine	; N: Do another line

-----------------

Now - I can't push the STA WSYNC further down. STA COLUP0 is finished on
cycle 22. Just one cycle more and the colors are ruined.

So, are there any ideas to speed this up some more?

Greetings,	
	Manuel

P.S.: Yes, I already know that the source is a big mess on some
locations and that the joystick routine is criminal/useless :-) All that
stuff was some quick copy & paste from various sources to have a base
for developing the kernel. I'll fix all this later, when I'm done with
the display kernel.
        processor 6502
      include vcs.h

horPos0        	= $80   ;This is the vertical position of the sprite
horPos1         = $81   ;This is the vertical position of the sprite
verPos0         = $82   ;This is the vertical position of the sprite
verPos1         = $83   ;This is the vertical position of the sprite

        org  $F000

start   	SEI
        	CLD
        	LDX  #$FF
        	TXS
        	LDA  #$00

zero    	STA  $00,X      ;zero out the machine
        	DEX
        	BNE  zero

        	LDA  #$32       ;set up some of the variables.
        	STA  COLUP0     ;set up sprite colour
        	LDA  #$60       ;set up the starting vertical position of sprite
        	STA  verPos0
      		STA  horPos0
        	STA  verPos1
      		STA  horPos1
      		LDA  #$1C
        	STA  COLUBK

        
MainLoop        JSR VerticalSync    ; 
		JSR VerticalBlank   ; 
                JSR MainScreen      ; MainScreen does Overscan
                JMP MainLoop        ; Repeat

VerticalSync    LDA #$02            ;
                STA WSYNC           ; Finish current line
                STA VSYNC           ; start vertical sync
                LDA #$03            ;
                STA TIM64T          ;
              	JMP WaitIntimReady  ; Wait until vertical sync finished

VerticalBlank   STA WSYNC           ; Finish current line
                STA VSYNC           ; Stop vertical sync
                LDA #$02            ;
                STA VBLANK          ; Start vertical blank
                LDA #$2B            ;
                STA TIM64T          ; Init timer

; Position all objects

            	LDY #$04
PosAnother      ldx horPos0,Y          ;+3  3
            	JSR PosPlayer
            	DEY
            	BPL PosAnother
            	STA WSYNC           ; Finish current line
            	sta HMOVE
            	LDY #$00
            	LDA #$08
            	STA REFP1

WaitIntimReady  LDA INTIM           ; Wait until vertical blank finished
                BNE WaitIntimReady  ;
                RTS

Waste           STA WSYNC           ; Waste a line
                DEX                 ;
                BNE Waste           ; if X is not zero, do more lines
                RTS

MainScreen      STA WSYNC           ; Finish current line
                STA VBLANK          ; Stop vertical blank

nextLine    	TYA			;2
            	SBC verPos0		;5
	    	TAX
	    	STA WSYNC		
            	BPL sprite1		;7/8
	    	NOP			;...
	    	LDA $00		;... 7 extra cycles
            	LDA #$00		;9
            	BEQ Continue	;12

sprite1     	CMP #$13		;10
            	BMI Sprite2		;12/13
            	LDA #$00		;14
            	BEQ Continue	;17
         
Sprite2     	LDA  p0data,x   	;19
        
Continue    	STA  GRP0		;22 = 3+ 12(+7extra) v 17 (+2extra) v 19
            	LDA colordata,x
            	STA COLUP0

            	TYA
	    	CLC
            	SBC verPos1
	    	TAX
            	BPL sprite3
	    	NOP			;...
	    	LDA $00		;... 7 extra cycles
            	LDA #$00
            	BEQ Continue2

sprite3     	CMP #$13
            	BMI Sprite4
            	LDA #$00
            	BEQ Continue2
         
Sprite4     	LDA  p0data,x   ;If not then load the sprite data.
        
Continue2    	STA  GRP1
            	LDA colordata,x
            	STA COLUP1

            	INY
            	CPY #$B0
            	BNE nextLine

oscan2  	JSR  joy        ;overscan. Time to read the joysticks.
        	LDX  #$1E
        	JMP Waste 

joy     	LDY #$00
        	LDA  SWCHA      
        	ASL
        BCC right
        ASL
        BCC left
        ASL
        BCC down
        ASL
        BCC up
        ASL
        BCC right2
        ASL
        BCC left2
        ASL
        BCC down2
        ASL
        BCC up2
        RTS
    
right   INC horPos0 ;set horizontal motion register to one pixel right
      LDA horPos0
      CMP #$99
      BNE HorPosOK
      DEC horPos0
HorPosOK rts

left    DEC horPos0       ;set horizontal motion register to one pixel left
      LDA horPos0
      CMP #$FF
        BNE HorPosOK2
      INC horPos0
HorPosOK2 rts

down      LDA  verPos0    ;make sure we haven't gone over the top of the screen
        CMP #$AB
        BEQ NoClimb
        INC  verPos0    ;if not then increase the vertical position
NoClimb RTS

up    LDA verPos0
        CMP #$01
        BEQ NoSink
        DEC  verPos0    ;decrease the vertical position
NoSink  RTS

right2   INC horPos1 ;set horizontal motion register to one pixel right
      LDA horPos1
      CMP #$A0
        BNE HorPosOK3
      DEC horPos1
HorPosOK3 rts

left2    DEC horPos1       ;set horizontal motion register to one pixel left
      LDA horPos1
      CMP #$FF
        BNE HorPosOK4
      INC horPos1
HorPosOK4 rts

up2      LDA  verPos1    ;make sure we haven't gone over the top of the screen
        CMP #$B0
        BEQ NoClimb2
        INC  verPos1    ;if not then increase the vertical position
NoClimb2 RTS

down2   LDA verPos1
        CMP #$20
        BEQ NoSink2
        DEC  verPos1    ;decrease the vertical position
NoSink2  RTS

PosPlayer
    sta WSYNC           ;begin scanline
    lda HorzTable,X     ;+4  7  
    sta HMP0,Y           ;+3 10
    and #$0F            ;+2 12
    tax                 ;+2 14
P0      dex                 ;+2 16
    bpl P0              ;when branch not taken: +2 (18 + x*5)
    sta RESP0,Y         ;(21 + x*5)
    sta WSYNC
    rts

    ORG $FE00

HorzTable    ;this must not cross a page boundary
    .byte $30,$20,$10,$00,$F0,$E0,$D0,$C0,$B0,$A0,$90
    .byte $71,$61,$51,$41,$31,$21,$11,$01,$F1,$E1,$D1,$C1,$B1,$A1,$91
    .byte $72,$62,$52,$42,$32,$22,$12,$02,$F2,$E2,$D2,$C2,$B2,$A2,$92
    .byte $73,$63,$53,$43,$33,$23,$13,$03,$F3,$E3,$D3,$C3,$B3,$A3,$93
    .byte $74,$64,$54,$44,$34,$24,$14,$04,$F4,$E4,$D4,$C4,$B4,$A4,$94
    .byte $75,$65,$55,$45,$35,$25,$15,$05,$F5,$E5,$D5,$C5,$B5,$A5,$95
    .byte $76,$66,$56,$46,$36,$26,$16,$06,$F6,$E6,$D6,$C6,$B6,$A6,$96
    .byte $77,$67,$57,$47,$37,$27,$17,$07,$F7,$E7,$D7,$C7,$B7,$A7,$97
    .byte $78,$68,$58,$48,$38,$28,$18,$08,$F8,$E8,$D8,$C8,$B8,$A8,$98
    .byte $79,$69,$59,$49,$39,$29,$19,$09,$F9,$E9,$D9,$C9,$B9,$A9,$99
    .byte $7A,$6A,$5A,$4A,$3A,$2A,$1A,$0A,$FA,$EA,$DA,$CA,$BA,$AA,$9A

p0data  
        .byte %00101000
        .byte %00101100
        .byte %00111100
        .byte %11111111
        .byte %00110100
        .byte %00111110
        .byte %00111100
        .byte %00011000
        .byte %00111111
        .byte %01111111
        .byte %11111100
        .byte %10111100
        .byte %10111100
        .byte %10111100
        .byte %01111110
        .byte %00100110
        .byte %01001100
        .byte %10001000
        .byte %11101110

    ORG $FF00

colordata
        .byte $00
        .byte $00
        .byte $00
        .byte $00
        .byte $54
        .byte $54
        .byte $54
        .byte $54
        .byte $0a
        .byte $0b
        .byte $0c
        .byte $0d
        .byte $0e
        .byte $0f
        .byte $10
        .byte $11
        .byte $12
        .byte $13
        .byte $14

        org $FFFC
        .word start
        .word start

Attachment: gunfight.bin
Description: Binary data

Current Thread