Hi. I've only recently started to learn 6502 code and decided to start off by breaking down the classic snake game found herehttps://skilldrick.github.io/easy6502/#snake . I'm trying to break it down into simple parts first by just making two pixels go down the assembler and then stop without any user input but am having trouble making it work as I described. Can anybody assist me in making it work at this basic level? Here is what i have so far which only creates 4 pixels and then stops.
define snakeLength $00
define snakeHeadL $10
define snakeHeadH $11
define snakeBodyStart $12
init: ;initialize the values of the lo and hi bytes
;of the snake head and its length
lda #$04
sta snakeLength
lda #$21
sta snakeHeadL
lda #$01
sta snakeBodyStart
lda #$14
sta $02
lda #$22
sta snakeHeadH
sta $13
sta $15
loop: ;this is the main game loop
jsr shiftValues
jsr updateHead
jsr incHead
jsr gameCheck
jsr drawSnake
jmp loop
gameCheck:
ldx #2
lda snakeHeadL, x
cmp snakeHeadL
lda snakeHeadH,x
cmp snakeHeadH
beq gameOver
inx
inx
cpx snakeLength
beq drawSnake
jmp gameCheck
incHead:
inc snakeHeadH
lda #$6
cmp snakeHeadH
beq gameOver
rts
updateHead: ;this will move the head one row down
;the assembler
LDA snakeHeadL
CLC
ADC #$20
STA snakeHeadL
rts
shiftValues: ;this will shift the values of the
;snakeHead to the body
LDX snakeLength
DEX
LDA snakeHeadL, X ;will give body pixel
STA snakeBodyStart, X
rts
drawSnake: ;this will draw the snake at the current
;position after the updates
ldx snakeLength
lda #$01
sta (snakeHeadL,x)
ldx #$00
lda #$01
sta (snakeHeadL,x)
rts
gameOver:
A bit of single-stepping can help you figure out what's going on. With experience you can simulate things in your head, or, easier, on paper. But at this level of programming you can't afford to skim-read a program you're debugging - every instruction counts, including the ones you forgot to write.
Another common debugging technique is to divide-and-conquer: put some kind of stop part way through the program, run up to that point, and then inspect the state of the machine and the state of memory to make sure everything is as it should be. Depending on the result, move your stop point earlier or later, and repeat.
There's no substitute for rolling up you sleeves and working through the program carefully. There are plenty of people here to help, but don't ask before you've tried pretty hard, or you'll just get the answer, and you won't get the valuable experience of finding the answer yourself.
One first-glance problem is that your shiftValues routine needs to be a loop.
Ok so after some time working the code I now have this but still doesn't seem to be working right. Any advice on what to do next? i think maybe my gameCheck isnt what it should be but I would like some advice on what to do next.
define snakeLength $00
define snakeHeadL $10
define snakeHeadH $11
define snakeBodyStart $12
init: ;initialize the values of the lo and hi bytes
;of the snake head and its length
lda #4
sta snakeLength
lda #$00
sta snakeHeadL
lda #$02
sta snakeBodyStart
lda #$01
sta $05
lda #$02
sta snakeHeadH
sta $03
sta $04
loop: ;this is the main game loop
jsr shiftValues
jsr updateHead
jsr gameCheck
jsr drawSnake
jmp loop
gameCheck:
ldx #2
lda snakeHeadL, x
cmp snakeHeadL
lda snakeHeadH,x
cmp snakeHeadH
beq gameOver
inx
inx
cpx snakeLength
beq drawSnake
jmp gameCheck
updateHead: ;this will move the head one row down
;the assembler
lda snakeHeadL
clc
adc #$20
sta snakeHeadL
incHeadH:
lda snakeHeadH
clc
adc #$01
sta snakeHeadH
cmp snakeHeadH
rts
shiftValues:
lda snakeHeadL, X
sta snakeBodyStart, X
dex
bpl shiftValues
rts
drawSnake: ;this will draw the snake at the current
;position after the updates
ldx snakeLength
lda #0
sta (snakeHeadL,x)
ldx #0
lda #1
sta (snakeHeadL,x)
rts
gameOver:
Where do you suspect the problem lies? How far have you traced into it where it stops working? Have you verified that each subroutine works as expected in isolation?
I have added a few comments to your code that appears strange to me - I admit that I actually don't understand how the game works. Nevertheless it may help you somehow.
....
loop: ;this is the main game loop
jsr shiftValues
jsr updateHead
jsr gameCheck
jsr drawSnake
jmp loop
gameCheck:
ldx #2
GAMECHKLOOP:
lda snakeHeadL, x
cmp snakeHeadL
lda snakeHeadH,x
cmp snakeHeadH -- this is not a valid 16 bit compare if you intended that
beq gameOver
inx
inx
cpx snakeLength
beq drawSnake -- bne GAMECHKLOOP
jmp gameCheck -- rts
updateHead: ;this will move the head one row down
;the assembler
lda snakeHeadL
clc
adc #$20
sta snakeHeadL
incHeadH:
lda snakeHeadH
clc -- I don't know how the snake creeps, but if this should be
adc #$01 -- snakeHead = snakeHead+$20 then the clc is wrong
sta snakeHeadH
cmp snakeHeadH -- cmp ? this would only set the Z flag, but you don't use this anyway
rts
shiftValues:
lda snakeHeadL, X
sta snakeBodyStart, X
dex
bpl shiftValues
rts
drawSnake: ;this will draw the snake at the current
;position after the updates
ldx snakeLength
lda #0
sta (snakeHeadL,x)
ldx #0
lda #1
sta (snakeHeadL,x)
rts
gameOver:
Edit: I inserted Garths very important hint (see below).
Last edited by GaBuZoMeu on Sat Apr 21, 2018 8:04 pm, edited 1 time in total.
Should your "jmp gameCheck" be "JMP gameCheck+2"? As you have it, X won't advance; because although you increment it, it keeps getting re-initialized to 2. Unless interrupts are changing the variables, the exit condition will never be met. If you do the +2 on the jump address, you'll skip the LDX #2 part that's re-initializing it every time, so it can advance.