This is the freely redistributable source code to a clone of Sokoban for the Nintendo Entertainment System. This game is written in 6502 assembly. There did not seem to be any Nintendo code in the database, (so I thought this would be a good addition).


;Sokoban - Johannes Holmberg 1999-2000

spritemem      = $200
bgpaldata      = $BFE0
sprpaldata     = $BFF0
playerxdata    = $20
paladdr        = $3F00
sprpaladdr     = $3F10
ppucontrol1    = $61
noboxdata      = $B300

playerx        = $2FF
playery        = $2FC
px             = $310
py             = $311
lvlmatrix      = $300
behbox         = $500
lvlpointer     = $0
boxcount       = $10
boxptr         = $11
boxesleft      = $12
tx             = $20
ty             = $21
curboxptr      = $40
temp1          = $50
temp2          = $51
temp3          = $52
temp4          = $53
temp5          = $54
temp6          = $55
temp7          = $56
temp8          = $57
dirx           = $45
diry           = $46
bgwall         = $60
bgground       = $65
bggoal         = $62
spbox          = $63
spchar         = $64
memlvlptr      = $2
startpressed   = $58

.org $C000

reset
   sei
   cld
   ldx $0
   stx $2000
   stx ppucontrol1
   stx $2001
   lda #7
   sta $1
   lda #0
   ldy #0
   ldx #$FF
   txs          ;Set stack pointer to $FF
clearram        ;Clear ram...
   sta (0),y
   dey
   bne clearram
   dec $1
   bpl clearram

   lda #$20     ;Clear name and attribute tables.=$1000 bytes
   sta $2006   
   lda #0
   sta $2006
   ldy #$10     ;$10*$100=$1000
   ldx #0
clearppuram
   sta $2007
   dex
   bne clearppuram
   dey
   bne clearppuram

   lda #$3F
   ldx #$0
   sta $2006
   stx $2006
   ldy #$20
setpalette            ;Set the palette...
   lda bgpaldata,x
   sta $2007
   inx
   dey
   bne setpalette

   lda #$FF           ;Tile numbers...
   sta bgwall
   lda #$4F
   sta bgground
   lda #$9F
   sta bggoal
   lda #$FF
   sta spchar
   lda #$3F
   sta spbox

   lda #1
   sta boxesleft   ;Just a precaution...
   lda #$90        ;Allow NMIs, and set background address to $1000.
   sta $2000
   sta ppucontrol1

   lda #0
   sta startpressed

   jsr titlescreen ;Titlescreen...

   lda #$80         ;Set the level pointer to $8000 - level 1 (duh).
   sta lvlpointer+1






bigloop
   jsr loadlevel    ;Load the level lvlpointer points to.
ostro               ;Just do nothing until there is a VBlank.
   jmp ostro



vblank
   pha              ;Store the values of the registers.
   txa              ;Not actually necessary right now,
   pha              ;but it might be in the future.
   tya
   pha
   lda boxesleft    ;Determine whether this level is completed.
   bne keepplayingthislevel
   inc lvlpointer+1
   jsr loadlevel
keepplayingthislevel
   lda #0           ;Make sure the screen doesn't scroll :)
   sta $2005
   sta $2005
   sta dirx         ;No movement (delete old movement values).
   sta diry
   lda #2           
   sta $4014        ;This seems like a stupid thing to do, oh well. :)
   ldx #1
   stx $4016
   dex
   stx $4016        ;Reset joypad register.
   lda $4016 ;A     ;These buttons are currently unused...
   lda $4016 ;B
   lda $4016 ;Select

   lda $4016 ;Start?
   and #1
   beq notstart
   lda startpressed
   bne startalreadypressed
   lda #$FF
   sta startpressed
   pla              ;Reset stack pointer
   pla
   pla
   dec bgwall  
   dec bgground
   dec bggoal
   dec spchar
   dec spbox        ;These are all increased by loadlevel
   jmp bigloop      ;Reload level.
notstart
   lda #0
   sta startpressed
startalreadypressed
   lda $4016 ;Up?
   and #1
   beq notup
   lda #$FF
   sta diry
   jmp trytomove
notup
   lda $4016 ;Down?
   and #1
   beq notdown
   lda #1
   sta diry
   jmp trytomove
notdown
   lda $4016 ;Left?
   and #1
   beq notleft
   lda #255
   sta dirx
   jmp trytomove
notleft
   lda $4016 ;Right?
   and #1
   beq notright
   lda #1
   sta dirx
   jmp trytomove
notright
backfrommoving
   pla           ;Get the register values back...
   tay
   pla
   tax
   pla
   rti


trytomove          ;Check if movement is possible.
   lda #6          ;Set the levelpointer.
   sta memlvlptr+1
   lda #0
   sta memlvlptr
   sta temp3       ;Store the pointer (might be unnecessary).
   sta temp4
   lda playerx     ;Load the player's x coordinate.
   lsr a            
   lsr a           ;Divide by 8 (sprite width).
   lsr a
   sta px          ;Store in another variable!
   clc
   adc dirx        ;Add the x movement to it.
   sta temp1       ;Store in temp1!!! :)
   lda playery     ;Do the same thing to the y coordinate.
   clc
   adc #1          ;Add one (you know why...).
   lsr a
   lsr a           ;Divide by 8 (Sprite height...).
   lsr a
   sec
   sbc #6          ;Subtract 6 (The playing field is centered on the screen).
   clc
   adc diry        ;Add the y direction.
   asl a           
   asl a
   asl a           ;Multiply by 32 (screen width in tiles).
   asl a
   asl a
   sta memlvlptr   ;Store in memlvlptr.
   lda #0
   adc memlvlptr+1 ;Add 0 to the high byte of memlvlptr,
   sta memlvlptr+1 ;Incase there is a carry bit.
   sta temp8       ;Store in temp8.
   lda memlvlptr
   clc
   adc temp1       ;Add temp1 (x position) to memlvlptr.
   sta temp7       ;Store in temp7.
   sta memlvlptr   ;Store in memlvlptr...
   ldy #0          ;No offset.
   lda (memlvlptr),y ;Load the byte at memlvlptr.
   cmp #$50          ;Is the square empty?
   beq normalmove
   cmp #$A0          ;Is it a "goal"-square?
   beq normalmove
   cmp #$FE          ;Is it a box?
   beq pushmove
   jmp backfrommoving

pushmove
   jsr moveboxtest
   jmp backfrommoving
normalmove
   jsr move
cantmove
   jmp backfrommoving



moveboxtest       ;Check the tile after the box to see if it is empty.
   lda diry
   asl a
   asl a
   asl a
   asl a
   asl a
   sta temp1
   lda memlvlptr
   pha
   clc
   adc dirx
   clc
   adc temp1
   sta memlvlptr
   sta temp5
   pla              ;
   lsr a            ;
   lsr a            ;
   lsr a            ;
   lsr a            ;
   lsr a            ;
   cmp #7           ;
   bne notthatway   ;
   lda diry         ;
   cmp #1           ;
   bne nobigchange  ;
   jmp bigchange    ;
notthatway          ;
   cmp #0           ;
   bne nobigchange  ;
   lda diry         ;
   cmp #$FF         ;
   bne nobigchange  ;
bigchange           ;
   lda memlvlptr+1  ;
   eor #1           ;
   sta memlvlptr+1  ;
;   bcc nobigchange
;   lda temp1
;   bmi nobigchange
;   lda memlvlptr+1
;   eor #1             ;Change the high byte if there has been an overflow.
;   sta memlvlptr+1
nobigchange
   lda memlvlptr+1
   sta temp6
   lda (memlvlptr),y
   sta temp3
   cmp #$50           
   beq oktomove       ;Ok, it's empty.
   cmp #$A0
   beq movetogoal       ;Ok, it's a "goal"-square.
   rts
movetogoal
   dec boxesleft
oktomove
                        ;Find the right sprite...
   lda dirx             ;Get the box coordinates by adding the
   asl a                ;movement values to the player coordinates.
   asl a
   asl a
   clc
   adc playerx
   sta temp1
   lda diry
   asl a
   asl a
   asl a
   clc
   adc playery
   sta temp2
   ldy #0
trynextsprite           ;Now go through all the sprites.
   lda spritemem,y      ;First check the y position.
   cmp temp2
   beq tryxtoo
   iny
   iny
   iny
   iny
   bne trynextsprite
tryxtoo                 ;If y is a match, check x too.
   lda spritemem+3,y
   cmp temp1
   beq foundit          ;If x also matches it must be the one!
   iny
   iny
   iny
   iny
   bne trynextsprite
foundit                
   sty curboxptr        ;Store the boxponter in curboxptr!
   lda curboxptr        ;Hmm, why not do a tya? :)
   lsr a                ;Divide by 4 to get the sprite number.
   lsr a
   tax                  ;Store it in x.
   lda temp7            ;Load memlvlptr from temp7 and temp8.
   sta memlvlptr
   lda temp8
   sta memlvlptr+1
   ldy #0
   lda behbox,x         ;See what's behind the box that is about to be moved.
   sta (memlvlptr),y    ;Store it instead of the box at that position.
   cmp #$A0
   bne itsnotagoalsquare
   inc boxesleft
itsnotagoalsquare
   lda temp5            ;Get the memlvlptr for the new boxposition.
   sta memlvlptr        ;temp5 and temp6...
   lda temp6
   sta memlvlptr+1
   lda (memlvlptr),y    ;See what is there.
   sta behbox,x         ;Store it in behbox,
   lda #$FE             ;and replace it with a box value.
   sta (memlvlptr),y
   ;Now move the damn box!!!


   lda ppucontrol1      ;Just some code to do the animation
   and #$7F             ;and change the coordinates of the player/box.
   sta ppucontrol1
   sta $2000
   ldy #8
   ldx curboxptr
novblankyet2
   lda $2002
   bpl novblankyet2
   lda #$2
   sta $4014
   lda dirx
   clc
   adc playerx
   sta playerx
   lda diry
   clc
   adc playery
   sta playery
   lda spritemem,x
   clc
   adc diry
   sta spritemem,x
   lda spritemem+3,x
   clc
   adc dirx
   sta spritemem+3,x
   dey
   bne novblankyet2
   lda ppucontrol1
   ora #$80
   sta ppucontrol1
   sta $2000
   ;slut p† det... <-Swedish ;)
   rts




move                 ;Move the player...
   lda ppucontrol1
   and #$7F
   sta ppucontrol1
   sta $2000
   ldy #8
novblankyet
   lda $2002
   bpl novblankyet
   lda #$2
   sta $4014
   lda dirx
   clc
   adc playerx
   sta playerx
   lda diry
   clc
   adc playery
   sta playery
   dey
   bne novblankyet
   lda ppucontrol1
   ora #$80
   sta ppucontrol1
   sta $2000
   rts
  







loadlevel      ;Load the level...
   inc bgwall  ;Use new set of tiles.
   inc bgground
   inc bggoal
   inc spchar
   inc spbox
   lda #0
   sta $2001   ;Disable backgrounds...
   lda ppucontrol1
   and #$7F
   sta $2000   ;Disable NMIs.
   sta ppucontrol1
lele           ;_Bnu was here. (?)
   lda $2002
   bpl lele

   ;Nytt
   lda #$3F
   sta $2006
   lda #$00
   sta $2006
   lda #0
   ldx #4
   clc
newpaletteloop
   adc #$10
   tay
   pha
   lda (lvlpointer),y
   sta $2007
   pla
   dex
   bne newpaletteloop
   pha
   lda #$3F
   sta $2006
   lda #$10
   sta $2006
   pla
   ldx #8
newpaletteloop2
   adc #$10
   tay
   pha
   lda (lvlpointer),y
   sta $2007
   pla
   dex
   bne newpaletteloop2
   ;slut p† nytt

lala
   lda $2002
   bpl lala
   lda #6
   sta ty
   sta memlvlptr+1 ;
   ldy #0     ;Reset sprites...
   sty tx
   sty boxptr
   sty boxcount
   sty memlvlptr ;
resetsprites
   tya
   lsr a
   lsr a
   tay
   lda #$50
   sta behbox,y
   tya
   asl a
   asl a
   tay

   lda #$F2
   sta spritemem,y
   iny
   lda spbox
   sta spritemem,y
   iny
   lda #1
   sta spritemem,y
   iny
   iny
   bne resetsprites
   sty playery+2
   ldy spchar
   sty playery+1

   lda #$20   ;Don't remember what this is supposed to do... Seems wrong...
   ldy #$C0   ;Oh well...
   
   sta $2006
   lda #0
   sta $2006
   ldx #$FF
settoff
   stx $2007
   dey
   bne settoff
   
   ldx #1    ;Shift the first one, don't and.
loadmore
   lda (lvlpointer),y
   dex
   bmi andnotshift
   lsr a
   lsr a
   lsr a
   lsr a
   jmp donewiththisstuff
andnotshift
   and #$F
donewiththisstuff
   cmp #5         ;Is it the player?
   bne notplayer
   lda ty
   asl a
   asl a
   asl a ;Multiply by 8...
   sbc #0 ;subtract 1...
   sta playery
   lda tx
   asl a
   asl a
   asl a ;Multiply by 8...
   sta playerx
   lda #$50
   pha
   lda bgground
   jmp notafloor
notplayer
   cmp #6
   bne notbox2
   inc boxcount
   tya              ;Create a new boxsprite...
   pha
   lda ty
   asl a
   asl a 
   asl a ;Multiply by 8 (sprite height)
   sbc #0 ;Subtract one from the y-position. Assumes that carry is not set.
   pha
   ldy boxptr
   lda #$A0
   sta behbox,y
   pla
   sta spritemem,y
   iny
   iny
   iny
   lda tx
   asl a
   asl a 
   asl a ;Multiply by 8 (sprite width :)
   sta spritemem,y
   iny
   sty boxptr
   lda #1         ;
   sta temp4      ;
   pla
   tay
   lda #$A0
   pha
   lda bggoal
   jmp notafloor
notbox2
   cmp #4
   bne notbox
   tya              ;Create a new boxsprite...
   pha
   inc boxcount
   lda ty
   asl a
   asl a 
   asl a ;Multiply by 8 (sprite height)
   sbc #0 ;Subtract one from the y-position. Assumes that carry is not set.
   ldy boxptr
   sta spritemem,y
   iny
   iny
   iny
   lda tx
   asl a
   asl a 
   asl a ;Multiply by 8 (sprite width :)
   sta spritemem,y
   iny
   sty boxptr
   lda #1         ;
   sta temp4      ;
   pla
   tay
   lda #$50
   pha
   lda bgground
   jmp notafloor
notbox
   cmp #0
   bne notempty
   lda #$FF
   pha
   jmp notafloor
notempty
   cmp #1
   bne notawall
   lda #$0
   pha
   lda bgwall
   jmp notafloor
notawall
   cmp #3
   bne notagoal
   lda #$A0
   pha
   lda bggoal
   jmp notafloor
notagoal
   cmp #2
   bne notafloor
   lda #$50
   pha
   lda bgground
notafloor
   
   sta $2007
   
               ;pha
   lda temp4      ;
   beq nochange   ;
   pla            ;
   lda #$FE       ;
   pha            ;
nochange          ;
   tya
   asl a
   bcc notpage2
   lda #7
   sta memlvlptr+1
notpage2
   txa
   beq noadd
   tya
   asl a
   bcs cool ;clc
   adc #1
   jmp add
cool         ;
   clc       ;
   adc #1    ;
   sec       ;
   jmp add   ;
noadd
   tya
   asl a
add
   tay
   pla
   sta (memlvlptr),y ;
   tya
   ror a
   tay
   lda #0         ;
   sta temp4      ;
   inc tx         
   lda #$20       
   cmp tx
   bne notnewline
   lda #$FF
   sta $2007
   sta $2007
   lda #2  ;blaff
   iny
   beq doneloading
   sta tx
   inc ty
notnewline
   txa
   bne dotheiny
   jmp loadmore
dotheiny
   ldx #1
   iny
   beq doneloading
   jmp loadmore
doneloading

   ldx #$FF
settoff2
   stx $2007
   dey
   bne settoff2
   lda lvlpointer+1
   sec
   sbc #$80
   tay
   ldx noboxdata,y
   stx boxesleft
uuu
   lda $2002        ;Working?
   bpl uuu
   lda #$18
   sta $2001
   lda ppucontrol1
   ora #$80
   sta ppucontrol1
   sta $2000
   rts

titlescreen
   lda #0
   sta $2001
   lda ppucontrol1
   and #$7F
   sta ppucontrol1
   sta $2000
   lda #$20
   sta $2006
   lda #0
   sta $2006
   ldy #$C0
   ldx #4
   lda #$FF
paintitblack
   sta $2007
   dey
   bne paintitblack
   dex
   bne paintitblack
   lda #$21
   sta $2006
   ldx #0
   stx $2006
drawmore
   lda $B200,x
   beq drawless
   sta $2007
   inx
   bne drawmore
drawless
   lda #$22
   sta $2006
   lda #$A
   sta $2006
   ldx #0
drawpressstart
   lda $B2C0,x
   beq yetanotherlabel
   sta $2007
   inx
   bne drawpressstart
yetanotherlabel
   lda #$18
   sta $2001
   lda ppucontrol1
   and #$7f
   sta ppucontrol1
   sta $2000
ostronhest
   ldx #1
   stx $4016
   dex
   stx $4016
   stx $2005
   stx $2005
   lda $4016
   lda $4016
   lda $4016
   lda $4016
   and #1
   cmp #1
   beq startispushed
   jmp ostronhest
startispushed
   lda ppucontrol1
   ora #$80
   sta ppucontrol1
   sta $2000
   rts




.org $FFFA
.word vblank
.word reset
.word reset

.end

Log in or register to write something here or to contact authors.