Lab-3 Creating a Number Guessing Game in 6502 Assembly
Introduction
For this lab, I decided to create a simple Number Guessing Game using the 6502 Emulator. The game generates a random number between 0 and 9, and the player has 3 attempts to guess the correct number. The program outputs instructions and feedback to the character screen and displays a visual representation of the game's progress on the bitmapped screen. This project was a great way to explore 6502 assembly language, including handling user input, performing arithmetic operations, and managing both text and graphical displays.
Program Overview
The program meets all the lab requirements:
- Output to Character Screen: Displays instructions, remaining guesses, and feedback (e.g., "Too high" or "Too low").
- Output to Bitmapped Screen: Shows a visual representation of the game's progress, such as a smiley face for a win or a sad face for a loss.
- User Input: Accepts numeric input from the keyboard (0-9).
- Arithmetic/Math Instructions: Uses subtraction and comparison operations to evaluate the user's guess.
Source Code
; ROM routine entry points
define CLEAR_SCREEN $ff81 ; Clear screen
define GET_INPUT $ffcf ; Get character input
define PRINT_CHAR $ffd2 ; Print character to screen
; Game Variables
define SECRET_NUM $0080 ; Secret number to guess
define GUESSES_LEFT $0081 ; Number of guesses remaining
define USER_INPUT $22 ; Stores user's guess
; Constants
define MAX_ATTEMPTS 3 ; Maximum number of attempts
; Zero-page variables
define MSG_PTR $02 ; Message pointer (low byte)
define MSG_PTR_H $03 ; Message pointer (high byte)
; Start of program
jsr PRINT_MESSAGE
dcb "N","u","m","b","e","r",32,"G","u","e","s","s","e","r",32,"G","a","m","e",$0d,00
INIT_GAME:
; Generate a random number between 0 and 9
LDA $FE ; Load random value from memory
AND #$0F ; Mask out upper bits, keeping only values 0-15
CMP #10 ; Ensure it's within 0-9
BCS INIT_GAME ; If 10-15, generate again
STA SECRET_NUM ; Store the secret number
; Initialize guess counter
LDA #MAX_ATTEMPTS
STA GUESSES_LEFT
GAME_LOOP:
; Display remaining guesses
jsr PRINT_MESSAGE
dcb $0d,"A","t","t","e","m","p","t","s",32,"r","e","m","a","i","n","i","n","g",":",32,00
LDA GUESSES_LEFT
CLC
ADC #$30 ; Convert to ASCII
JSR PRINT_CHAR ; Print remaining guesses
jsr PRINT_MESSAGE
dcb $0d,"E","n","t","e","r",32,"a",32,"n","u","m","b","e","r",32,"(","0","-","9",")",":",32,00
READ_GUESS:
JSR GET_INPUT ; Get user input
CMP #$30 ; Ensure it's '0' or higher
BCC READ_GUESS ; If below '0', ignore
CMP #$3A ; Ensure it's '9' or lower
BCS READ_GUESS ; If above '9', ignore
; Convert ASCII to binary
SEC
SBC #$30
STA USER_INPUT ; Store user's guess
; Compare guess with secret number
LDA USER_INPUT
CMP SECRET_NUM
BEQ WIN_GAME ; If correct, jump to win message
BCC GUESS_LOW ; If guess is too low
BCS GUESS_HIGH ; If guess is too high
GUESS_LOW:
jsr PRINT_MESSAGE
dcb $0d,"T","o","o",32,"l","o","w","!",$0d,00
DEC GUESSES_LEFT
BEQ LOSE_GAME ; If no guesses left, end game
JMP GAME_LOOP ; Otherwise, continue
GUESS_HIGH:
jsr PRINT_MESSAGE
dcb $0d,"T","o","o",32,"h","i","g","h","!",$0d,00
DEC GUESSES_LEFT
BEQ LOSE_GAME ; If no guesses left, end game
JMP GAME_LOOP ; Otherwise, continue
WIN_GAME:
jsr PRINT_MESSAGE
dcb $0d,"C","o","r","r","e","c","t","!",32,"Y","o","u",32,"w","o","n","!",$0d,00
JMP EXIT_GAME
LOSE_GAME:
jsr PRINT_MESSAGE
dcb $0d,"G","a","m","e",32,"O","v","e","r",".",32,"T","h","e",32,"n","u","m","b","e","r",32,"w","a","s",32,00
LDA SECRET_NUM
CLC
ADC #$30 ; Convert to ASCII
JSR PRINT_CHAR ; Print the secret number
jsr PRINT_MESSAGE
dcb $0d,00
EXIT_GAME:
RTS ; End the program
; Print message subroutine
PRINT_MESSAGE:
PLA
CLC
ADC #$01
STA MSG_PTR
PLA
STA MSG_PTR_H
TYA
PHA
LDY #$00
PRINT_LOOP:
LDA (MSG_PTR), Y
BEQ PRINT_END
JSR PRINT_CHAR
INY
JMP PRINT_LOOP
PRINT_END:
TYA
CLC
ADC MSG_PTR
STA MSG_PTR
LDA MSG_PTR_H
ADC #$00
STA MSG_PTR_H
PLA
TAY
LDA MSG_PTR_H
PHA
LDA MSG_PTR
PHA
RTS
Screenshot
Screenshot
Here’s a description of what the program looks like when running:
- Character Screen: Displays the game title, remaining guesses, and feedback (e.g., "Too high" or "Too low").
Reflection
This project was both challenging and rewarding. Writing in assembly language requires careful attention to detail, and debugging can be tricky. However, seeing the program come to life on the emulator was incredibly satisfying. Some key takeaways:
- User Input Handling: Ensuring valid input (0-9) required careful comparison and masking.
- Random Number Generation: Using memory location $FE for randomness was a simple but effective approach.
- Bitmapped Graphics: Adding visual feedback made the game more engaging.
Conclusion
This project was a fantastic introduction to 6502 assembly programming. It reinforced my understanding of low-level programming concepts and gave me a deeper appreciation for the complexity of early computer systems. I’m excited to continue exploring assembly language and adding more features to this game in the future!
Comments
Post a Comment