|
Subject: [stella] Introduction and new game From: "Erik J. Eid" <eeid@xxxxxxxxx> Date: Wed, 06 Jun 2001 22:23:19 -0400 |
;
; Euchre game program for the Atari 2600 video computer system
;
; Copyright 2001 by Erik Eid (eeid@xxxxxxxxx)
;
; Last update: June 3, 2001
;
; Compiled with the dasm assembler using the -f3 option
;
processor 6502
include vcs.h
; Constants
seg.u defines
CardsInDeck = $18 ; 24 cards in a Euchre deck
Team1Color = $88
Team2Color = $38
TableRegionColor = $d4
CardTableColor = $0f
RedSuitColor = $36
BlackSuitColor = $00
MessageRegionColor = $22
RankMask = %00000111 ; Bit mask for rank of a card
DispSuitMask = %00011000 ; Bit mask for suit displayed on a card
RealSuitMask = %01100000 ; Bit mask for suit used when following (the left
; bower becomes the suit of the right bower)
ShowCardMask = %10000000 ; Bit mask for determining if a card is shown
BlackSuitMask = %00010000
SWACNT = $281 ; Strangely not part of the original vcs.h
VS_Disable = 0 ; Ditto
CenterRankPos = $75 ; Player positions
CenterSuitPos = $66
LeftRankPos = $a2
RightRankPos = $57
MessageP0Pos = $44
MessageP1Pos = $c4
; Variables
seg.u vars
org $80
Team1Score ds 1
Team2Score ds 1
Team1Tricks ds 1
Team2Tricks ds 1
NorthHand ds 5 ; Cards in a player's hand
EastHand ds 5
SouthHand ds 5
WestHand ds 5
NorthCard ds 1 ; Cards down on the table
EastCard ds 1
SouthCard ds 1
WestCard ds 1
ImgPtr1 ds 2 ; Pointers to playfield and player images
ImgPtr2 ds 2
ImgPtr3 ds 2
ImgPtr4 ds 2
HandCard ds 1 ; Pointer to a card in a hand
T1 ds 1 ; Temporary variables used in subroutines
T2 ds 1
T3 ds 1
rand1 ds 1 ; Locations to hold bits of random number
rand2 ds 1
rand3 ds 1
rand4 ds 1
NeedShuffle ds 1 ; Flag indicating if a shuffle is needed
DeckStart = NorthHand
; Program
seg code
org $f000 ; 4K cartridge
;
; Initialization
;
CartStart
sei ; Disable all interrupts
cld ; Clear decimal mode (so carry is at 256, not 100)
ldx #$ff
txs ; Reset the stack pointer to the highest point possible
; Clear out registers and variables
lda #$00
ClearRAM
sta $00,x
dex
bne ClearRAM ; Loop does not zero WSYNC, but it's not needed
sta SWACNT ; Tell port A to accept input
lda #$6d ; seed random number generator
sta rand1
sta rand2
sta rand3
sta rand4
ProgStart
;
; Begin a new game
;
GameStart
lda #$00
sta Team1Score
sta Team2Score
;
; Begin a new hand
;
HandStart
lda #$00
sta Team1Tricks
sta Team2Tricks
lda #$01
sta NeedShuffle
;
; Main loop
;
Main
; Start of display kernel
; Provide three lines of vertical sync
lda #VS_Enable
sta WSYNC
sta WSYNC
sta WSYNC
sta VSYNC
sta WSYNC
sta WSYNC
sta WSYNC
lda #VS_Disable
sta VSYNC
; Provide 37 scanlines of vertical blank
lda #43 ; 37 lines * 76 cycles/line = 2812 cycles / 64 cycles/interval = 43.96 intervals
sta TIM64T
; When it comes time, check console switches here
lda NeedShuffle
beq PostShuffle
jsr ShuffleDeck
lda #$00
sta NeedShuffle
PostShuffle
jsr RandomBit ; keep the randomness flowing
WaitVBlank
lda INTIM
nop
bne WaitVBlank
sta WSYNC ; Finish up last line
sta VBLANK ; Stop vertical blank (accumulator holds zero)
; Now we start on the visible portion of the screen
; First eight lines are blank...
lda #9 ; 8 lines * 76 cycles/line = 608 cycles / 64 cycles/interval = 9.5 intervals
sta TIM64T
; Since we have some time, prepare the playfield for displaying the scores
; and get pointers to playfield images for them.
lda #Team1Color
sta COLUP0
lda #Team2Color
sta COLUP1
lda #PF_Score
sta CTRLPF
ldx Team1Score
ldy #ImgPtr1
jsr GetScoreImage
ldx Team2Score
ldy #ImgPtr2
jsr GetScoreImage
WaitEndScore
lda INTIM
nop
bne WaitEndScore
; Now we spend ten lines drawing the scores on the playfield
ldx #$09
ScoresLoop
sta WSYNC
txa
lsr
tay
lda (ImgPtr1),y
sta PF1
ror T1
ror T1
nop
nop
nop
lda (ImgPtr2),y
sta PF1
dex
bpl ScoresLoop
; Pause for four lines and prepare to show tricks
sta WSYNC
lda #$00
sta PF1
lda #4
sta TIM64T
WaitBeginTricks
lda INTIM
nop
bne WaitBeginTricks
; Trick graphics are four lines with the same value, so the offset into
; the TrickImages table is for the number of tricks rather than the xth
; byte of an image.
ldy #$04
TricksLoop
sta WSYNC
ldx Team1Tricks
lda TrickImages,x
sta PF1
ror T1
ror T1
nop
nop
nop
ldx Team2Tricks
lda TrickImages,x
sta PF1
dey
bne TricksLoop
; Pause for eight more lines.
sta WSYNC
lda #$00
sta PF1
lda #7
sta TIM64T
; Position the players for display of a card. This is well in advance but
; we have time now.
lda #CenterRankPos
ldx #0
jsr PositionPlayer
lda #CenterSuitPos
ldx #1
jsr PositionPlayer
sta WSYNC
sta HMOVE
WaitBeginTable
lda INTIM
nop
bne WaitBeginTable
; Now switch to the "card table" display
sta WSYNC
lda #TableRegionColor
sta COLUBK
lda #CardTableColor
sta COLUPF
lda #PF_Reflect
sta CTRLPF
lda #$0f
sta PF1
lda #$ff
sta PF2
lda NorthCard
ldx #ImgPtr1
ldy #ImgPtr2
jsr GetCardGraphics
sta COLUP0
sta COLUP1
jsr DrawSingleCard
lda #$00
sta GRP0
sta GRP1
; Now we come to the hard one... both West and East
lda #P_TwoClose ; Two copies close
sta NUSIZ0
sta NUSIZ1
lda WestCard
ldx #ImgPtr1
ldy #ImgPtr3
jsr GetCardGraphics
sta COLUP0
lda EastCard
ldx #ImgPtr2
ldy #ImgPtr4
jsr GetCardGraphics
sta COLUP1
lda #LeftRankPos
ldx #0
jsr PositionPlayer
lda #RightRankPos
ldx #1
jsr PositionPlayer
sta WSYNC
sta HMOVE
ldy #7
DrawWestEastCards
nop
nop
ror T1
ror T1
lda (ImgPtr3),y
tax
lda (ImgPtr1),y
sta GRP0
stx GRP0
pha
lda (ImgPtr4),y
tax
lda (ImgPtr2),y
sta GRP1
stx GRP1
pla
sta WSYNC
dey
bpl DrawWestEastCards
lda #$00
sta GRP0
sta GRP1
sta NUSIZ0
sta NUSIZ1
lda #CenterRankPos
ldx #0
jsr PositionPlayer
lda #CenterSuitPos
ldx #1
jsr PositionPlayer
sta WSYNC
sta HMOVE
lda SouthCard
ldx #ImgPtr1
ldy #ImgPtr2
jsr GetCardGraphics
sta COLUP0
sta COLUP1
jsr DrawSingleCard
lda #4
sta TIM64T
WaitEndSouth
lda INTIM
nop
bne WaitEndSouth
lda #9 ; burn 8 lines
sta TIM64T
lda #$00
sta COLUBK
sta PF1
sta PF2
WaitBeforeHand
lda INTIM
nop
bne WaitBeforeHand
; Draw the five cards in the player's hand. For each of the cards, draw four
; black lines then twelve card lines. The middle eight lines of the card have
; the images. During the four black lines, get the image pointers and player
; colors.
lda #$00
sta HandCard
ShowHandLoop
lda #4
sta TIM64T
lda #$00
sta COLUBK
sta PF2
ldx HandCard
lda SouthHand,x
ldx #ImgPtr1
ldy #ImgPtr2
jsr GetCardGraphics
sta COLUP0
sta COLUP1
WaitToDrawHandCard
lda INTIM
nop
bne WaitToDrawHandCard
lda #$f0
sta PF2
sta WSYNC
sta WSYNC
jsr DrawSingleCard
lda #$00
sta GRP0
sta GRP1
sta WSYNC
sta WSYNC
inc HandCard
lda HandCard
cmp #$05
bne ShowHandLoop
; Now the gap between the last card and the message region
lda #9
sta TIM64T
lda #$00
sta COLUBK
sta PF2
sta COLUP0
sta COLUP1
WaitForGap
lda INTIM
nop
bne WaitForGap
lda #MessageRegionColor
sta COLUBK
lda #MessageP0Pos
ldx #0
jsr PositionPlayer
lda #MessageP1Pos
ldx #1
jsr PositionPlayer
lda P_ThreeClose
sta NUSIZ0
sta NUSIZ1
lda #19 ; 16 lines of message
sta TIM64T
WaitForMessage
lda INTIM
nop
bne WaitForMessage
lda #$00
sta COLUPF
lda #9 ; 8 lines
sta INTIM
lda #$00
sta WSYNC
sta PF1
sta PF2
sta COLUBK
sta COLUP0
sta COLUP1
sta COLUPF
sta CTRLPF
sta GRP0
sta GRP1
sta NUSIZ0
sta NUSIZ1
WaitForEnd
lda INTIM
nop
bne WaitForEnd
sta WSYNC
lda #35 ; 30 lines of overscan
sta TIM64T
lda #$02
sta VBLANK
CheckReset
lda SWCHB
and #$01
cmp #$01
beq WaitOverscan
jmp ProgStart
WaitOverscan
lda INTIM
nop
bne WaitOverscan
sta WSYNC
jmp Main
GetScoreImage
txa
asl
tax
lda ScoreImages,x
sta $00,y
lda ScoreImages+1,x
sta $01,y
rts
GetRankImage
txa
asl
tax
lda RankImages,x
sta $00,y
lda RankImages+1,x
sta $01,y
rts
GetSuitImage
txa
asl
tax
lda SuitImages,x
sta $00,y
lda SuitImages+1,x
sta $01,y
rts
NewDeck
.byte $00,$01,$02,$03,$04,$05
.byte $28,$29,$2a,$2b,$2c,$2d
.byte $50,$51,$52,$53,$54,$55
.byte $78,$79,$7a,$7b,$7c,$7d
; All images are reversed since they are read by decrementing loops.
ScoreImage0
.byte $07,$05,$05,$05,$07
ScoreImage1
.byte $07,$02,$02,$06,$02
ScoreImage2
.byte $07,$04,$07,$01,$07
ScoreImage3
.byte $07,$01,$03,$01,$07
ScoreImage4
.byte $01,$05,$07,$01,$01
ScoreImage5
.byte $07,$01,$07,$04,$07
ScoreImage6
.byte $07,$04,$07,$05,$07
ScoreImage7
.byte $04,$04,$02,$01,$07
ScoreImage8
.byte $07,$05,$02,$05,$07
ScoreImage9
.byte $07,$01,$07,$05,$07
ScoreImage10
.byte $77,$25,$25,$65,$27
ScoreImage11
.byte $72,$22,$22,$62,$22
ScoreImage12
.byte $77,$24,$27,$61,$27
ScoreImage13
.byte $77,$21,$23,$61,$27
ScoreImages
.byte <ScoreImage0
.byte >ScoreImage0
.byte <ScoreImage1
.byte >ScoreImage1
.byte <ScoreImage2
.byte >ScoreImage2
.byte <ScoreImage3
.byte >ScoreImage3
.byte <ScoreImage4
.byte >ScoreImage4
.byte <ScoreImage5
.byte >ScoreImage5
.byte <ScoreImage6
.byte >ScoreImage6
.byte <ScoreImage7
.byte >ScoreImage7
.byte <ScoreImage8
.byte >ScoreImage8
.byte <ScoreImage9
.byte >ScoreImage9
.byte <ScoreImage10
.byte >ScoreImage10
.byte <ScoreImage11
.byte >ScoreImage11
.byte <ScoreImage12
.byte >ScoreImage12
.byte <ScoreImage13
.byte >ScoreImage13
TrickImages
.byte $00,$01,$05,$15,$55,$FF
; routine to draw a single card
; assumes ImgPtr1 and ImgPtr2 point to proper images, sprites are
; positioned, and so on
DrawSingleCard
ldy #07
DrawCardLoop
sta WSYNC
lda (ImgPtr1),y
sta GRP0
lda (ImgPtr2),y
sta GRP1
dey
bpl DrawCardLoop
rts
; routine to shuffle the deck
ShuffleDeck
ldx #CardsInDeck
RefreshDeck
dex
lda NewDeck,x
sta DeckStart,x
bne RefreshDeck
lda #$08
sta T3
ShuffleLoop
ldx #CardsInDeck
OneShuffle
dex
stx T1
jsr RandomByte
ModLoop
cmp #CardsInDeck
bcc LTCards
sec
sbc #CardsInDeck
jmp ModLoop
LTCards
ldx T1
tay
lda DeckStart,x
sta T2
lda DeckStart,y
sta DeckStart,x
lda T2
sta DeckStart,y
ldx T1
bne OneShuffle
dec T3
bne ShuffleLoop
rts
org $fd00
; routine for getting images and colors of a card
; a = card
; x = image pointer for rank
; y = image pointer for suit
; returns: a = color of card
GetCardGraphics
sta T1
stx T2
sty T3
lda T1
and #RankMask
tax
ldy T2
jsr GetRankImage
lda T1
and #DispSuitMask
lsr
lsr
lsr
tax
ldy T3
jsr GetSuitImage
lda T1
and #BlackSuitMask
bne CardIsBlack
lda #RedSuitColor
jmp LeaveGetCardGraphics
CardIsBlack
lda #BlackSuitColor
LeaveGetCardGraphics
rts
org $fe00
; routine to position a player
; original version by Erik Mooney in the Stella mailing list message
; "Re: [stella] sexp8.bin Multi-Japanese Sprites" from April 18, 1998
; (http://www.biglist.com/lists/stella/archives/199804/msg00170.html)
; modified to work on both player 0 and 1 and to take a hard-coded
; position value rather than look at a table (there is no motion in
; this game, so the table is not necessary)
;
; a = position value - high nybble = fine position, low nybble =
; course position
; x = player number
PositionPlayer
sta WSYNC
ror T1 ; waste 5 cycles
sta HMP0,x
and #$0f
tay
P0
dey
bpl P0
sta RESP0,x
; Rather than WSYNC and HMOVE now, let the calling routine do it. If both
; players are positioned in succession, this saves a scanline.
rts
; routine to generate a random number
; original version by Erik Mooney in the Stella mailing list message
; "Re: [stella] demo update: PCMSD20.BIN" from April 14, 1997
; (http://www.biglist.com/lists/stella/archives/199704/msg00136.html)
; requires four memory locations to be reserved for generation
;
; returns: a = random number
RandomBit
lda rand4
asl
asl
asl
eor rand4 ;new bit is now in bit 6 of A
asl
asl ;new bit is now in carry
rol rand1 ;shift new bit into bit 0 of register; bit 7 goes into carry
rol rand2 ;shift old bit 7 into bit 8, etc.
rol rand3
rol rand4
rts
RandomByte
ldx #8
RandomByte1
jsr RandomBit
dex
bne RandomByte1
lda rand1
rts
org $ff00
; All images are reversed since they are read by decrementing loops.
RankImage9
.byte $00,$3c,$46,$06,$3e,$66,$66,$3c
RankImage10
.byte $00,$ee,$5b,$5b,$5b,$5b,$db,$4e
RankImageJack
.byte $00,$3c,$66,$06,$06,$06,$06,$0e
RankImageQueen
.byte $00,$3a,$64,$6a,$66,$66,$66,$3c
RankImageKing
.byte $00,$66,$6c,$78,$70,$78,$6c,$66
RankImageAce
.byte $00,$c6,$c6,$fe,$fe,$c6,$7c,$38
RankImageLeft
.byte $00,$ec,$8a,$8a,$8c,$8a,$8a,$8c ; debug "LB"
; .byte $00,$3c,$66,$06,$06,$06,$06,$0e
RankImageRight
.byte $00,$ac,$aa,$aa,$cc,$aa,$aa,$cc ; debug "RB"
; .byte $00,$3c,$66,$06,$06,$06,$06,$0e
SuitImageHeart
.byte $00,$10,$38,$7c,$fe,$fe,$ee,$44
SuitImageDiamond
.byte $00,$10,$38,$7c,$fe,$7c,$38,$10
SuitImageClub
.byte $00,$18,$7e,$ff,$7e,$18,$3c,$18
SuitImageSpade
.byte $00,$38,$ba,$fe,$fe,$7c,$38,$10
RankImages
.byte <RankImage9
.byte >RankImage9
.byte <RankImage10
.byte >RankImage10
.byte <RankImageJack
.byte >RankImageJack
.byte <RankImageQueen
.byte >RankImageQueen
.byte <RankImageKing
.byte >RankImageKing
.byte <RankImageAce
.byte >RankImageAce
.byte <RankImageLeft
.byte >RankImageLeft
.byte <RankImageRight
.byte >RankImageRight
SuitImages
.byte <SuitImageHeart
.byte >SuitImageHeart
.byte <SuitImageDiamond
.byte >SuitImageDiamond
.byte <SuitImageClub
.byte >SuitImageClub
.byte <SuitImageSpade
.byte >SuitImageSpade
org $fffc
.byte <CartStart
.byte >CartStart
.byte <CartStart
.byte >CartStart
Attachment:
Euchre.bin
Description: Binary data
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| Aw: Re: [stella] Infogrames conside, cybergoth | Thread | Re: [stella] Introduction and new g, Manuel Polik |
| Re: [stella] Infogrames considers A, Thomas Jentzsch | Date | Re: [stella] Infogrames considers A, Russ Perry Jr |
| Month |