Re: [stella] Wide Missile Spacing?

Subject: Re: [stella] Wide Missile Spacing?
From: Andrew Towers <mariofrog@xxxxxxxxxxx>
Date: Thu, 11 Dec 2003 14:36:25 +1100
At 06:28 PM 10/12/2003 +0100, Manuel wrote:
> Theoretically possible?
Unfortunately no. The mode "double width & triple copies" does not exist.

I've wondered about this one for a while but I've never gotten around to testing it. Theoretically if the timing is just right it should be possible to get at least 4 double-width players on the screen, 2 copies of P0 double-width and 2 copies of P1 double-width.

However I can't get it to work in the emulators (Z26 or StellaX)
and I have no Supercharger or Cuttle to test this out on some
real hardware. So if someone can try this and tell me what
happens.. :)

What you should see is 4 normal-width players on the top row
with the dragon graphics split in half - this is to check the
spacing. On the second row should be one copy of the left
dragon using double-width graphics - just for reference.

On the third row I'm trying to draw 2 dragons, the left dragon
facing right and the right dragon facing left. The left edge of
the left dragon should be hard up against the right edge of the
left vertical strip (!), and the left edge of the right dragon
should be hard up against the left edge of the right strip,
drawn on top of the strip =)

If it doesn't work or the positions aren't quite right, you can
move the graphics left/right one pixel at a time by moving the
joystick left or right. Press the fire button to reset the
position adjustment. If I'm out by one or two pixels in my
timings this should make it work ;) Otherwise the whole thing
is a dud.

Thanks,
Andrew.

Attachment: dragons.bin
Description: Binary data

;---------------------------------------------------------------------------
;
; Generic 2600 Game
;
;---------------------------------------------------------------------------

        processor 6502
        include vcs.h


;---------------------------------------------------------------------------
; Constants
;---------------------------------------------------------------------------

;---------------------------------------------------------------------------
; RAM Variables
;---------------------------------------------------------------------------

line  equ $80
adjust equ $81
debounce equ $82


  MAC SLEEP
    IF {1} = 1
      ECHO "ERROR: SLEEP 1 not allowed !"
      END
    ENDIF
    IF {1} & 1
      nop $00
      REPEAT ({1}-3)/2
        nop
      REPEND
    ELSE
      REPEAT ({1})/2
        nop
      REPEND
    ENDIF
  ENDM



;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
        org $F000
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------

;---------------------------------------------------------------------------
; Start of Program
;---------------------------------------------------------------------------
; Clear memory, locate character graphics positions and such,
; initialize key memory values, start GameLoop.
;-------------------------------------------------------------
Start
        sei
        cld
        ldx #$FF
        txs
        lda #0
clear
        sta 0,x
        dex
        bne clear

;---------------------------------------------------------------------------
; Initialize variables / registers
;---------------------------------------------------------------------------

        lda #$2F  ;48
        sta COLUP0
        lda #$2F  ;99
        sta COLUP1
        
        lda #$20
        sta COLUPF

        lda #%11110000
        sta PF1

        lda #$01	; set vertical delay on for both players
        sta VDELP0
        sta VDELP1
        
        LDA	#2
        STA	adjust	; initial hmove value, should be correct

	LDA	#20
	STA	debounce	; for Z26


;--------------------------------------------------------------------------
; GameLoop
;--------------------------------------------------------------------------
GameLoop
        jsr VSync       ;start vertical retrace

        jsr VBlank      ; spare time during screen blank
        jsr Picture     ; draw one screen
        jsr overscan    ; do overscan

        jmp GameLoop    ;back to top

;--------------------------------------------------------------------------
; VSync
;--------------------------------------------------------------------------
VSync
        lda #2          ;bit 1 needs to be 1 to start retrace
        sta VSYNC       ;start retrace
        sta WSYNC       ;wait a few lines
        sta WSYNC
        lda #44         ;prepare timer to exit blank period (44)
        sta TIM64T      ;turn it on
        sta WSYNC       ;wait one more
        sta VSYNC       ;done with retrace, write 0 to bit 1

        rts ; VSync



;--------------------------------------------------------------------------
; VBlank
;--------------------------------------------------------------------------
; Game Logic
;--------------------------------------------------------------------------
VBlank

; check for joystick button, reset the hmove adjust
	LDA	INPT4
	BMI	NoReset		; -> not pressed, done

        LDA	#2
        STA	adjust	; initial hmove value, should be correct

        RTS

; check for left/right direction	
NoReset
	LDA	debounce
	BEQ	DoCheck
	DEC	debounce
	RTS

DoCheck
	BIT	SWCHA
	BPL	MoveRight	; if d7=0 (S)
	BVC	MoveLeft	; if d6=0 (V)

        RTS ; VBlank

MoveRight
	DEC	adjust
	LDA	#20
	STA	debounce
	RTS
	
MoveLeft
	INC	adjust
	LDA	#20
	STA	debounce
	RTS


;--------------------------------------------------------------------------
; Overscan
;--------------------------------------------------------------------------
; More Game Logic
;--------------------------------------------------------------------------
overscan

        sta WSYNC

        lda #$00
        sta COLUBK

        lda #36         ; Use the timer to make sure overscan takes (34)
        sta TIM64T      ; 30 scan lines.  29 scan lines * 76 = 2204 / 64 = 34.4

endOS
        lda INTIM       ; We finished, but wait for timer
        bne endOS       ; by looping till zero

        sta WSYNC       ; End last scanline

        lda #$82
        sta VBLANK
        lda #$02
        sta VBLANK

        rts     ; overscan



;--------------------------------------------------------------------------
; Draw TV Pictures
;--------------------------------------------------------------------------
;
;--------------------------------------------------------------------------


Picture

pictureLoop
        lda INTIM       ;check timer for end of VBLANK period
        bne pictureLoop ;loop until it reaches 0

        sta WSYNC	;-

        lda #$80	;2
        sta VBLANK      ;3	end screen blank

	SLEEP	24	;   [29]

; position the players as close as possible to their final
; positions (pixels 32 and 48 respectively)

	STA	RESP0	;3  [32]
	NOP		;2
	STA	RESP1	;3  [37]

; note: turning on stretch 2x mode delays the graphics output
; by one pixel (in Z26 and StellaX anyway) so I have to shift
; both players left one more pixel than I would expect to.

        ;LDA	#(2 << 4)	; exactly on pixel 48
        ;STA	HMP0
        ;LDA	#(1 << 4)	; exactly on pixel 48
        ;STA	HMP1

; actually let the user adjust the position with the joystick

	LDA	adjust		; allow position to be tweaked
	AND	#%00001111	; ignore top bits
	ROL
	ROL
	ROL
	ROL
        STA	HMP0
        SEC
        SBC	#%00010000	; subtract 1
        AND	#%11110000	; wrap around
        STA	HMP1

        STA	WSYNC	;-
        STA	HMOVE
	SLEEP	24
	STA	HMCLR

	LDX	#%00000101	;2	stretch 2x
	;LDX	#%00000100	;2	2 copies far
	STX	NUSIZ0		;3
	STX	NUSIZ1		;3

	JMP	renderIt


	ALIGN	256
renderIt

;------------------------------------------------------------------
; first just draw the non-stretched players

	LDA	#%00000100	;2	2 copies far
	STA	NUSIZ0		;3
	STA	NUSIZ1		;3

; this is a copy of the "real" code from down below with
; all the trick parts nop'd or deleted out. the timing
; is exactly the same though.

        LDY	#25		; 26 lines to draw
renderLoop1
	STA	WSYNC		;-

; set up all graphics at the start of the line
; use VDELP so we can just push through the graphics later

	LDA	gfx0,Y		;4
	STA	GRP0		;3
	LDA	gfx1,Y		;4
	STA	GRP1		;3
	LDA	gfx2,Y		;4
	STA	GRP0		;3
	LDA	gfx3,Y		;4

; nothing better to do right now, set up colours etc

	SLEEP	10		;10

; use these values to switch back and forth quickly

	NOP			;2
	STA	GRP1		;3 [40]
	NOP			;2

; push through the new graphics for the righthand side

	STA	GRP0		;3 [45]

; go around and do it again and again

	DEY			;2
	BPL	renderLoop1	;3 /2


        lda #0          ;2
        sta GRP0
        sta GRP1
        sta GRP0

	STA	WSYNC
	STA	WSYNC
	STA	WSYNC
	STA	WSYNC
	STA	WSYNC

;------------------------------------------------------------------
; now draw them just 2x stretched the whole time

	LDA	#%00000101	;2	stretch 2x
	STA	NUSIZ0		;3
	STA	NUSIZ1		;3

; this is a copy of the "real" code from down below with
; all the trick parts nop'd or deleted out. the timing
; is exactly the same though.

        LDY	#25		; 26 lines to draw
renderLoop2
	STA	WSYNC		;-

; set up all graphics at the start of the line
; use VDELP so we can just push through the graphics later

	LDA	gfx0,Y		;4
	STA	GRP0		;3
	LDA	gfx1,Y		;4
	STA	GRP1		;3
	LDA	gfx2,Y		;4
	STA	GRP0		;3
	LDA	gfx3,Y		;4

; nothing better to do right now, set up colours etc

	SLEEP	10		;10

; use these values to switch back and forth quickly

	NOP			;2
	STA	GRP1		;3 [40]
	NOP			;2

; push through the new graphics for the righthand side

	STA	GRP0		;3 [45]

; go around and do it again and again

	DEY			;2
	BPL	renderLoop2	;3 /2


        lda #0          ;2
        sta GRP0
        sta GRP1
        sta GRP0

	STA	WSYNC
	STA	WSYNC
	STA	WSYNC
	STA	WSYNC
	STA	WSYNC


;------------------------------------------------------------------
; now draw them using the trick to switch backward and forward
; between 2x stretched and 2 copies far.

	LDA	#%00000101	;2	stretch 2x
	STA	NUSIZ0		;3
	STA	NUSIZ1		;3

; this is the "real" code referred to above.

        LDY	#25		; 26 lines to draw
renderLoop3
	STA	WSYNC		;-

; set up all graphics at the start of the line
; use VDELP so we can just push through the graphics later

	LDA	gfx0,Y		;4
	STA	GRP0		;3
	LDA	gfx1,Y		;4
	STA	GRP1		;3
	LDA	gfx2,Y		;4
	STA	GRP0		;3
	LDA	gfx3,Y		;4

; nothing better to do right now, set up colours etc

	SLEEP	10		;10

; use these values to switch back and forth quickly

	LDX	#%00000101	;2	stretch 2x
	STA	GRP1		;3 [40]
	LDA	#%00000100	;2	2 copies far

; push through the new graphics for the righthand side

	STA	GRP0		;3 [45]
	SLEEP	3		;3

; now do the switching trick

	STA	NUSIZ0		;3 [51]
	STX	NUSIZ0		;3 [54]
	STA	NUSIZ1		;3 [57]
	STX	NUSIZ1		;3 [60]

; go around and do it again and again

	DEY			;2
	BPL	renderLoop3	;3 /2


;------------------------------------------------------------------


        lda #0          ;2
        sta GRP0
        sta GRP1
        sta GRP0

	STA	WSYNC
	STA	WSYNC
	STA	WSYNC
	STA	WSYNC
	STA	WSYNC


; draw a few copies down the screen

;	DEC	line
;	BEQ	exitLoop
;	JMP	screenLoop

exitLoop
        ldx #97

ScanLoop
        sta WSYNC
        dex
        bne ScanLoop

        ;sta COLUPF

        rts     ; Picture


        ;------------------------------------------------------------------
        ;------------------------------------------------------------------



;---------------------------------------------------------------------------

        align 256

; left half of left image

gfx0
        .byte #%00001010
        .byte #%00101110
        .byte #%10111101
        .byte #%11011011
        .byte #%10011111
        .byte #%00111111
        .byte #%11011111
        .byte #%11101111
        .byte #%11110111
        .byte #%11011011
        .byte #%11100011
        .byte #%11010011
        .byte #%10100011
        .byte #%11000111
        .byte #%10100110
        .byte #%11001111
        .byte #%10001110
        .byte #%00000100
        .byte #%00011111
        .byte #%00010111
        .byte #%00101011
        .byte #%00110111
        .byte #%00011011
        .byte #%01101111
        .byte #%00011010
        .byte #%00010010

; right half of left image

gfx1
        .byte #%00000000
        .byte #%00000000
        .byte #%11010100
        .byte #%11101110
        .byte #%10111000
        .byte #%11010000
        .byte #%11100000
        .byte #%11110000
        .byte #%11100000
        .byte #%11010000
        .byte #%10100000
        .byte #%11000000
        .byte #%10100000
        .byte #%01000000
        .byte #%10000000
        .byte #%00000000
        .byte #%00000100
        .byte #%11101010
        .byte #%11111111
        .byte #%11000000
        .byte #%00001110
        .byte #%11111101
        .byte #%10011111
        .byte #%11110110
        .byte #%00000000
        .byte #%00000000

; left half of right image

gfx2
        .byte #%00000000
        .byte #%00000000
        .byte #%00101011
        .byte #%01110111
        .byte #%00011101
        .byte #%00001011
        .byte #%00000111
        .byte #%00001111
        .byte #%00000111
        .byte #%00001011
        .byte #%00000101
        .byte #%00000011
        .byte #%00000101
        .byte #%00000010
        .byte #%00000001
        .byte #%00000000
        .byte #%00100000
        .byte #%01010111
        .byte #%11111111
        .byte #%00000011
        .byte #%01110000
        .byte #%10111111
        .byte #%11111001
        .byte #%01101111
        .byte #%00000000
        .byte #%00000000

; right half of right image

gfx3
        .byte #%01010000
        .byte #%01110100
        .byte #%10111101
        .byte #%11011011
        .byte #%11111001
        .byte #%11111100
        .byte #%11111011
        .byte #%11110111
        .byte #%11101111
        .byte #%11011011
        .byte #%11000111
        .byte #%11001011
        .byte #%11000101
        .byte #%11100011
        .byte #%01100101
        .byte #%11110011
        .byte #%01110001
        .byte #%00100000
        .byte #%11111000
        .byte #%11101000
        .byte #%11010100
        .byte #%11101100
        .byte #%11011000
        .byte #%11110110
        .byte #%01011000
        .byte #%01001000

	


;---------------------------------------------------------------------------
; Program Startup
;---------------------------------------------------------------------------
        org $FFFC
        .word Start
        .word Start

Current Thread