Compare commits

..

4 Commits
0.6.0 ... main

  1. 7
      dict/compress.py
  2. 5
      dict/solver.py
  3. 8
      inc/constants.asm
  4. 137
      inc/dict.asm
  5. 30
      inc/guess.asm
  6. 33
      inc/hints.asm
  7. 97
      inc/init.asm
  8. 47
      inc/input.asm
  9. 17
      inc/interrupts.asm
  10. 8
      inc/math.asm
  11. 38
      inc/messages.asm
  12. 22
      inc/oam.asm
  13. 113
      inc/search.asm
  14. 22
      inc/wincondition.asm
  15. 1
      maps/window-game.asm
  16. 8
      maps/window-help.asm
  17. 17
      tiles/sign-arrow.asm
  18. 17
      tiles/sign-slash.asm
  19. 121
      wordle.asm
  20. BIN
      wordle.gb

7
dict/compress.py

@ -1,4 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""
To fit the whole game into one memory bank, the dictionary is compressed.
Since only 2^5 combinations are needed to store 26 letters,
5 bits would be enough; for simplicity's sake, however, we take 6.
This way we can reduce the memory consumption by 20%.
"""
import struct import struct
def compress(in_path: str, out_path:str): def compress(in_path: str, out_path:str):

5
dict/solver.py

@ -1,4 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""
Even though I like Wordle, it becomes very exhausting to constantly
use your brain while developing. That's why this tool exists.
"""
import random import random
print("Welcome to this debug tool!") print("Welcome to this debug tool!")

8
inc/constants.asm

@ -1,4 +1,10 @@
;; Game Boy Constants ;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▄░█░▄▄▀█░▄▀▄░█░▄▄████░▄▄▀█▀▄▄▀█░██░████░▄▄▀█▀▄▄▀█░▄▄▀█░▄▄█▄░▄█░▄▄▀█░▄▄▀█▄░▄█░▄▄██
;; ██░█▀▀█░▀▀░█░█▄█░█░▄▄████░▄▄▀█░██░█░▀▀░████░████░██░█░██░█▄▄▀██░██░▀▀░█░██░██░██▄▄▀██
;; ██░▀▀▄█▄██▄█▄███▄█▄▄▄████░▀▀░██▄▄██▀▀▀▄████░▀▀▄██▄▄██▄██▄█▄▄▄██▄██▄██▄█▄██▄██▄██▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Hardware specific values and addresses
; Interrupt Flags ; Interrupt Flags
INTERRUPT_SETTINGS EQU $ffff INTERRUPT_SETTINGS EQU $ffff
INT_VBLANK_ON EQU %00000001 INT_VBLANK_ON EQU %00000001

137
inc/dict.asm

@ -1,15 +1,29 @@
; Selects a random word from the dictionary. ;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
; Sets the to be guessed and the revealed letter indices. ;; ██░▄▄▀██▄██▀▄▀█▄░▄██▄██▀▄▄▀█░▄▄▀█░▄▄▀█░▄▄▀█░██░██
;; ██░██░██░▄█░█▀██░███░▄█░██░█░██░█░▀▀░█░▀▀▄█░▀▀░██
;; ██░▀▀░█▄▄▄██▄███▄██▄▄▄██▄▄██▄██▄█▄██▄█▄█▄▄█▀▀▀▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; This file contains all the functions to interact with the dictionary.
;; Therefore, a random word can be selected and it is possible to check if an entered word exists.
; Selects a random entry from the dictionary and saves it.
; ;
; Note: The dict saves the 5 chars of the words in 4 bytes. ; Note:
; In the dictionary, entries with a word length of five are stored with only four bytes.
; n+0: 11111122 ; n+0: 11111122
; n+1: 22223333 ; n+1: 22223333
; n+2: 33444444 ; n+2: 33444444
; n+3: 55555500 ; n+3: 55555500
; ~> 00111111 00222222 00333333 00444444 00555555
; ;
; -> [random_number]: depends on the current random number
; <- [currend_word]: five characters, index starts at one
select_word: select_word:
ld de, current_word ld de, current_word
; determine the starting address of the dictionary entry
; (start address + random * word length)
ld a, [random_number+0] ld a, [random_number+0]
and %00011111 and %00011111
ld h, a ld h, a
@ -95,3 +109,120 @@ select_word:
ld [de], a ld [de], a
ret ret
; In order to check whether an entered word exists in the dictionary,
; it must first be compressed according to the dictionary.
; -> [current guess]: current rate attempt, stored in five bytes
; <- bc: first two bytes of the compression
; <- de: second two bytes of the compression
compress_guess:
call get_guess_offset
; first byte
ld a, [hl+] ; letter 1
and %00111111
sla a
sla a
ld b, a
ld a, [hl] ; letter 2
and %00110000
sra a
sra a
sra a
sra a
add a, b
ld d, a
; second byte
ld a, [hl+] ; letter 2
and %00001111
sla a
sla a
sla a
sla a
ld b, a
ld a, [hl] ; letter 3
and %00111100
sra a
sra a
add a, b
ld e, a
push de
; third byte
ld a, [hl+] ; letter 3
and %00000011
sla a
sla a
sla a
sla a
sla a
sla a
ld b, a
ld a, [hl+] ; letter 4
and %00111111
add a, b
ld d, a
; fourth byte
ld a, [hl] ; letter 5
and %00111111
sla a
sla a
ld e, a
pop bc
ret
; Try to find the current guess within the dictionary
; -> bc: first two bytes of the compression
; -> de: second two bytes of the compression
; <- a: whether the entry exists
find_guess:
ld hl, dictionary
.loop:
; check if the end of the dictionary is reached
push bc
ld bc, dictionary_end
ld a, h
cp a, b
jp nz, .not_eof
ld a, l
cp a, c
jp nz, .not_eof
pop bc
jp .return
.not_eof:
pop bc
ld a, [hl+]
cp a, b
jp nz, .add3
ld a, [hl+]
cp a, c
jp nz, .add2
ld a, [hl+]
cp a, d
jp nz, .add1
ld a, [hl+]
cp a, e
jp nz, .add0
ld a, 1
ret
.add3:
inc hl
.add2:
inc hl
.add1:
inc hl
.add0:
jp .loop
.return:
ld a, 0
ret

30
inc/guess.asm

@ -1,7 +1,17 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▄░█░██░█░▄▄█░▄▄█░▄▄█░███░█▀▄▄▀█░▄▄▀█░█▀██
;; ██░█▀▀█░██░█░▄▄█▄▄▀█▄▄▀█▄▀░▀▄█░██░█░▀▀▄█░▄▀██
;; ██░▀▀▄██▄▄▄█▄▄▄█▄▄▄█▄▄▄██▄█▄███▄▄██▄█▄▄█▄█▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Manages and displays the guessing attempts
; Updates the objects of the entered characters ; Updates the objects of the entered characters
; -> [guess_attempts]
; <- [obj_guess_letters]
update_guess_objects: update_guess_objects:
ld hl, obj_guess_letters ld hl, obj_guess_letters
ld de, guesses ld de, guess_attempts
ld a, $14 ld a, $14
call update_guess_row call update_guess_row
@ -20,9 +30,10 @@ update_guess_objects:
; Updates one line of entered characters ; Updates one line of entered characters
; -> hl: position within obj data ; -> hl: address of where to write obj data
; -> de: position within the guesses data ; -> de: address of the current guess
; -> a: vertical screen position ; -> a: vertical screen position
; <- [obj_guess_letters]
update_guess_row: update_guess_row:
push hl push hl
push hl push hl
@ -31,14 +42,14 @@ update_guess_row:
; distance between objects ; distance between objects
ld bc, 4 ld bc, 4
; vertical positions ; write all five vertical positions
ld [hl], a ld [hl], a
REPT 4 REPT 4
add hl, bc add hl, bc
ld [hl], a ld [hl], a
ENDR ENDR
; horizontal positions ; write all five horizontal positions
pop hl pop hl
inc hl inc hl
ld a, $30 ld a, $30
@ -49,7 +60,7 @@ REPT 4
ld [hl], a ld [hl], a
ENDR ENDR
; tile indices ; write all five tile indices
pop hl pop hl
inc hl inc hl
inc hl inc hl
@ -62,7 +73,7 @@ REPT 4
ld [hl], a ld [hl], a
ENDR ENDR
; palette info ; write all five palette info
pop hl pop hl
inc hl inc hl
inc hl inc hl
@ -80,7 +91,8 @@ ENDR
; Calculates the position of the current guess ; Calculates the address of the current guess attempt, using the number of the attempt
; -> [current_guess]: number of the current attempt
; <- hl ; <- hl
get_guess_offset: get_guess_offset:
ld a, [current_guess] ld a, [current_guess]
@ -88,7 +100,7 @@ get_guess_offset:
call multiply_ab call multiply_ab
ld b, 0 ld b, 0
ld c, a ld c, a
ld hl, guesses ld hl, guess_attempts
add hl, bc add hl, bc
ret ret

33
inc/hints.asm

@ -1,7 +1,19 @@
; Update the character hint objects ;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░██░██▄██░▄▄▀█▄░▄█░▄▄██
;; ██░▄▄░██░▄█░██░██░██▄▄▀██
;; ██░██░█▄▄▄█▄██▄██▄██▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Manages the obtained hints
; Updates the background layer with the obtained hints.
; Note: a row within the background map consists of 32 tiles
; -> [guess_hints]
; <- [BKG_LOC_9800]
update_hint_markings: update_hint_markings:
ld hl, BKG_LOC_9800 + 20*32 + 6 ; calculate the
ld de, guesses_hints ld hl, BKG_LOC_9800 + 32*20 + 6
ld de, guess_hints
ld b, 6 ld b, 6
.loop_outer: .loop_outer:
@ -30,8 +42,13 @@ update_hint_markings:
; Update the hint data ; Saves the obtained hints.
; -> [current_word]
; -> [current_guess]
; -> [guess]
mark_hints: mark_hints:
; To get the beginning of the clues,
; you can use the end of the guessing attempts
call get_guess_offset call get_guess_offset
push hl push hl
pop de pop de
@ -40,6 +57,7 @@ mark_hints:
ld b, 0 ld b, 0
.loop: .loop:
; update the hints char by char
ld a, [de] ld a, [de]
call hint_for_char call hint_for_char
ld [hl], a ld [hl], a
@ -53,9 +71,10 @@ mark_hints:
; Determines the hint for one character ; Determines the hint for one character.
; <- a: character value to check ; -> [current_word]
; <- b: index within the guess ; -> a: character value to check
; -> b: position within the guess
hint_for_char: hint_for_char:
push hl push hl
push bc push bc

97
inc/init.asm

@ -1,4 +1,18 @@
; Initialise everything for the main game state ;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; █▄░▄█░▄▄▀██▄██▄░▄██▄██░▄▄▀█░███▄██▄▄░█░▄▄▀█▄░▄██▄██▀▄▄▀█░▄▄▀██
;; ██░██░██░██░▄██░███░▄█░▀▀░█░███░▄█▀▄██░▀▀░██░███░▄█░██░█░██░██
;; █▀░▀█▄██▄█▄▄▄██▄██▄▄▄█▄██▄█▄▄█▄▄▄█▄▄▄█▄██▄██▄██▄▄▄██▄▄██▄██▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Establish a defined initial state
; Initialize everything for the main game state
; <- [current_state]
; <- [sub_state]
; <- [BKG_POS_X_REGISTER]
; <- [BKG_POS_Y_REGISTER]
; <- [LCD_CONTROL_REGISTER]
; <- [message_objs]
init_state_menu: init_state_menu:
ld a, STATE_MENU ld a, STATE_MENU
ld [current_state], a ld [current_state], a
@ -22,7 +36,17 @@ init_state_menu:
; Initialise everything for help screen ; Initialize everything for the help screen
; <- [current_state]
; <- [BKG_POS_X_REGISTER]
; <- [BKG_POS_Y_REGISTER]
; <- [WND_POS_X_REGISTER]
; <- [WND_POS_Y_REGISTER]
; <- [LCD_CONTROL_REGISTER]
; <- [current_word]
; <- [guess]
; <- [guess_hints]
; <- [message_objs]
init_state_help: init_state_help:
ld a, STATE_HELP ld a, STATE_HELP
ld [current_state], a ld [current_state], a
@ -45,24 +69,27 @@ init_state_help:
ld a, $70 ld a, $70
ld [WND_POS_Y_REGISTER], a ld [WND_POS_Y_REGISTER], a
; load the window data
ld hl, window_help ld hl, window_help
call load_window_map call load_window_map
; set a fixed game state ; Set a fixed and actually impossible game state.
; containing: [current_word], [guess] and [guess_hints]
;
; This is only possible because the memory space of these
; three variables is located directly after each other.
ld hl, current_word ld hl, current_word
ld de, help_word ld de, help_word
ld c, 65 ld c, 65
.set_gamestate: .copy_gamestate:
ld a, [de] ld a, [de]
ld [hl], a ld [hl], a
inc de inc de
inc hl inc hl
dec c dec c
jp nz, .set_gamestate jp nz, .copy_gamestate
; This is only possible because the memory space of these
; two variables is located directly after each other.
; for the rest we can use the default functions
call update_hint_markings call update_hint_markings
call update_guess_objects call update_guess_objects
@ -76,7 +103,21 @@ init_state_help:
; Initialise everything for the main game state ; Initialize everything for the main game state
; <- [current_state]
; <- [BKG_POS_X_REGISTER]
; <- [BKG_POS_Y_REGISTER]
; <- [WND_POS_X_REGISTER]
; <- [WND_POS_Y_REGISTER]
; <- [LCD_CONTROL_REGISTER]
; <- [current_word]
; <- [current_guess]
; <- [current_char]
; <- [guess]
; <- [guess_hints]
; <- [selected_letter_x]
; <- [selected_letter_y]
; <- [message_objs]
init_state_game: init_state_game:
; set the current state ; set the current state
ld a, STATE_GAME ld a, STATE_GAME
@ -98,22 +139,22 @@ init_state_game:
; set the window position ; set the window position
ld a, 3 ld a, 3
ld [WND_POS_X_REGISTER], a ld [WND_POS_X_REGISTER], a
ld a, $70 ld a, $68
ld [WND_POS_Y_REGISTER], a ld [WND_POS_Y_REGISTER], a
; load the window data ; load the window data
ld hl, window_game ld hl, window_game
call load_window_map call load_window_map
; initialise some more variables ; initialize some more variables
ld a, 0 ld a, 0
ld [selected_letter_x], a ld [selected_letter_x], a
ld [selected_letter_y], a ld [selected_letter_y], a
ld [current_guess], a ld [current_guess], a
ld [current_char], a ld [current_char], a
.reset_guesses .reset_guess_attempts
ld hl, guesses ld hl, guess_attempts
ld a, NULL ld a, NULL
ld d, 30 ld d, 30
.loop1: .loop1:
@ -122,7 +163,7 @@ init_state_game:
jp nz, .loop1 jp nz, .loop1
.reset_hints .reset_hints
ld hl, guesses_hints ld hl, guess_hints
ld a, TILE_WHITE ld a, TILE_WHITE
ld d, 30 ld d, 30
.loop2: .loop2:
@ -140,7 +181,9 @@ init_state_game:
; Switches to the lost state ; Switches to the state when the player has lost
; <- [current_state]
; <- [message_objs]
init_state_lost: init_state_lost:
ld a, STATE_LOST ld a, STATE_LOST
ld [current_state], a ld [current_state], a
@ -149,7 +192,9 @@ init_state_lost:
; Switches to the won state ; Switches to the state when the player has won
; <- [current_state]
; <- [message_objs]
init_state_won: init_state_won:
ld a, STATE_WON ld a, STATE_WON
ld [current_state], a ld [current_state], a
@ -158,7 +203,10 @@ init_state_won:
; Initialise the DMG color palettes ; Initialize the DMG color palettes
; <- [PALETTE_BKG_REGISTER]
; <- [PALETTE_OBJ0_REGISTER]
; <- [PALETTE_OBJ1_REGISTER]
init_palettes: init_palettes:
ld a, %10010011 ld a, %10010011
ld [PALETTE_BKG_REGISTER], a ld [PALETTE_BKG_REGISTER], a
@ -168,7 +216,9 @@ init_palettes:
; Load the tile data into the vram ; Copy the tile data into the vram
; -> [tiles]
; <- [TLS_LOC_8000]
load_tiles: load_tiles:
ld bc, tiles_start ld bc, tiles_start
ld hl, TLS_LOC_8000 ld hl, TLS_LOC_8000
@ -189,7 +239,9 @@ load_tiles:
; Load the background map into the vram ; Copy the background map into the vram
; -> [background]
; <- [BKG_LOC_9800]
load_background_map: load_background_map:
ld bc, background ld bc, background
ld hl, BKG_LOC_9800 ld hl, BKG_LOC_9800
@ -210,12 +262,13 @@ load_background_map:
; Load the window map into the vram ; Copy a window map into the vram
; -> hl ; -> hl: address of the desired window map
; <- [WND_LOC_9C00]
load_window_map: load_window_map:
ld bc, WND_LOC_9C00 ld bc, WND_LOC_9C00
ld d, 32 ld d, 32
ld e, 4 ld e, 5
.loop: .loop:
ld a, [hl] ld a, [hl]

47
inc/input.asm

@ -1,6 +1,14 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; █▄░▄█░▄▄▀█▀▄▄▀█░██░█▄░▄██
;; ██░██░██░█░▀▀░█░██░██░███
;; █▀░▀█▄██▄█░█████▄▄▄██▄███
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Handles the player inputs
; Read the current input state ; Read the current input state
; -> b: current keystates ; <- b: current keystates
; -> c: changed keys since last read ; <- c: changed keys since last read
read_input: read_input:
di di
@ -42,7 +50,8 @@ read_input:
; React on input within the menu ; React to input within the menu
; -> c: the changed keystate
handle_input_menu: handle_input_menu:
.check_movement: .check_movement:
ld a, c ld a, c
@ -54,9 +63,11 @@ handle_input_menu:
ld [sub_state], a ld [sub_state], a
and a, STATE_MENU_START and a, STATE_MENU_START
jp z, .switch_to_help jp z, .switch_to_help
.switch_to_start .switch_to_start
call show_message_menu_start call show_message_menu_start
jp .check_confirm jp .check_confirm
.switch_to_help .switch_to_help
call show_message_menu_help call show_message_menu_help
jp .check_confirm jp .check_confirm
@ -79,6 +90,8 @@ handle_input_menu:
; React to input within the help screen
; -> c: the changed keystate
handle_input_help: handle_input_help:
ld a, c ld a, c
and a, INPUT_START and a, INPUT_START
@ -89,8 +102,10 @@ handle_input_help:
; React on input within the main game ; React to input within the main game
; <- c: changed keys since last read ; -> c: the changed keystate
; <- [selected_letter_x]
; <- [selected_letter_y]
handle_input_game: handle_input_game:
ld a, [selected_letter_x] ld a, [selected_letter_x]
ld d, a ld d, a
@ -178,22 +193,26 @@ handle_input_game:
; React on input after a game round ; React to input after a game round,
; no matter if won or lost
; -> c: the changed keystate
handle_input_after: handle_input_after:
ld a, c ld a, c
and a, INPUT_START and a, INPUT_START
jp z, .nothing jp z, .nothing
call init_state_game call init_state_game
call clear_message call clear_message
.nothing .nothing
ret ret
; Add a character to the guess ; Select a character and add it to the current guess
; -> d: x position of the cursor ; -> d: x position of the cursor
; -> e: y position of the cursor ; -> e: y position of the cursor
; <- [current_guess]
; <- [current_char]
; <- [guess_attempts]
select_letter: select_letter:
push hl push hl
push af push af
@ -216,7 +235,7 @@ select_letter:
jp .return jp .return
.normal_letter: .normal_letter:
ld hl, guesses ld hl, guess_attempts
ld a, [current_guess] ld a, [current_guess]
ld b, 5 ld b, 5
call multiply_ab call multiply_ab
@ -243,14 +262,17 @@ select_letter:
; Delete the last letter ; Delete the last entered letter
; <- [current_guess]
; <- [current_char]
; <- [guess_attempts]
delete_letter: delete_letter:
push hl push hl
push af push af
push bc push bc
push de push de
ld hl, guesses ld hl, guess_attempts
ld a, [current_guess] ld a, [current_guess]
ld b, 5 ld b, 5
call multiply_ab call multiply_ab
@ -280,6 +302,9 @@ delete_letter:
; Update the object data for the alphabet cursor ; Update the object data for the alphabet cursor
; -> [selected_letter_x]
; -> [selected_letter_y]
; <- [obj_selected_letter]
update_cursor_objects: update_cursor_objects:
ld hl, obj_selected_letter ld hl, obj_selected_letter

17
inc/interrupts.asm

@ -1,4 +1,12 @@
; Interrupt handler for the vertical blanking ;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; █▄░▄█░▄▄▀█▄░▄█░▄▄█░▄▄▀█░▄▄▀█░██░█▀▄▄▀█▄░▄█░▄▄██
;; ██░██░██░██░██░▄▄█░▀▀▄█░▀▀▄█░██░█░▀▀░██░██▄▄▀██
;; █▀░▀█▄██▄██▄██▄▄▄█▄█▄▄█▄█▄▄██▄▄▄█░█████▄██▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Handle hardware interrupts
; Interrupt handler for the vertical blanking period
int_vblank: int_vblank:
push af push af
ld a, 1 ld a, 1
@ -11,7 +19,10 @@ int_vblank:
; Interrupt handler for the timer ; Interrupt handler for the timer
; ;
; Getting random numbers is hard, here we read the vertical position of the scanline, ; Getting random numbers is hard, here we read the vertical position of the scanline,
; save them periodically and use them to get something. ; save them periodically and use them to get something. This approach works,
; but is not unbalanced because the y position only goes from 0 to 153.
; To get around this, two values are stored as in a shift register
; and not all bits of this are used when determining the random number.
int_timer: int_timer:
push hl push hl
push af push af
@ -26,7 +37,7 @@ int_timer:
ld hl, LCD_POSITION_REGISTER ld hl, LCD_POSITION_REGISTER
ld a, [hl] ld a, [hl]
; save the new number ; save the old and new number
ld hl, random_number ld hl, random_number
ld [hl+], a ld [hl+], a
ld a, d ld a, d

8
inc/math.asm

@ -1,3 +1,11 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▀▄░█░▄▄▀█▄░▄█░█████
;; ██░█░█░█░▀▀░██░██░▄▄░██
;; ██░███░█▄██▄██▄██▄██▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Mathematical functions
; Multiply a and b ; Multiply a and b
; -> a, b ; -> a, b
; <- a ; <- a

38
inc/messages.asm

@ -1,4 +1,16 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▀▄░█░▄▄█░▄▄█░▄▄█░▄▄▀█░▄▄▄█░▄▄█░▄▄██
;; ██░█░█░█░▄▄█▄▄▀█▄▄▀█░▀▀░█░█▄▀█░▄▄█▄▄▀██
;; ██░███░█▄▄▄█▄▄▄█▄▄▄█▄██▄█▄▄▄▄█▄▄▄█▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; To give the user specific information, short messages could be displayed.
;; These are either permanent or can be provided with a timer.
;; Some of these messages are also used for highlighting in the menu.
; Highlights the menu entry "start game" ; Highlights the menu entry "start game"
; <- de: message address
; <- b: message timeout
show_message_menu_start: show_message_menu_start:
ld de, message_menu_start ld de, message_menu_start
ld b, 0 ld b, 0
@ -8,6 +20,8 @@ show_message_menu_start:
; Highlights the menu entry "how it works" ; Highlights the menu entry "how it works"
; <- de: message address
; <- b: message timeout
show_message_menu_help: show_message_menu_help:
ld de, message_menu_help ld de, message_menu_help
ld b, 0 ld b, 0
@ -17,15 +31,19 @@ show_message_menu_help:
; Inform that the current guess is not in the dictionary ; Inform that the current guess is not in the dictionary
; <- de: message address
; <- b: message timeout
show_message_unknown: show_message_unknown:
ld de, message_unknown ld de, message_unknown
ld b, 180 ld b, 180 ; three seconds
call show_message call show_message
ret ret
; Inform about the users victory ; Inform about the users victory
; <- de: message address
; <- b: message timeout
show_message_won: show_message_won:
ld de, message_won ld de, message_won
ld b, 0 ld b, 0
@ -35,6 +53,8 @@ show_message_won:
; Inform about the users loss ; Inform about the users loss
; <- de: message address
; <- b: message timeout
show_message_lost: show_message_lost:
ld de, message_lost ld de, message_lost
ld b, 0 ld b, 0
@ -57,9 +77,11 @@ ENDR
; Displays a message to the user ; Generic function to present a message to the user
; <- de ; -> de: message address
; <- b ; -> b: message timeout
; <- [obj_message_letters]
; <- [message_timeout]
show_message: show_message:
push hl push hl
push bc push bc
@ -85,7 +107,10 @@ show_message:
; Checks if the current message has expired ; Checks if the current message has expired and removes it when necessary
; -> [message_timeout]
; <- [message_timeout]
; <- [obj_message_letters]
check_message_timeout: check_message_timeout:
ld a, [message_timeout] ld a, [message_timeout]
cp a, 0 cp a, 0
@ -103,7 +128,8 @@ check_message_timeout:
; Clears the current message by overwriting with nothing ; Clears the current message by overwriting it with NULL values
; <- [obj_message_letters]
clear_message: clear_message:
ld de, message_clear ld de, message_clear
ld b, 0 ld b, 0

22
inc/oam.asm

@ -1,18 +1,32 @@
; Fill the whole oam copy with zero to prevent artifacts ;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▄▄░█░▄▄▀███▄█░▄▄█▀▄▀█▄░▄███░▄▄▀█▄░▄█▄░▄█░▄▄▀██▄██░▄▄▀█░██░█▄░▄█░▄▄████░▄▀▄░█░▄▄█░▄▀▄░█▀▄▄▀█░▄▄▀█░██░██
;; ██░███░█░▄▄▀███░█░▄▄█░█▀██░████░▀▀░██░███░██░▀▀▄██░▄█░▄▄▀█░██░██░██░▄▄████░█░█░█░▄▄█░█▄█░█░██░█░▀▀▄█░▀▀░██
;; ██░▀▀▀░█▄▄▄▄█░▀░█▄▄▄██▄███▄████░██░██▄███▄██▄█▄▄█▄▄▄█▄▄▄▄██▄▄▄██▄██▄▄▄████░███░█▄▄▄█▄███▄██▄▄██▄█▄▄█▀▀▀▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Contains functions to manage the object attribute memory (OAM).
;; We do not write to this area directly, but use a copy in the working memory.
;; During a v-blank, the OAM is updated using direct memory access (DMA).
;; Note: the Game Boy can only handle a total of 40 objects, and only 10 can be displayed on a line.
; Fill the whole OAM copy with zero to prevent artifacts
; <- [objects]
init_oam_copy: init_oam_copy:
ld b, 160 ld b, 160
ld a, 0 ld a, 0
ld hl, obj_start ld hl, obj_start
.zero_loop .copy_loop
ld [hl+], a ld [hl+], a
dec b dec b
jp nz, .zero_loop jp nz, .copy_loop
ret ret
; Write into OAM via DMA ; Update the OAM via DMA
; -> [objects]
; <- [OAM]
update_oam: update_oam:
; start DMA ; start DMA
ld a, $c0 ld a, $c0

113
inc/search.asm

@ -1,113 +0,0 @@
; Compresses the current guess to the same format as the dictionary
; <- bc
; <- de
compress_guess:
call get_guess_offset
; first byte
ld a, [hl+] ; letter 1
and %00111111
sla a
sla a
ld b, a
ld a, [hl] ; letter 2
and %00110000
sra a
sra a
sra a
sra a
add a, b
ld d, a
; second byte
ld a, [hl+] ; letter 2
and %00001111
sla a
sla a
sla a
sla a
ld b, a
ld a, [hl] ; letter 3
and %00111100
sra a
sra a
add a, b
ld e, a
push de
; third byte
ld a, [hl+] ; letter 3
and %00000011
sla a
sla a
sla a
sla a
sla a
sla a
ld b, a
ld a, [hl+] ; letter 4
and %00111111
add a, b
ld d, a
; fourth byte
ld a, [hl] ; letter 5
and %00111111
sla a
sla a
ld e, a
pop bc
ret
; Try to find the guess within the dictionary
; -> bc
; -> de
; <- a
find_guess:
ld hl, dictionary
.loop:
; check if the end of the dictionary is reached
push bc
ld bc, dictionary_end
ld a, h
cp a, b
jp nz, .not_eof
ld a, l
cp a, c
jp nz, .not_eof
pop bc
jp .return
.not_eof:
pop bc
ld a, [hl+]
cp a, b
jp nz, .add3
ld a, [hl+]
cp a, c
jp nz, .add2
ld a, [hl+]
cp a, d
jp nz, .add1
ld a, [hl+]
cp a, e
jp nz, .add0
ld a, 1
ret
.add3:
inc hl
.add2:
inc hl
.add1:
inc hl
.add0:
jp .loop
.return:
ld a, 0
ret

22
inc/wincondition.asm

@ -1,4 +1,17 @@
; Check if the guess is valid ;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░███░██▄██░▄▄▀███▀▄▀█▀▄▄▀█░▄▄▀█░▄▀██▄██▄░▄██▄██▀▄▄▀█░▄▄▀██
;; ██░█░█░██░▄█░██░███░█▀█░██░█░██░█░█░██░▄██░███░▄█░██░█░██░██
;; ██▄▀▄▀▄█▄▄▄█▄██▄████▄███▄▄██▄██▄█▄▄██▄▄▄██▄██▄▄▄██▄▄██▄██▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Functions to be able to detect the end of the game.
; Check if the guess attempt is valid
; -> [guess]
; -> [current_guess]
; -> [current_char]
; -> [obj_message]
; <- a: whether the test is valid or not
check_guess: check_guess:
push hl push hl
push af push af
@ -14,7 +27,6 @@ check_guess:
; and then search after it. ; and then search after it.
call compress_guess call compress_guess
call find_guess call find_guess
cp a, 1 cp a, 1
jp nz, .is_invalid jp nz, .is_invalid
@ -56,8 +68,10 @@ check_guess:
; Check the win conditions ; Check if guessed correctly and therefore won
; <- a ; -> [current_word]
; -> [current_guess]
; <- a: whether it is correct or not
check_win: check_win:
call get_guess_offset call get_guess_offset
ld bc, current_word ld bc, current_word

1
maps/window-game.asm

@ -1,4 +1,5 @@
; Window map while in game ; Window map while in game
DB $1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$1b,$01,$1b,$02,$1b,$03,$1b,$04,$1b,$05,$1b,$06,$1b,$07,$1b,$08,$1b,$09,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b DB $1b,$1b,$01,$1b,$02,$1b,$03,$1b,$04,$1b,$05,$1b,$06,$1b,$07,$1b,$08,$1b,$09,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$1b,$0a,$1b,$0b,$1b,$0c,$1b,$0d,$00,$0e,$1b,$0f,$1b,$10,$1b,$11,$1b,$12,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b DB $1b,$1b,$0a,$1b,$0b,$1b,$0c,$1b,$0d,$00,$0e,$1b,$0f,$1b,$10,$1b,$11,$1b,$12,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$1b,$13,$1b,$14,$1b,$15,$1b,$16,$1b,$17,$1b,$18,$1b,$19,$1b,$1a,$1b,$1e,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b DB $1b,$1b,$13,$1b,$14,$1b,$15,$1b,$16,$1b,$17,$1b,$18,$1b,$19,$1b,$1a,$1b,$1e,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b

8
maps/window-help.asm

@ -1,6 +1,6 @@
; Window map while within help ; Window map while within help
DB $1b,$1b,$13,$14,$01,$12,$14,$1b,$1b,$0e,$05,$17,$1b,$07,$01,$0d,$05,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$1b,$13,$05,$0c,$05,$03,$14,$1b,$03,$08,$05,$03,$0b,$1b,$17,$0f,$12,$04,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$1b,$02,$22,$01,$1b,$1b,$1b,$1b,$04,$05,$22,$13,$05,$0c,$05,$03,$14,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b DB $1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$1b,$13,$14,$01,$12,$14,$1b,$22,$0e,$05,$17,$1b,$07,$01,$0d,$05,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$1b,$13,$05,$0c,$05,$03,$14,$22,$03,$08,$05,$03,$0b,$1b,$17,$0f,$12,$04,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b

17
tiles/sign-arrow.asm

@ -0,0 +1,17 @@
; Slash
DB %00000000, \
%00000000, \
%00000000, \
%00000000, \
%00001000, \
%00001000, \
%00000100, \
%00000100, \
%01111110, \
%01111110, \
%00000100, \
%00000100, \
%00001000, \
%00001000, \
%00000000, \
%00000000

17
tiles/sign-slash.asm

@ -1,17 +0,0 @@
; Slash
DB %00000000, \
%00000000, \
%00000010, \
%00000010, \
%00000100, \
%00000100, \
%00001000, \
%00001000, \
%00010000, \
%00010000, \
%00100000, \
%00100000, \
%01000000, \
%01000000, \
%10000000, \
%10000000, \

121
wordle.asm

@ -1,5 +1,15 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░███░█▀▄▄▀█░▄▄▀█░▄▀█░██░▄▄██
;; ██░█░█░█░██░█░▀▀▄█░█░█░██░▄▄██
;; ██▄▀▄▀▄██▄▄██▄█▄▄█▄▄██▄▄█▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; The famous word puzzle
; Include hardware-specific constants
; used all over the code.
include "inc/constants.asm" include "inc/constants.asm"
;; Game specific constants ;; Game specific constants
; Game states ; Game states
STATE_MENU EQU %00000001 STATE_MENU EQU %00000001
@ -22,28 +32,28 @@ TILE_ENTER EQU $1e
TILE_RIGHT EQU $1f TILE_RIGHT EQU $1f
TILE_MISPLACED EQU $20 TILE_MISPLACED EQU $20
TILE_WRONG EQU $21 TILE_WRONG EQU $21
TILE_SLASH EQU $22 TILE_ARROW EQU $22
; Vertical blanking interrupt starting address ; Vertical blanking interrupt starting address
SECTION "ENTRY_VBLANK", ROM0[$0040] SECTION "ENTRY_VBLANK", ROM0[$0040]
jp int_vblank jp int_vblank ; used for game logic updates
; LCDC status interrupt starting address ; LCDC status interrupt starting address
SECTION "ENTRY_LCDCS", ROM0[$0048] SECTION "ENTRY_LCDCS", ROM0[$0048]
reti reti ; we don't use this interrupt
; Timer overflow interrupt starting address ; Timer overflow interrupt starting address
SECTION "ENTRY_TIMER", ROM0[$0050] SECTION "ENTRY_TIMER", ROM0[$0050]
jp int_timer jp int_timer ; used for generating randomness
; Serial transfer completion interrupt starting address ; Serial transfer completion interrupt starting address
SECTION "ENTRY_SERIAL", ROM0[$0058] SECTION "ENTRY_SERIAL", ROM0[$0058]
reti reti ; we don't use this interrupt
; Program starting address ; Program starting address
@ -54,7 +64,8 @@ SECTION "ENTRY_START", ROM0[$0100]
SECTION "MAIN", ROM0[$0150] SECTION "MAIN", ROM0[$0150]
main: main:
; turn the screen off until everything is initialised ; turn the screen off until everything is initialized,
; or wild glitches will appear
ld a, DISPLAY_OFF ld a, DISPLAY_OFF
ld [LCD_CONTROL_REGISTER], a ld [LCD_CONTROL_REGISTER], a
ld [LCD_STATUS_REGISTER], a ld [LCD_STATUS_REGISTER], a
@ -99,7 +110,6 @@ main_loop:
.within_vblank: .within_vblank:
call update_oam call update_oam
call read_input call read_input
ld a, [current_state] ld a, [current_state]
.in_menu: .in_menu:
@ -156,7 +166,6 @@ include "inc/dict.asm"
include "inc/input.asm" include "inc/input.asm"
include "inc/guess.asm" include "inc/guess.asm"
include "inc/hints.asm" include "inc/hints.asm"
include "inc/search.asm"
include "inc/messages.asm" include "inc/messages.asm"
include "inc/wincondition.asm" include "inc/wincondition.asm"
include "inc/interrupts.asm" include "inc/interrupts.asm"
@ -165,7 +174,10 @@ include "inc/interrupts.asm"
;; Game data ;; Game data
SECTION "DATA0", ROM0[$1000] SECTION "DATA0", ROM0[$1000]
; Tiles
;; Tiles
; Small 8x8 pixel images, which are addressable
; and will be used for sprite maps and objects.
tiles_start: tiles_start:
tile_null: tile_null:
include "tiles/plain-null.asm" include "tiles/plain-null.asm"
@ -185,15 +197,16 @@ tile_misplaced:
include "tiles/sign-misplaced.asm" include "tiles/sign-misplaced.asm"
tiles_wrong: tiles_wrong:
include "tiles/sign-wrong.asm" include "tiles/sign-wrong.asm"
tiles_slash: tiles_arrow:
include "tiles/sign-slash.asm" include "tiles/sign-arrow.asm"
tiles_logo: tiles_logo:
include "tiles/logo.asm" include "tiles/logo.asm"
tiles_end: tiles_end:
;; Maps
; Maps ; Each map defines a grid of tile addresses,
; which combined will form the desired image.
maps_start: maps_start:
background: background:
include "maps/background.asm" include "maps/background.asm"
@ -203,13 +216,20 @@ window_game:
include "maps/window-game.asm" include "maps/window-game.asm"
maps_end: maps_end:
;; Dictionary
; A list of known words to choose from.
dictionary: dictionary:
incbin "dict/en.dat" incbin "dict/en.dat"
dictionary_end: dictionary_end:
DB
; Help data ;; Help data
; The help screen will reuse the normal
; game mechanics to provide a manual
; how to play this game.
; Now following is hard coded-data
; to provide a set of information.
help_word: help_word:
DB $12, $09, $07, $08, $14 ; right DB $12, $09, $07, $08, $14 ; right
@ -230,7 +250,11 @@ help_guess_hints:
DB TILE_WHITE, TILE_WHITE, TILE_WHITE, TILE_WHITE, TILE_WHITE DB TILE_WHITE, TILE_WHITE, TILE_WHITE, TILE_WHITE, TILE_WHITE
; Messages ;; Messages
; This game uses a message system to
; provide feedback to the user.
; For this, nine objects are reserved
; and can be used at will.
message_clear: message_clear:
DB $00, $00, $00, $00 DB $00, $00, $00, $00
DB $00, $00, $00, $00 DB $00, $00, $00, $00
@ -265,41 +289,41 @@ message_menu_help:
DB $90, $80, 25, OBJ_ATTR_PALETTE1 ; Y DB $90, $80, 25, OBJ_ATTR_PALETTE1 ; Y
message_unknown: message_unknown:
DB $74, $38, 21, OBJ_ATTR_PALETTE1 ; U DB $78, $38, 21, OBJ_ATTR_PALETTE1 ; U
DB $74, $40, 14, OBJ_ATTR_PALETTE1 ; N DB $78, $40, 14, OBJ_ATTR_PALETTE1 ; N
DB $74, $48, 11, OBJ_ATTR_PALETTE1 ; k DB $78, $48, 11, OBJ_ATTR_PALETTE1 ; k
DB $74, $50, 14, OBJ_ATTR_PALETTE1 ; N DB $78, $50, 14, OBJ_ATTR_PALETTE1 ; N
DB $74, $58, 15, OBJ_ATTR_PALETTE1 ; O DB $78, $58, 15, OBJ_ATTR_PALETTE1 ; O
DB $74, $60, 23, OBJ_ATTR_PALETTE1 ; W DB $78, $60, 23, OBJ_ATTR_PALETTE1 ; W
DB $74, $68, 14, OBJ_ATTR_PALETTE1 ; N DB $78, $68, 14, OBJ_ATTR_PALETTE1 ; N
DB $00, $00, 0, 0 DB $00, $00, 0, 0
DB $00, $00, 0, 0 DB $00, $00, 0, 0
message_won: message_won:
DB $74, $38, 25, OBJ_ATTR_PALETTE1 ; Y DB $78, $38, 25, OBJ_ATTR_PALETTE1 ; Y
DB $74, $40, 15, OBJ_ATTR_PALETTE1 ; O DB $78, $40, 15, OBJ_ATTR_PALETTE1 ; O
DB $74, $48, 21, OBJ_ATTR_PALETTE1 ; U DB $78, $48, 21, OBJ_ATTR_PALETTE1 ; U
DB $74, $58, 23, OBJ_ATTR_PALETTE1 ; W DB $78, $58, 23, OBJ_ATTR_PALETTE1 ; W
DB $74, $60, 15, OBJ_ATTR_PALETTE1 ; O DB $78, $60, 15, OBJ_ATTR_PALETTE1 ; O
DB $74, $68, 14, OBJ_ATTR_PALETTE1 ; N DB $78, $68, 14, OBJ_ATTR_PALETTE1 ; N
DB $00, $00, 0, 0 DB $00, $00, 0, 0
DB $00, $00, 0, 0 DB $00, $00, 0, 0
DB $00, $00, 0, 0 DB $00, $00, 0, 0
message_lost: message_lost:
DB $74, $30, 9, OBJ_ATTR_PALETTE1 ; I DB $78, $30, 9, OBJ_ATTR_PALETTE1 ; I
DB $74, $38, 20, OBJ_ATTR_PALETTE1 ; T DB $78, $38, 20, OBJ_ATTR_PALETTE1 ; T
DB $74, $40, 19, OBJ_ATTR_PALETTE1 ; S DB $78, $40, 19, OBJ_ATTR_PALETTE1 ; S
DB $74, $50, 0, OBJ_ATTR_PALETTE1 ; guess[0] DB $78, $50, 0, OBJ_ATTR_PALETTE1 ; guess[0]
DB $74, $58, 0, OBJ_ATTR_PALETTE1 ; guess[1] DB $78, $58, 0, OBJ_ATTR_PALETTE1 ; guess[1]
DB $74, $60, 0, OBJ_ATTR_PALETTE1 ; guess[2] DB $78, $60, 0, OBJ_ATTR_PALETTE1 ; guess[2]
DB $74, $68, 0, OBJ_ATTR_PALETTE1 ; guess[3] DB $78, $68, 0, OBJ_ATTR_PALETTE1 ; guess[3]
DB $74, $70, 0, OBJ_ATTR_PALETTE1 ; guess[4] DB $78, $70, 0, OBJ_ATTR_PALETTE1 ; guess[4]
DB $00, $00, 0, 0 DB $00, $00, 0, 0
; Address reservations within the working ram ;; Address reservations within the working ram
SECTION "RAM", WRAM0 SECTION "RAM", WRAM0
; The first 160 Bytes are reserved for a copy ; The first 160 Bytes are reserved for a copy
; of the OAM data, which will be updated via DMA. ; of the OAM data, which will be updated via DMA.
@ -319,7 +343,7 @@ obj_dma_padding:
vblank_flag: vblank_flag:
DB DB
; Saves the current 16bit random number ; Saves the current random number consisting of 16 bits
random_number: random_number:
DS 2 DS 2
@ -327,19 +351,19 @@ random_number:
input_state: input_state:
DB DB
; Saves the current game state ; Saves the current game state (see STATE constants)
current_state: current_state:
DB DB
; Saves the state in the submenu ; Saves the subordinate state (see STATE constants)
sub_state: sub_state:
DB DB
; Number of the current guess ; Number of the current guess (0..5)
current_guess: current_guess:
DB DB
; Position within the current guess ; Position within the current guess (0..4)
current_char: current_char:
DB DB
@ -348,21 +372,22 @@ current_word:
DS 5 DS 5
; The guess attempts ; The guess attempts
guesses: guess_attempts:
DS 30 DS 30
; The corresponding hints ; The corresponding hints
guesses_hints: guess_hints:
DS 30 DS 30
; Message timeout ; Message timeout (remaining number of frames)
message_timeout: message_timeout:
DB DB
; Horizontal position of the letter selection ; Horizontal position of the letter selection within the alphabet grid
selected_letter_x: selected_letter_x:
DB DB
; Vertical position of the letter selection ; Vertical position of the letter selection within the alphabet grid
selected_letter_y: selected_letter_y:
DB DB

BIN
wordle.gb

Binary file not shown.
Loading…
Cancel
Save