Assembly language code
Tags: lab2
Published: 2024-02-05 16:32:09

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

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

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

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

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

        dec NEW_COL     ; ... if yes, decrement COL
        rts

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

        dec NEW_ROW     ; ... if yes, decrement ROW
        rts

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

        inc NEW_COL     ; ... if yes, increment COL
        rts

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

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            

; 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xt8uylnnzqmljfhsgih.png)

Moving: 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nxfbzt9bf4qm1ro6nvu2.png)

Finished: the red mark changes to green

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fr4o2b24htcb95karonm.png)

Output: 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djx0u6ko3xvao0h335zt.png)

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.