DEV Community

Heavendeep Kaur Munjal
Heavendeep Kaur Munjal

Posted on

Assembly language code

About:
maze game using zero-page variables for efficient memory access and execution speed. These variables include ROW, COL, DRAWN_ROW, MAZE_L, MAZE_H, PLAYER_L, PLAYER_H, TARGET_L, and TARGET_H. ROW and COL track the player's current position in the maze, while DRAWN_ROW counts the drawn rows on the screen. MAZE_L and MAZE_H point to where the maze is drawn, and PLAYER_L and PLAYER_H point to the player's position. TARGET_L and TARGET_H point to the target position the player aims to reach. Zero-page variables optimize memory usage and speed up access to critical data during execution, crucial for game performance. The code initializes the game, manages player movements, checks for collisions, and handles game completion. It uses ROM routines for screen initialization and displays instructions and completion messages. Maze data, help text, and completion messages are provided in the code. The game loop continuously updates the player's position, receives user input, checks for collisions, and displays appropriate messages upon game completion. By leveraging zero-page variables, the code enhances memory management and execution efficiency, essential for smooth gameplay in assembly-based maze games.

Code:
; zero-page variables
define NEW_ROW $20 ; current row
define NEW_COL $21 ; current column
define NEW_DRAWN_ROW $22 ; number of drawn rows
define NEW_MAZE_L $14 ; a pointer that points to where the maze will
define NEW_MAZE_H $15 ; be drawn
define NEW_PLAYER_L $10 ; a pointer that points to the player in the
; screen
define NEW_PLAYER_H $11
define NEW_TARGET_L $12 ; a pointer that points to the target position
define NEW_TARGET_H $13 ; where the player wants to proceed

; constants
define PATH $03 ; path color
define PLAYER $0e ; player color
define HEIGHT 7 ; height of the maze
define WIDTH 7 ; width of the maze

; ROM routine
define SCINIT $ff81 ; initialize/clear screen

    jsr printHelp
    jsr drawMaze
    jsr gameInit
    jsr gameLoop
Enter fullscreen mode Exit fullscreen mode

printHelp: ldy #$00 ; print instructions on the screen
pHelpLoop: lda help,y
beq done
sta $f000,y
iny
bne pHelpLoop

gameInit: lda #$01 ; initialize ROW, COL to make the player
sta NEW_ROW ; starting at $0221 of the screen
sta NEW_COL
rts

gameLoop: jsr updatePosition
jsr getkey
jsr checkCollision
ldx #$00 ; clear out the key buffer
stx $ff
jmp gameLoop

updatePosition: ldy NEW_ROW ; load PLAYER pointer with ROW
lda table_low,y
sta NEW_PLAYER_L
lda table_high,y
sta NEW_PLAYER_H

    ldy NEW_COL     ; place the player at (POINTER + COL)
    lda #PLAYER
    sta (NEW_PLAYER_L),y
    rts
Enter fullscreen mode Exit fullscreen mode

getkey: lda $ff ; get the input key

    cmp #$80    ; allow arrow keys only
    bmi getkey
    cmp #$84
    bpl getkey

    pha     ; save the accumulator
    lda #PATH   ; set color of the current position to PATH
    sta (NEW_PLAYER_L),y
    pla     ; restore accumulator

    cmp #$80    ; check key is up
    bne checkRight

    dec NEW_ROW     ; ... if yes, decrement ROW
    rts
Enter fullscreen mode Exit fullscreen mode

checkRight: cmp #$81 ; check if key is right
bne checkDown
inc NEW_COL ; ... if yes, increment COL
rts

checkDown: cmp #$82 ; check if key is down
bne checkLeft
inc NEW_ROW ; ... if yes, increment ROW
rts

checkLeft: cmp #$83 ; check if key is left
bne done
dec NEW_COL ; ... if yes, decrement COL
rts

done: rts ; break out of a loop or subroutine

checkCollision: ldy NEW_ROW ; load TARGET pointer with ROW
lda table_low,y
sta NEW_TARGET_L
lda table_high,y
sta NEW_TARGET_H

    ldy NEW_COL     ; load the color from the target
    lda (NEW_TARGET_L),y; at (POINTER + COL)

    cmp #$01
    beq done
    cmp #$03
    beq done
    cmp #$0a
    beq gameComplete

    lda #$00
    sta (NEW_TARGET_L),y

    lda $ff
    cmp #$80    ; if input key was up...
    bne ifRight

    inc NEW_ROW     ; ... if yes, increment ROW
    rts
Enter fullscreen mode Exit fullscreen mode

ifRight: cmp #$81 ; if input key was right...
bne ifDown

    dec NEW_COL     ; ... if yes, decrement COL
    rts
Enter fullscreen mode Exit fullscreen mode

ifDown: cmp #$82 ; if input key was down...
bne ifLeft

    dec NEW_ROW     ; ... if yes, decrement ROW
    rts
Enter fullscreen mode Exit fullscreen mode

ifLeft: cmp #$83 ; if input key was left...
bne done

    inc NEW_COL     ; ... if yes, increment COL
    rts
Enter fullscreen mode Exit fullscreen mode

gameComplete: jsr SCINIT
ldy #$00 ; print game completion message on the screen
pGameComplete: lda complete,y
beq done
sta $f000,y
iny
bne pGameComplete
brk

drawMaze: lda #$21 ; a pointer pointing to the first pixel
sta NEW_MAZE_L ; of the screen
lda #$02
sta NEW_MAZE_H

    lda #$00    ; number of drawn rows
    sta NEW_DRAWN_ROW

    ldx #$00    ; maze data index
    ldy #$00    ; column index
Enter fullscreen mode Exit fullscreen mode

draw: lda maze_data,x
sta (NEW_MAZE_L), y
inx
iny
cpy #WIDTH ; compare with the number of WIDTH
bne draw ; if not, keep drawing the column

    inc NEW_DRAWN_ROW   ; increment the number of row
    lda #HEIGHT
    cmp NEW_DRAWN_ROW   ; compare with the number of HEIGHT
    beq done

    lda NEW_MAZE_L
    clc
    adc #$20    ; add 32(0x0020) to increment the row
    sta NEW_MAZE_L  ; of the pixel
    lda NEW_MAZE_H
    adc #$00
    sta NEW_MAZE_H

    ldy #$00    ; reset the column index for the new row
    beq draw            
Enter fullscreen mode Exit fullscreen mode

; help text message
help:
dcb "P","l","a","y",32,"w","i","t","h",32,"a","r","r","o","w"
dcb 32,"k","e","y","s",32,"t","o",32,"c","o","n","t","r","o","l",10
dcb 00

; game complete message
complete:
dcb "Y","o","u",32,"c","o","m", "p", "l", "e", "t", "e", "d", 32
dcb "t","h","e",32,"g","a","m","e","!"
dcb 00

; maze map data
maze_data:
dcb 01,00,01,00,01,01,01
dcb 01,01,01,00,00,00,01
dcb 00,00,01,00,01,00,01
dcb 01,00,01,00,01,01,01
dcb 01,00,01,00,01,00,01
dcb 01,00,01,00,01,00,01
dcb 01,01,01,01,01,00,10

; these two tables contain the high and low bytes
; of the addresses of the start of each row
table_high:
dcb $02,$02,$02,$02,$02,$02,$02,$02
dcb $03,$03,$03,$03,$03,$03,$03,$03
dcb $04,$04,$04,$04,$04,$04,$04,$04
dcb $05,$05,$05,$05,$05,$05,$05,$05

table_low:
dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
dcb $00,$20,$40,$60,$80,$a0,$c0,$e0

User input: keyboard keys

Image description

Moving:
Image description

Finished: the red mark changes to green

Image description

Output:

Image description

Summary:
It was a very fun lab. I have made maze before but with python and using assembly language was a game changer for me. This could be made with more difficult mazes and level up with time.

Top comments (0)