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