Sokoban in RISC-V
October 18, 2025
(Written with my lab partner, Yash Vora.)
# player character position
addi x12, x0, 12 # intentionally out of bounds
jal x0, rendersetup
level4:
# play dimensions
addi x7, x0, 7 # “height”
addi x25, x0, -7 # “height”
addi x8, x0, 81 # total volume (easier than width)
addi x24, x10, -35
addi x24, x24, 51
addi x9, x0, 1024
slli x9, x9, 1
sw x24, 384(x9)
# store the blocks in memory
sw x10, 3(x0)
sw x10, 4(x0)
sw x10, 5(x0)
sw x10, 6(x0)
sw x10, 8(x0)
sw x10, 9(x0)
sw x10, 10(x0)
sw x10, 13(x0)
sw x10, 14(x0)
sw x10, 15(x0)
sw x16, 17(x0)
sw x10, 20(x0)
sw x10, 21(x0)
sw x21, 23(x0)
sw x19, 24(x0)
sw x21, 25(x0)
sw x10, 27(x0)
sw x10, 28(x0)
sw x10, 34(x0)
sw x10, 35(x0)
sw x10, 36(x0)
sw x10, 37(x0)
sw x10, 40(x0)
sw x10, 41(x0)
sw x10, 44(x0)
sw x10, 45(x0)
sw x10, 46(x0)
sw x10, 47(x0)
# player character position
addi x12, x0, 12
jal x0, rendersetup
rendersetup:
# vga store location
addi x9, x0, 1024
slli x9, x9, 1
addi x5, x0, 0 # current mem loc
addi x6, x0, 640 # current vga render loc
addi x6, x6, 10 # current vga render loc
addi x14 x0, 0 # current row number
render:
beq x24, x0, nolvl
addi x26, x10, -35
addi x26, x26, 83
sw x26, 32(x9)
addi x26, x26, -83
addi x26, x26, 79
sw x26, 64(x9)
sw x26, 128(x9)
addi x26, x26, -79
addi x26, x26, 75
sw x26, 96(x9)
addi x26, x26, -75
addi x26, x26, 66
sw x26, 160(x9)
addi x26, x26, -66
addi x26, x26, 65
sw x26, 192(x9)
addi x26, x26, -65
addi x26, x26, 78
sw x26, 224(x9)
addi x9, x9, 256
addi x26, x26, -78
addi x26, x26, 45
sw x26, 0(x9)
addi x26, x26, -45
addi x26, x26, 76
sw x26, 32(x9)
sw x26, 96(x9)
addi x26, x26, -76
addi x26, x26, 86
sw x26, 64(x9)
addi x9, x9, -256
nolvl:
lw x3, 0(x5)
bne x5, x12, rendermem # if x5 = x12, store the current vga loc and render
player
add x13, x6, x0
add x4, x9, x6
sw x11, 0(x4)
beq x3, x21, player_on_box
bne x3, x19, updateloc
sw x20, 0(x4) # player on sprite
jal x0, updateloc
player_on_box:
sw x20, 0(x4) # player on sprite
jal x0, updateloc
rendermem:
add x4, x9, x6
sw x3, 0(x4)
updateloc:
addi x5, x5, 1
addi x6, x6, 1
addi x14, x14, 1
beq x5, x8, mainloop # if x5 = x8, done
bne x14, x7, render # if x14 = x7, skip the rest of the column
addi x6, x6, 32
sub x6, x6, x7
sub x14, x14, x7
jal x0, render
mainloop:
# Bitflag handling for RLUD
addi x18, x0, 1
beq x18 x31 start
and x18, x17, x18
jal x0, wincheck
nvm:
bne x18, x0, rightskip # skip if right pressed
beq x27, x0, right
leftcheck:
addi x18, x0, 2
and x18, x17, x18
bne x18, x0, leftskip # skip if left pressed
beq x28, x0, left
upcheck:
addi x18, x0, 4
and x18, x17, x18
bne x18, x0, upskip # skip if up pressed
beq x29, x0, up
downcheck:
addi x18, x0, 8
and x18, x17, x18
bne x18, x0, downskip # skip if down pressed
beq x30, x0, down
# DO NOT PUT ANY CODE HERE, IT WILL NOT ALWAYS RUN; put it at start of mainloop
beq x0, x0, mainloop
rightskip:
bne x27, x0, rightreset
jal x0, leftcheck
rightreset:
addi x17, x17, -1
jal x0, leftcheck
leftskip:
bne x28, x0, leftreset
jal x0, upcheck
leftreset:
addi x17, x17, -2
jal x0, upcheck
upskip:
bne x29, x0, upreset
jal x0, downcheck
upreset:
addi x17, x17, -4
jal x0, downcheck
downskip:
bne x30, x0, downreset
jal x0, mainloop
downreset:
addi x17, x17, -8
jal x0, mainloop
right:
addi x17, x17, 1 # update bitflag
add x23, x12, x7
lw x15, 0(x23)
beq x15, x10 mainloop
beq x15, x16 boxmoveright
beq x15, x21 boxoffplateright
# if no box, then easy
add x12, x12, x7
addi x13, x13, 32
jal x0, rendersetup
boxmoveright:
add x23, x23, x7
lw x15, 0(x23)
beq x15, x10 mainloop # stop if wall
beq x15, x16 mainloop # stop if another box
beq x15, x21 mainloop # stop if another box-on-plate
add x12, x12, x7
addi x13, x13, 32
beq x15, x19 boxonplateright
sw x0, 0(x12)
sw x16, 0(x23)
jal x0, rendersetup
boxonplateright:
sw x0, 0(x12)
add x23, x12, x7
sw x21, 0(x23)
jal x0, rendersetup
boxoffplateright:
add x23, x23, x7
lw x15, 0(x23)
beq x15, x10 mainloop # stop if wall
beq x15, x16 mainloop # stop if another box
beq x15, x21 mainloop # stop if another box-on-plate
add x12, x12, x7
sw x19, 0(x12)
sw x16, 0(x23)
jal x0, rendersetup
left:
addi x17, x17, 2 # update bitflag
add x23, x12, x25
lw x15, 0(x23)
add x0, x0, x0
beq x15 x10 mainloop
beq x15, x16 boxmoveleft
beq x15, x21 boxoffplateleft
add x12, x12, x25
addi x13, x13, -32
jal x0, rendersetup
boxmoveleft:
add x23, x23, x25
lw x15, 0(x23)
beq x15 x10 mainloop
beq x15 x16 mainloop
beq x15, x21 mainloop # stop if another box-on-plate
add x12, x12, x25
beq x15, x19 boxonplateleft
sw x0, 0(x12)
add x23, x12, x25
sw x16, 0(x23)
jal x0, rendersetup
boxonplateleft:
sw x0, 0(x12)
add x23, x12, x25
sw x21, 0(x23)
jal x0, rendersetup
boxoffplateleft:
add x23, x23, x25
lw x15, 0(x23)
beq x15, x10 mainloop # stop if wall
beq x15, x16 mainloop # stop if another box
beq x15, x21 mainloop # stop if another box-on-plate
add x12, x12, x25
sw x19, 0(x12)
add x23, x12, x25
sw x16, 0(x23)
jal x0, rendersetup
up:
addi x17, x17, 4 # update bitflag
lw x15, -1(x12)
beq x15 x10 mainloop
beq x15, x16 boxmoveup
beq x15, x21 boxoffplateup
addi x12, x12, -1
addi x13, x13, -1
jal x0, rendersetup
boxmoveup:
lw x15 -2(x12)
beq x15 x10 mainloop
beq x15 x16 mainloop
beq x15, x21 mainloop # stop if another box-on-plate
addi x12, x12, -1
addi x13, x13, -1
beq x15, x19 boxonplateup
sw x0, 0(x12)
sw x16, -1(x12)
jal x0, rendersetup
boxonplateup:
sw x0, 0(x12)
sw x21, -1(x12)
jal x0, rendersetup
boxoffplateup:
lw x15, -2(x12)
beq x15, x10 mainloop # stop if wall
beq x15, x16 mainloop # stop if another box
beq x15, x21 mainloop # stop if another box-on-plate
addi x12, x12, -1
sw x19, 0(x12)
beq x15, x19, boxonplateplateup
sw x16, -1(x12)
jal x0, rendersetup
boxonplateplateup:
sw x21, -1(x12)
jal x0, rendersetup
down:
addi x17, x17, 8 # update bitflag
lw x15, 1(x12)
beq x15 x10 mainloop
beq x15, x16 boxmovedown
beq x15, x21 boxoffplatedown
addi x12, x12, 1
addi x13, x13, 1
jal x0, rendersetup
boxmovedown:
lw x15 2(x12)
beq x15 x10 mainloop
beq x15 x16 mainloop
beq x15, x21 mainloop # stop if another box-on-plate
addi x12, x12, 1
addi x13, x13, 1
beq x15, x19 boxonplatedown
sw x0, 0(x12)
sw x16, 1(x12)
jal x0, rendersetup
boxonplatedown:
sw x0, 0(x12)
sw x21, 1(x12)
jal x0, rendersetup
boxoffplatedown:
lw x15, 2(x12)
beq x15, x10 mainloop # stop if wall
beq x15, x16 mainloop # stop if another box
beq x15, x21 mainloop # stop if another box-on-plate
addi x12, x12, 1
sw x19, 0(x12)
beq x15, x19, boxonplateplatedown
sw x16, 1(x12)
jal x0, rendersetup
boxonplateplatedown:
sw x21, 1(x12)
jal x0, rendersetup
wincheck:
addi x24, x0, 0
beq x22, x24, wincheck1
addi x24, x0, 1
beq x22, x24, wincheck2
addi x24, x0, 2
beq x22, x24, wincheck3
addi x24, x0, 3
beq x22, x24, wincheck4
wincheck1:
lw x15 9(x0)
bne x15 x21 nvm
lw x15 26(x0)
bne x15 x21 nvm
addi x22, x22, 1
jal x0, start
wincheck2:
lw x15, 11(x0)
bne x15, x21, nvm
lw x15 48(x0)
bne x15 x21 nvm
lw x15 13(x0)
bne x15 x21 nvm
lw x15 41(x0)
bne x15 x21 nvm
lw x15 43(x0)
bne x15 x21 nvm
lw x15 60(x0)
bne x15 x21 nvm
lw x15 33(x0)
bne x15 x21 nvm
addi x22, x22, 1
jal x0, start
wincheck4:
lw x15 23(x0)
bne x15 x21 nvm
lw x15 24(x0)
bne x15 x21 nvm
lw x15 25(x0)
bne x15 x21 nvm
addi x22, x22, 1
jal x0, start
wincheck3:
bne x31, x0, hard
jal x0, wincheck3
hard:
addi x22, x22, 1
jal x0, start
done: