Wasteland Snake - by PFC Vargas (Full Source Code)

Topics covering the 6502 emulator in Ranger Citadel: tutorials, specs, source code and share your work!

Moderator: Ranger Team Alpha

Post Reply
User avatar
Joby
Developer
Posts: 129
Joined: February 23rd, 2012, 9:21 am
Location: Ground Zero - inXile
Contact:

Wasteland Snake - by PFC Vargas (Full Source Code)

Post by Joby » September 23rd, 2014, 1:12 pm

Greetings rangers!

As promised, here is the full source code for the Snake game. Hopefully, this will give you some ideas on how to create your own game... and probably a good lesson on what not to do. I am by no means an expert in 6502 code... as you'll see. ;)

First and foremost, I want to give mad props to two websites (that I already mentioned in the learning to code post) that are fantastic tools and should be a part of your tool kit. Easy 6502 http://skilldrick.github.io/easy6502/ is fantastic at taking you step by step through programming and full source code for a Snake game. That code was the basis for this Snake game. It was my initial test bed to make sure my 6502 emulator was working. I figured if it could run that code then I was good. From the very beginning I wanted to release my Wasteland Snake code to help people develop 6502 code, but I thought it would be even better to base it off their open-source code so you could start off with a simpler version and really learn how it works, then see how it was modified to be more of a complete game and fitting within the Wasteland 2 6502 computer. I changed it quite a bit, but the foundation is there and should be recognizable. Please spend time with his code and tutorial. It's a fantastic site and playground to test out 6502 code (though be aware you won't be able to use code directly as the memory mappings and capabilities are quite different). The second is an assembler http://www.masswerk.at/6502/assembler.html that is a little limited, but fantastically simple to use. It also does a great job throwing errors to help you get your code right. The below code won't quite work with it as is, but much of your own code can leverage his tool to create the op code you need for a binary. In any assembler, make sure you can set the starting address to 0x7000 for the Wasteland 2 computer. I used a variation of his tool for my own personal needs, changing the output and allowing for longer labels. But, his tool too should be given mad props and high honor. One of the limitations was defining .BYTE and .WORD. Other assemblers allow for a series of bytes to be defined like a string of text as a resource in the code. His assembler, however, is limited in this respect. I created a little work around Ruby script to generate labels for building strings that I could just cut and paste in. It's ugly as hell but works for this situation... thus the painfully long and obnoxious labels and word definitions at the end to create labeled text strings. If you want to assemble this directly, you can use my modified version of his tool, http://jobybednar.com/6502/index.html, but I wanted to give him props for the original.

I would love to hear what assemblers you are using. I tried to leverage freely available online tools so anyone could get into this, but if you have the killer 6502 development tool, please do share it.

6502 assembly code needs to be specific to both your assembler and the "computer" it will run on. It might take some minor tweaks to get it to work with your tools... but hopefully you can take this and run with it!

Code: Select all

* = $7000

  jsr welcome
  jsr init
  jsr paintdesert
  jsr loop

welcome
  jsr introtext
  jsr waitforkey
  jsr screenwipe
  rts

introtext
  jsr initcursor
  lda $ff02 
  
  lda #$3e
  sta $0e
  lda #<word_wasteland
  sta $0c
  lda #>word_wasteland
  sta $0d
  jsr printstring
  
  lda #$48
  sta $0e
  lda #<word_snake
  sta $0c
  lda #>word_snake
  sta $0d
  jsr printstring
  
  lda #$3
  sta $026c
  lda #$2
  sta $026d
  lda #$4
  sta $026e

  lda #$5b
  sta $02a8
  lda #$57
  sta $02a9
  lda #$5d
  sta $02aa
  
  lda #$5b
  sta $02ba
  lda #$41
  sta $02bb
  lda #$5d
  sta $02bc
  lda #$2b
  sta $02bd
  lda #$5b
  sta $02be
  lda #$44
  sta $02bf
  lda #$5d
  sta $02c0
  
  lda #$5b
  sta $02d0
  lda #$53
  sta $02d1
  lda #$5d
  sta $02d2
  
  lda #$b
  sta $0307
  
  lda #$09
  sta $0e
  lda #$03
  sta $0f
  lda #<word_findwater
  sta $0c
  lda #>word_findwater
  sta $0d
  jsr printstring
  
  lda #$b
  sta $0314
  
  lda #$6b
  sta $0e
  lda #<word_bypfcvargas
  sta $0c
  lda #>word_bypfcvargas
  sta $0d
  jsr printstring
  
  rts

waitforkey
  lda $fff0
wkeyloop
  pha
  jsr spinWheels
  jsr spinWheels
  jsr waterdrops
  pla
  cmp $fff0
  beq wkeyloop
  rts
  
waterdrops
  inc $0307
  lda $0307
  cmp #$f
  bne nextdrop
  lda #$b
  sta $0307
nextdrop
  inc $0314
  lda $0314
  cmp #$f
  bne dropdone
  lda #$b
  sta $0314
dropdone
  rts

screenwipe
  lda $ff07
  lda #$80
  sta $ff0d
  lda #$80
  sta $0f
  wipemainloop
  ldy #0
  wipeloop
  lda $0f
  sta $f400,y
  iny
  cpy #8
  bne wipeloop
  cmp #1
  beq wipeend
  lsr a
  sta $0f
  jsr spinWheels
  jmp wipemainloop
  wipeend
  rts

paintdesert
  lda #$7
  sta $ff09
  lda $ff12
  lda $ff04
  ldx #0
  lda #$e
  
  paintloop
  sta $0400,x
  inx
  cpx #0
  bne paintloop
  
  ldx #0
  paintloop2
  sta $0500,x
  inx
  cpx #0
  bne paintloop2
  
  ldx #0
  paintloop3
  sta $0600,x
  inx
  cpx #0
  bne paintloop3
  
  ldx #0
  paintloop4
  sta $0700,x
  inx
  cpx #0
  bne paintloop4
  
  rts

init
  jsr initSnake
  jsr generateRocks
  jsr generateApplePosition
  jsr clearscore
  rts


initSnake
  lda #2
  sta $02
  lda #4
  sta $03
  lda #$11
  sta $20
  lda #$10
  sta $22
  lda #$0f
  sta $24
  lda #$06
  sta $21
  sta $23
  sta $25
  
  lda #$0
  sta $09
  lda #$7
  sta $0a
  lda #$c
  sta $0b
  rts

generateRocks
  lda $fffa
  sta $10
  lda $fffa
  and #$03
  clc
  adc #4
  sta $11
  
  lda $fffa
  sta $12
  lda $fffa
  and #$03
  clc
  adc #4
  sta $13
  
  lda $fffa
  sta $14
  lda $fffa
  and #$03
  clc
  adc #4
  sta $15
  
  lda $fffa
  sta $16
  lda $fffa
  and #$03
  clc
  adc #4
  sta $17
  
  lda $fffa
  sta $18
  lda $fffa
  and #$03
  clc
  adc #4
  sta $19
  
  lda $fffa
  sta $1a
  lda $fffa
  and #$03
  clc
  adc #4
  sta $1b
  
  lda $fffa
  sta $1c
  lda $fffa
  and #$03
  clc
  adc #4
  sta $1d
  
  lda $fffa
  sta $1e
  lda $fffa
  and #$03
  clc
  adc #4
  sta $1f
  rts 

generateApplePosition

  lda $fffa
  sta $00

  lda $fffa
  and #$03
  clc
  adc #4
  sta $01
  
  jmp checkRockPosition
  
applePositionGood 
  
  inc $05
  inc $06
  lda $05
  cmp #42
  beq maxscore
  lda $06
  cmp #$a
  beq tensplace
  rts
  
tensplace
  inc $07
  lda #0
  sta $06
  rts
  
checkRockPosition
  ldx #0
rockPositionLoop
  lda $10,x
  cmp $0
  bne continueRockPositionLoop

maybeRockPosition
  lda $11,x
  cmp $1
  beq didRockPosition

continueRockPositionLoop
  inx
  inx
  cpx #16
  beq didntRockPosition
  jmp rockPositionLoop

didRockPosition
  jmp generateApplePosition
didntRockPosition
  jmp applePositionGood
  
maxscore
  jmp gameWon

clearscore
  lda #0
  sta $05
  lda #0
  sta $06
  rts

loop
  jsr readKeys
  jsr checkCollision
  jsr updateSnake
  jsr drawRocks
  jsr drawApple
  jsr drawSnake
  jsr spinWheels
  jmp loop


readKeys
  lda $fff0
  cmp #$77
  beq upKey
  cmp #$64
  beq rightKey
  cmp #$73
  beq downKey
  cmp #$61
  beq leftKey
  rts
upKey
  lda #4
  bit $02
  bne illegalMove

  lda #1
  sta $02
  rts
rightKey
  lda #8
  bit $02
  bne illegalMove

  lda #2
  sta $02
  rts
downKey
  lda #1
  bit $02
  bne illegalMove

  lda #4
  sta $02
  rts
leftKey
  lda #2
  bit $02
  bne illegalMove

  lda #8
  sta $02
  rts
illegalMove
  rts


checkCollision
  jsr checkAppleCollision
  jsr checkRockCollision
  jsr checkSnakeCollision
  rts


checkAppleCollision
  lda $00
  cmp $20
  bne doneCheckingAppleCollision
  lda $01
  cmp $21
  bne doneCheckingAppleCollision

  inc $03
  inc $03
  jsr shiftRockPosition
  jsr generateApplePosition
doneCheckingAppleCollision
  rts

checkRockCollision
  ldx #0
rockCollisionLoop
  lda $10,x
  cmp $20
  bne continueRockCollisionLoop

maybeRockCollided
  lda $11,x
  cmp $21
  beq didRockCollide

continueRockCollisionLoop
  inx
  inx
  cpx #16
  beq didntRockCollide
  jmp rockCollisionLoop

didRockCollide
  jmp gameOver
didntRockCollide
  rts

checkSnakeCollision
  ldx #2
snakeCollisionLoop
  lda $20,x
  cmp $20
  bne continueCollisionLoop

maybeCollided
  lda $21,x
  cmp $21
  beq didCollide

continueCollisionLoop
  inx
  inx
  cpx $03
  beq didntCollide
  jmp snakeCollisionLoop

didCollide
  jmp gameOver
didntCollide
  rts

shiftRockPosition
  lda $fffa
  and #$7
  asl a
  clc
  tax
  lda #$e
  sta ($10,x)
  lda $fffa
  sta $10,x
  lda $fffa
  and #$3
  clc
  adc #4
  sta $11,x
  rts

updateSnake
  ldx $03
  dex
  txa
updateloop
  lda $20,x
  sta $22,x
  dex
  bpl updateloop

  lda $02
  lsr A

  bcs up
  lsr A
  bcs right
  lsr A
  bcs down
  lsr A
  bcs left
up
  lda $20
  sec
  sbc #$20
  sta $20
  bcc upup
  rts
upup
  dec $21
  lda #$3
  cmp $21
  beq collision
  rts
right
  inc $20
  lda #$1f
  bit $20
  beq collision
  rts
down
  lda $20
  clc
  adc #$20
  sta $20
  bcs downdown
  rts
downdown
  inc $21
  lda #$8
  cmp $21
  beq collision
  rts
left
  dec $20
  lda $20
  and #$1f
  cmp #$1f
  beq collision
  rts
  
collision
  jmp gameOver

drawRocks
  ldx #0
  drawRocksLoop
  lda #2
  sta ($10,x)
  inx
  inx
  cpx #16
  bne drawRocksLoop
  rts

drawApple
  lda $fffa
  and #$9
  ora #$1
  ldy #0
  sta ($00),y
  rts


drawSnake
  ldx #0
  lda $0b
  eor #$c
  sta $0b
  eor $0a
  sta $0a
  eor $09
  sta $09
  sta ($20,x)
  ldx $03
  lda #$e
  sta ($20,x)
  rts


spinWheels
  lda #100
  sbc $03
  tax
spinloop
  nop
  nop
  dex
  bne spinloop
  rts

pause
  lda $03
  tax
  lda #4
  loopkillcolor
  sta ($20,x)
  dex
  dex
  bne loopkillcolor
  
  jsr drawRocks
  
  lda #0
  sta $03
  
  ldy #16
  pauseloop
  jsr spinWheels
  dey
  bne pauseloop
  rts

pauseWon
  ldy #32
  pauseloopwon
  
  lda $03
  tax
  tya
  and #$15
  loopkillcolorwon
  sta ($20,x)
  dex
  dex
  bne loopkillcolorwon
  
  jsr spinWheels
  dey
  bne pauseloopwon
  rts

gameWon
  jsr pauseWon
  jsr initcursor
  lda $ff02 
  
  lda #$3
  sta $026c
  lda #$2
  sta $026d
  lda #$4
  sta $026e
  
  lda #$a3
  sta $0e
  lda #<word_yourlifehas
  sta $0c
  lda #>word_yourlifehas
  sta $0d
  jsr printstring
  
  lda #$b9
  sta $0e
  lda #<word_conquered
  sta $0c
  lda #>word_conquered
  sta $0d
  jsr printstring
  
   lda #$cb
  sta $0e
  lda #<word_thewasteland
  sta $0c
  lda #>word_thewasteland
  sta $0d
  jsr printstring
  
  lda #$3
  sta $030c
  lda #$2
  sta $030d
  lda #$4
  sta $030e
  
  jmp finalscore

gameOver
  jsr pause
  jsr initcursor
  lda $ff02 

  lda #$2d
  sta $0e
  lda #<word_gameover
  sta $0c
  lda #>word_gameover
  sta $0d
  jsr printstring
  
  lda #$3
  sta $026c
  lda #$8
  sta $026d
  lda #$4
  sta $026e
  
  lda #$a3
  sta $0e
  lda #<word_yourlifehas
  sta $0c
  lda #>word_yourlifehas
  sta $0d
  jsr printstring
  
  lda #$b9
  sta $0e
  lda #<word_endedin
  sta $0c
  lda #>word_endedin
  sta $0d
  jsr printstring
  
   lda #$cb
  sta $0e
  lda #<word_thewasteland
  sta $0c
  lda #>word_thewasteland
  sta $0d
  jsr printstring
  
  lda #$3
  sta $030c
  lda #$8
  sta $030d
  lda #$4
  sta $030e

finalscore  

  lda #$f
  sta $0344
  
  lda #$45
  sta $0e
  lda #$03
  sta $0f
  jsr print_wire

  lda #$10
  sta $034e
  
  lda #$13
  sta $0358
  
  lda #$59
  sta $0e
  lda #<word_score
  sta $0c
  lda #>word_score
  sta $0d
  jsr printstring
  
  clc
  lda $07
  adc #48
  sta $0360
  lda $06
  adc #48
  sta $0361
  
  lda #$13
  sta $0362
  
  lda #$11
  sta $036c
  
  lda #$6d
  sta $0e
  lda #$03
  sta $0f
  jsr print_wire
  
  lda #$12
  sta $0376
  jmp theend

initcursor
  lda #$02
  sta $0f
  lda #0
  sta $0e
  rts

printstring
 ldy #0
 ldx #0
ps_next
 lda ($0c),y
 beq ps_done
 sta ($0e,X)
 inc $0e
 bne ps_y
 inc $0f
ps_y 
 iny
 bne ps_next
ps_done
 rts
 
print_wire
 lda #<word_wire
 sta $0c
 lda #>word_wire
 sta $0d
 jsr printstring
 rts

c_wa = $4157
c_st = $5453
c_el = $4c45
c_an = $4e41
c_d  = $44

c_sn = $4e53
c_ak = $4b41
c_e  = $45

c_f = $46
c_in = $494e
c_d_ = $2044
c_wa = $4157
c_te = $4554
c_r = $52

c_by = $5942
c__p = $5020
c_fc = $4346
c__v = $5620
c_ar = $5241
c_ga = $4147
c_s = $53

c_me = $454d
c__o = $4f20
c_ve = $4556

c_yo = $4f59
c_ur = $5255
c__l = $4c20
c_if = $4649
c_ha = $4148

c_en = $4e45
c_de = $4544
c_d_ = $2044
c_in = $4e49

c_co = $4f43
c_nq = $514e
c_ue = $4555
c_re = $4552

c_th = $4854
c_e_ = $2045

c_sc = $4353
c_or = $524f
c_eq = $3a45

c_wire = $1414
c_wirenull = $14

word_thewasteland
.word c_th
.word c_e_

word_wasteland
.word c_wa
.word c_st
.word c_el
.word c_an
.word c_d

word_snake
.word c_sn
.word c_ak
.word c_e

word_findwater
.byte c_f
.word c_in
.word c_d_
.word c_wa
.word c_te
.word c_r

word_bypfcvargas
.word c_by
.word c__p
.word c_fc
.word c__v
.word c_ar
.word c_ga
.word c_s

word_gameover
.word c_ga
.word c_me
.word c__o
.word c_ve
.word c_r

word_yourlifehas
.word c_yo
.word c_ur
.word c__l
.word c_if
.word c_e_
.word c_ha
.word c_s

word_endedin
.word c_en
.word c_de
.word c_d_
.word c_in
.byte $0

word_conquered
.word c_co
.word c_nq
.word c_ue
.word c_re
.word c_d

word_score
.word c_sc
.word c_or
.word c_eq
.byte $0

word_wire
.word c_wire
.word c_wire
.word c_wire
.word c_wire
.word c_wirenull

theend
.END
- Joby
inXile's ruthless Leader of Scripters

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest