Compare commits

..

13 Commits
0.5.1 ... main

  1. 4
      Readme.md
  2. 21
      dict/compress.py
  3. BIN
      dict/en.dat
  4. 141
      dict/solver.py
  5. 8
      inc/constants.asm
  6. 137
      inc/dict.asm
  7. 30
      inc/guess.asm
  8. 33
      inc/hints.asm
  9. 160
      inc/init.asm
  10. 188
      inc/input.asm
  11. 17
      inc/interrupts.asm
  12. 8
      inc/math.asm
  13. 66
      inc/messages.asm
  14. 22
      inc/oam.asm
  15. 113
      inc/search.asm
  16. 22
      inc/wincondition.asm
  17. 70
      maps/background.asm
  18. 6
      maps/window-game.asm
  19. 6
      maps/window-help.asm
  20. 36
      maps/window.asm
  21. 17
      tiles/sign-arrow.asm
  22. 210
      wordle.asm
  23. BIN
      wordle.gb

4
Readme.md

@ -1,14 +1,14 @@
Wordle
======
In this game, a word with five letters has to be guessed. For this purpose, six words can be tried. After each attempt, every letter is shown whether it is not present, present and in the right place, or present but not in the right place.
In this game, a word with five letters has to be guessed. For this purpose, six words can be tried. After each attempt, every character is shown whether it is not present, present and in the right place, or present but not in the right place.
Controls
---------
```
START Starts a new game
SELECT Selects a letter
SELECT Confirms the entered word
→ ↓ ← ↑ Moves the cursor
A Selects a character
B Deletes the last character

21
dict/compress.py

@ -1,4 +1,11 @@
#!/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
def compress(in_path: str, out_path:str):
@ -13,13 +20,13 @@ def compress(in_path: str, out_path:str):
if len(set(list(word))) != len(word):
continue
a = (((ord(word[0])-0x61) << 2) & 0x00fc) | \
(((ord(word[1])-0x61) >> 4) & 0x0003)
b = (((ord(word[1])-0x61) << 4) & 0x00f0) | \
(((ord(word[2])-0x61) >> 2) & 0x000f)
c = (((ord(word[2])-0x61) << 6) & 0x00c0) | \
(((ord(word[3])-0x61) >> 0) & 0x003f);
d = (((ord(word[4])-0x61) << 2) & 0x00fc)
a = (((ord(word[0])-0x60) << 2) & 0x00fc) | \
(((ord(word[1])-0x60) >> 4) & 0x0003)
b = (((ord(word[1])-0x60) << 4) & 0x00f0) | \
(((ord(word[2])-0x60) >> 2) & 0x000f)
c = (((ord(word[2])-0x60) << 6) & 0x00c0) | \
(((ord(word[3])-0x60) >> 0) & 0x003f);
d = (((ord(word[4])-0x60) << 2) & 0x00fc)
pack = struct.pack("BBBB", a, b, c, d)
data.write(pack)

BIN
dict/en.dat

Binary file not shown.

141
dict/solver.py

@ -0,0 +1,141 @@
#!/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
print("Welcome to this debug tool!")
print("Just follow the instructions,")
print("however the input syntax is special.")
print()
print("A letter following by a !:")
print(" this letter doesn't exist at all")
print()
print("A letter following by a ?:")
print(" this letter exits but is misplaced")
print()
print("For example:")
print("li!n?u!s!")
print()
print("Which translates into:")
print(" the first letter is an l")
print(" the word doesn't contain an i")
print(" the letter n is misplaced")
print(" the word doesn't contain an u")
print(" the word doesn't contain an s")
print()
print()
def determine_guess(words: list, tries: int) -> str:
""" Selects one word from the remaining dictionary """
if tries > 0:
return random.choice(words) # good enough
else:
return "intro"
def is_letter(char: str) -> bool:
""" Checks if a character exists within the alphabet """
return char >= "a" and char <= "z"
def get_next_letter(response: str, current_index: int) -> str:
""" Returns the following letter """
next_index = current_index + 1
if next_index >= len(response):
return None
return response[next_index]
def update_hints(hints: dict, response: str) -> dict:
"""
Reads the user supplied response and translates it into logical assumptions
The hints dictionary contains single letters as keys,
where the values are lists of possible locations for this letter.
When the user enters o! we know that 'o' has no valid position within the searched word.
dict['o'] -> []
When a letter is marked as misplaced, this eliminates possible positions.
dict['k'] -> [0, 1, 3, 4]
Lastly, correct letters are greatly reducing the possibilities.
dict['m'] -> [2]
"""
response = response.lower()
position = 0
for i in range(len(response)):
letter = response[i]
if not is_letter(letter):
continue
if not letter in hints:
hints[letter] = [0, 1, 2, 3, 4]
next_letter = get_next_letter(response, i)
if not next_letter or is_letter(next_letter):
hints[letter] = [position]
elif next_letter == "?":
hints[letter] = [l for l in hints[letter] if l != position]
elif next_letter == "!":
hints[letter] = []
else:
print("invalid input syntax")
position += 1
return hints
def narrow_dictionary(words: list, hints: dict) -> list:
""" Apply the hints to narrow down the possibilities """
invalid_words = []
for word in words:
for key in hints:
pos = word.find(key)
# skip optional hints
if pos == -1 and len(hints[key]) == 0:
continue
if not pos in hints[key]:
invalid_words.append(word)
break
return list(filter(lambda w: w not in invalid_words, words))
with open("en.txt", "r") as handle:
words = handle.readlines()
words = list(map(lambda l: l.strip(), words))
hints = {}
tries = 0
while tries < 6:
guess = determine_guess(words, tries)
print(f"{len(words)} words remaining")
print(f"input: {guess}")
response = input("response: ")
print()
hints = update_hints(hints, response)
words = narrow_dictionary(words, hints)
if len(words) == 1:
print(f"It must be {words[0]}")
exit()
if len(words) == 0:
print("There are no words left, please check your input.")
exit()
tries += 1
print("I hope the last try was successful.")
print()

8
inc/constants.asm

@ -1,4 +1,10 @@
;; Game Boy Constants
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▄░█░▄▄▀█░▄▀▄░█░▄▄████░▄▄▀█▀▄▄▀█░██░████░▄▄▀█▀▄▄▀█░▄▄▀█░▄▄█▄░▄█░▄▄▀█░▄▄▀█▄░▄█░▄▄██
;; ██░█▀▀█░▀▀░█░█▄█░█░▄▄████░▄▄▀█░██░█░▀▀░████░████░██░█░██░█▄▄▀██░██░▀▀░█░██░██░██▄▄▀██
;; ██░▀▀▄█▄██▄█▄███▄█▄▄▄████░▀▀░██▄▄██▀▀▀▄████░▀▀▄██▄▄██▄██▄█▄▄▄██▄██▄██▄█▄██▄██▄██▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Hardware specific values and addresses
; Interrupt Flags
INTERRUPT_SETTINGS EQU $ffff
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+1: 22223333
; n+2: 33444444
; 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:
ld de, current_word
; determine the starting address of the dictionary entry
; (start address + random * word length)
ld a, [random_number+0]
and %00011111
ld h, a
@ -95,3 +109,120 @@ select_word:
ld [de], a
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
; -> [guess_attempts]
; <- [obj_guess_letters]
update_guess_objects:
ld hl, obj_guess_letters
ld de, guesses
ld de, guess_attempts
ld a, $14
call update_guess_row
@ -20,9 +30,10 @@ update_guess_objects:
; Updates one line of entered characters
; -> hl: position within obj data
; -> de: position within the guesses data
; -> hl: address of where to write obj data
; -> de: address of the current guess
; -> a: vertical screen position
; <- [obj_guess_letters]
update_guess_row:
push hl
push hl
@ -31,14 +42,14 @@ update_guess_row:
; distance between objects
ld bc, 4
; vertical positions
; write all five vertical positions
ld [hl], a
REPT 4
add hl, bc
ld [hl], a
ENDR
; horizontal positions
; write all five horizontal positions
pop hl
inc hl
ld a, $30
@ -49,7 +60,7 @@ REPT 4
ld [hl], a
ENDR
; tile indices
; write all five tile indices
pop hl
inc hl
inc hl
@ -62,7 +73,7 @@ REPT 4
ld [hl], a
ENDR
; palette info
; write all five palette info
pop 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
get_guess_offset:
ld a, [current_guess]
@ -88,7 +100,7 @@ get_guess_offset:
call multiply_ab
ld b, 0
ld c, a
ld hl, guesses
ld hl, guess_attempts
add hl, bc
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:
ld hl, BKG_LOC_9800 + 20*32 + 6
ld de, guesses_hints
; calculate the
ld hl, BKG_LOC_9800 + 32*20 + 6
ld de, guess_hints
ld b, 6
.loop_outer:
@ -30,8 +42,13 @@ update_hint_markings:
; Update the hint data
; Saves the obtained hints.
; -> [current_word]
; -> [current_guess]
; -> [guess]
mark_hints:
; To get the beginning of the clues,
; you can use the end of the guessing attempts
call get_guess_offset
push hl
pop de
@ -40,6 +57,7 @@ mark_hints:
ld b, 0
.loop:
; update the hints char by char
ld a, [de]
call hint_for_char
ld [hl], a
@ -53,9 +71,10 @@ mark_hints:
; Determines the hint for one character
; <- a: character value to check
; <- b: index within the guess
; Determines the hint for one character.
; -> [current_word]
; -> a: character value to check
; -> b: position within the guess
hint_for_char:
push hl
push bc

160
inc/init.asm

@ -1,30 +1,134 @@
; 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:
ld a, STATE_MENU
ld [current_state], a
ld a, STATE_MENU_START
ld [sub_state], a
; set the background position
ld a, 0
ld [BKG_POS_X_REGISTER], a
ld [BKG_POS_Y_REGISTER], a
call show_message_menu_start
; turn the screen on
ld a, DISPLAY_ON + TLS_USE_LOC_8000 \
+ BKG_DISPLAY_ON + BKG_USE_LOC_9800 \
+ WND_DISPLAY_OFF + WND_USE_LOC_9C00 \
+ OBJ_DISPLAY_OFF + OBJ_SIZE_8X8
+ OBJ_DISPLAY_ON + OBJ_SIZE_8X8
ld [LCD_CONTROL_REGISTER], a
ret
; 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:
ld a, STATE_HELP
ld [current_state], a
; turn the screen off
ld a, DISPLAY_OFF
ld [LCD_CONTROL_REGISTER], a
call clear_message
; set the background position
ld a, 0
ld [BKG_POS_X_REGISTER], a
ld a, $9a
ld [BKG_POS_Y_REGISTER], a
; set the window position
ld a, 3
ld [WND_POS_X_REGISTER], a
ld a, $70
ld [WND_POS_Y_REGISTER], a
; load the window data
ld hl, window_help
call load_window_map
; 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 de, help_word
ld c, 65
.copy_gamestate:
ld a, [de]
ld [hl], a
inc de
inc hl
dec c
jp nz, .copy_gamestate
; for the rest we can use the default functions
call update_hint_markings
call update_guess_objects
; turn the screen on
ld a, DISPLAY_ON + TLS_USE_LOC_8000 \
+ BKG_DISPLAY_ON + BKG_USE_LOC_9800 \
+ WND_DISPLAY_ON + WND_USE_LOC_9C00 \
+ OBJ_DISPLAY_ON + OBJ_SIZE_8X8
ld [LCD_CONTROL_REGISTER], a
ret
; 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:
; set the current state
ld a, STATE_GAME
ld [current_state], a
; turn the screen off
ld a, DISPLAY_OFF
ld [LCD_CONTROL_REGISTER], a
call select_word
call clear_message
; set the background position
ld a, 0
@ -35,18 +139,22 @@ init_state_game:
; set the window position
ld a, 3
ld [WND_POS_X_REGISTER], a
ld a, $5e
ld a, $68
ld [WND_POS_Y_REGISTER], a
; initialise some more variables
; load the window data
ld hl, window_game
call load_window_map
; initialize some more variables
ld a, 0
ld [selected_letter_x], a
ld [selected_letter_y], a
ld [current_guess], a
ld [current_char], a
.reset_guesses
ld hl, guesses
.reset_guess_attempts
ld hl, guess_attempts
ld a, NULL
ld d, 30
.loop1:
@ -55,7 +163,7 @@ init_state_game:
jp nz, .loop1
.reset_hints
ld hl, guesses_hints
ld hl, guess_hints
ld a, TILE_WHITE
ld d, 30
.loop2:
@ -73,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:
ld a, STATE_LOST
ld [current_state], a
@ -82,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:
ld a, STATE_WON
ld [current_state], a
@ -91,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:
ld a, %10010011
ld [PALETTE_BKG_REGISTER], a
@ -101,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:
ld bc, tiles_start
ld hl, TLS_LOC_8000
@ -122,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:
ld bc, background
ld hl, BKG_LOC_9800
@ -143,18 +262,19 @@ load_background_map:
; Load the window map into the vram
; Copy a window map into the vram
; -> hl: address of the desired window map
; <- [WND_LOC_9C00]
load_window_map:
ld bc, window
ld hl, WND_LOC_9C00
ld bc, WND_LOC_9C00
ld d, 32
ld e, 32
ld e, 5
.loop:
ld a, [bc]
ld [hl], a
inc bc
ld a, [hl]
ld [bc], a
inc hl
inc bc
dec d
jp nz, .loop

188
inc/input.asm

@ -1,46 +1,14 @@
; Update the object data for the alphabet cursor
update_cursor_objects:
ld hl, obj_selected_letter
; vertical position
ld a, [selected_letter_y]
ld b, $08
call multiply_ab
add a, $86
ld [hl+], a
; horizontal position
ld a, [selected_letter_x]
ld b, $10
call multiply_ab
add a, $14
ld [hl+], a
; tile index
ld a, [selected_letter_x]
ld c, a
ld a, [selected_letter_y]
ld b, $09
call multiply_ab
add a, c
; char 26 doesn't exist, it's the enter sign
cp a, 26
jp nz, .not_enter
ld a, TILE_ENTER
.not_enter:
ld [hl+], a
; attributes
ld a, OBJ_ATTR_PALETTE1
ld [hl+], a
ret
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; █▄░▄█░▄▄▀█▀▄▄▀█░██░█▄░▄██
;; ██░██░██░█░▀▀░█░██░██░███
;; █▀░▀█▄██▄█░█████▄▄▄██▄███
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Handles the player inputs
; Read the current input state
; -> b: current keystates
; -> c: changed keys since last read
; <- b: current keystates
; <- c: changed keys since last read
read_input:
di
@ -82,20 +50,62 @@ read_input:
; React on input within the menu
; React to input within the menu
; -> c: the changed keystate
handle_input_menu:
.check_movement:
ld a, c
and a, INPUT_START
jp z, .nothing
and a, INPUT_UP | INPUT_DOWN
jp z, .check_confirm
ld a, [sub_state]
; flip the corresponding bits
xor a, STATE_MENU_START + STATE_MENU_HELP
ld [sub_state], a
and a, STATE_MENU_START
jp z, .switch_to_help
.switch_to_start
call show_message_menu_start
jp .check_confirm
.switch_to_help
call show_message_menu_help
jp .check_confirm
.check_confirm
ld a, c
and a, INPUT_START | INPUT_A
jp z, .return
ld a, [sub_state]
and a, STATE_MENU_START
jp z, .help_selected
.start_selected
call init_state_game
jp .return
.help_selected
call init_state_help
jp .return
.return
ret
.nothing
; React to input within the help screen
; -> c: the changed keystate
handle_input_help:
ld a, c
and a, INPUT_START
jp z, .return
call init_state_game
.return
ret
; React on input within the main game
; <- c: changed keys since last read
; React to input within the main game
; -> c: the changed keystate
; <- [selected_letter_x]
; <- [selected_letter_y]
handle_input_game:
ld a, [selected_letter_x]
ld d, a
@ -120,8 +130,11 @@ handle_input_game:
jp z, .check_left
ld a, d
cp a, $08
jp z, .check_left
jp z, .overflow_right
inc d
jp .check_left
.overflow_right:
ld d, 0
.check_left:
ld a, c
@ -129,8 +142,11 @@ handle_input_game:
jp z, .check_up
ld a, d
cp a, 0
jp z, .check_up
jp z, .overflow_left
dec d
jp .check_up
.overflow_left:
ld d, 8
.check_up:
ld a, c
@ -138,8 +154,11 @@ handle_input_game:
jp z, .check_down
ld a, e
cp a, 0
jp z, .check_down
jp z, .overflow_up
dec e
jp .check_down
.overflow_up:
ld e, 2
.check_down:
ld a, c
@ -147,8 +166,11 @@ handle_input_game:
jp z, .check_a
ld a, e
cp a, $02
jp z, .check_a
jp z, .overflow_down
inc e
jp .check_a
.overflow_down:
ld e, 0
.check_a:
ld a, c
@ -171,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:
ld a, c
and a, INPUT_START
jp z, .nothing
call init_state_game
call clear_message
.nothing
ret
; Add a character to the guess
; Select a character and add it to the current guess
; -> d: x position of the cursor
; -> e: y position of the cursor
; <- [current_guess]
; <- [current_char]
; <- [guess_attempts]
select_letter:
push hl
push af
@ -198,17 +224,18 @@ select_letter:
ld b, 9
call multiply_ab
add a, d
inc a
ld c, a
; check if it's enter
ld a, c
cp a, 26
cp a, 27
jp nz, .normal_letter
call check_guess
jp .return
.normal_letter:
ld hl, guesses
ld hl, guess_attempts
ld a, [current_guess]
ld b, 5
call multiply_ab
@ -235,14 +262,17 @@ select_letter:
; Delete the last letter
; Delete the last entered letter
; <- [current_guess]
; <- [current_char]
; <- [guess_attempts]
delete_letter:
push hl
push af
push bc
push de
ld hl, guesses
ld hl, guess_attempts
ld a, [current_guess]
ld b, 5
call multiply_ab
@ -269,3 +299,47 @@ delete_letter:
pop hl
ret
; Update the object data for the alphabet cursor
; -> [selected_letter_x]
; -> [selected_letter_y]
; <- [obj_selected_letter]
update_cursor_objects:
ld hl, obj_selected_letter
; vertical position
ld a, [selected_letter_y]
ld b, $08
call multiply_ab
add a, $80
ld [hl+], a
; horizontal position
ld a, [selected_letter_x]
ld b, $10
call multiply_ab
add a, $14
ld [hl+], a
; tile index
ld a, [selected_letter_x]
ld c, a
ld a, [selected_letter_y]
ld b, $09
call multiply_ab
add a, c
inc a
; char 27 doesn't exist, it's the enter sign
cp a, 27
jp nz, .not_enter
ld a, TILE_ENTER
.not_enter:
ld [hl+], a
; attributes
ld a, OBJ_ATTR_PALETTE1
ld [hl+], a
ret

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:
push af
ld a, 1
@ -11,7 +19,10 @@ int_vblank:
; Interrupt handler for the timer
;
; 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:
push hl
push af
@ -26,7 +37,7 @@ int_timer:
ld hl, LCD_POSITION_REGISTER
ld a, [hl]
; save the new number
; save the old and new number
ld hl, random_number
ld [hl+], a
ld a, d

8
inc/math.asm

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

66
inc/messages.asm

@ -1,13 +1,49 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▀▄░█░▄▄█░▄▄█░▄▄█░▄▄▀█░▄▄▄█░▄▄█░▄▄██
;; ██░█░█░█░▄▄█▄▄▀█▄▄▀█░▀▀░█░█▄▀█░▄▄█▄▄▀██
;; ██░███░█▄▄▄█▄▄▄█▄▄▄█▄██▄█▄▄▄▄█▄▄▄█▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; 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"
; <- de: message address
; <- b: message timeout
show_message_menu_start:
ld de, message_menu_start
ld b, 0
call show_message
ret
; Highlights the menu entry "how it works"
; <- de: message address
; <- b: message timeout
show_message_menu_help:
ld de, message_menu_help
ld b, 0
call show_message
ret
; Inform that the current guess is not in the dictionary
; <- de: message address
; <- b: message timeout
show_message_unknown:
ld de, message_unknown
ld b, 180
ld b, 180 ; three seconds
call show_message
ret
; Inform about the users victory
; <- de: message address
; <- b: message timeout
show_message_won:
ld de, message_won
ld b, 0
@ -17,6 +53,8 @@ show_message_won:
; Inform about the users loss
; <- de: message address
; <- b: message timeout
show_message_lost:
ld de, message_lost
ld b, 0
@ -39,12 +77,18 @@ ENDR
; Displays a message to the user
; <- de
; <- b
; Generic function to present a message to the user
; -> de: message address
; -> b: message timeout
; <- [obj_message_letters]
; <- [message_timeout]
show_message:
push hl
push bc
push de
ld hl, obj_message_letters
ld c, 32
ld c, 36
.loop:
ld a, [de]
ld [hl], a
@ -55,11 +99,18 @@ show_message:
ld a, b
ld [message_timeout], a
pop de
pop bc
pop hl
ret
; 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:
ld a, [message_timeout]
cp a, 0
@ -77,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:
ld de, message_clear
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:
ld b, 160
ld a, 0
ld hl, obj_start
.zero_loop
.copy_loop
ld [hl+], a
dec b
jp nz, .zero_loop
jp nz, .copy_loop
ret
; Write into OAM via DMA
; Update the OAM via DMA
; -> [objects]
; <- [OAM]
update_oam:
; start DMA
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:
push hl
push af
@ -14,7 +27,6 @@ check_guess:
; and then search after it.
call compress_guess
call find_guess
cp a, 1
jp nz, .is_invalid
@ -56,8 +68,10 @@ check_guess:
; Check the win conditions
; <- a
; Check if guessed correctly and therefore won
; -> [current_word]
; -> [current_guess]
; <- a: whether it is correct or not
check_win:
call get_guess_offset
ld bc, current_word

70
maps/background.asm

@ -1,36 +1,36 @@
; Background map
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,$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,$22,$23,$24,$25,$26,$27,$28,$29,$2a,$2b,$2c,$2d,$2e,$2f,$30,$31,$32,$33,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$34,$35,$36,$37,$38,$39,$3a,$3b,$3c,$3d,$3e,$3f,$40,$41,$42,$43,$44,$45,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$46,$47,$48,$49,$4a,$4b,$4c,$4d,$4e,$4f,$50,$51,$52,$53,$54,$55,$56,$57,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1b,$58,$59,$5a,$5b,$5c,$5d,$5e,$5f,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$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,$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,$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,$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 $1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1a,$1a,$1a,$1a,$0f,$11,$04,$12,$12,$1a,$1a,$12,$13,$00,$11,$13,$1a,$1a,$1a,$1a,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b
DB $1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$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,$1b,$1b,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$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,$1b,$1b,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$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,$1b,$1b,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$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,$1b,$1b,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$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,$1b,$1b,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$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,$1b,$1b,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$1b,$1d,$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,$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,$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 $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$23,$24,$25,$26,$27,$28,$29,$2a,$2b,$2c,$2d,$2e,$2f,$30,$31,$32,$33,$34,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$35,$36,$37,$38,$39,$3a,$3b,$3c,$3d,$3e,$3f,$40,$41,$42,$43,$44,$45,$46,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$47,$48,$49,$4a,$4b,$4c,$4d,$4e,$4f,$50,$51,$52,$53,$54,$55,$56,$57,$58,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$59,$5a,$5b,$5c,$5d,$5e,$5f,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$6a,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1b,$1b,$1b,$1b,$1b,$13,$14,$01,$12,$14,$1b,$07,$01,$0d,$05,$1b,$1b,$1b,$1b,$1b,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1b,$1b,$1b,$1b,$1b,$08,$0f,$17,$1b,$14,$0f,$1b,$10,$0c,$01,$19,$1b,$1b,$1b,$1b,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1d,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c
DB $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c

6
maps/window-game.asm

@ -0,0 +1,6 @@
; 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,$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,$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

6
maps/window-help.asm

@ -0,0 +1,6 @@
; Window map while within help
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

36
maps/window.asm

@ -1,36 +0,0 @@
; Window map
DB $1a,$1a,$00,$1a,$01,$1a,$02,$1a,$03,$1a,$04,$1a,$05,$1a,$06,$1a,$07,$1a,$08,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a
DB $1a,$1a,$09,$1a,$0a,$1a,$0b,$1a,$0c,$1a,$0d,$1a,$0e,$1a,$0f,$1a,$10,$1a,$11,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a
DB $1a,$1a,$12,$1a,$13,$1a,$14,$1a,$15,$1a,$16,$1a,$17,$1a,$18,$1a,$19,$1a,$1e,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a
DB $1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a
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,$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,$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,$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,$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,$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,$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,$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,$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,$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,$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,$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,$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,$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,$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,$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

210
wordle.asm

@ -1,45 +1,59 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░███░█▀▄▄▀█░▄▄▀█░▄▀█░██░▄▄██
;; ██░█░█░█░██░█░▀▀▄█░█░█░██░▄▄██
;; ██▄▀▄▀▄██▄▄██▄█▄▄█▄▄██▄▄█▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; The famous word puzzle
; Include hardware-specific constants
; used all over the code.
include "inc/constants.asm"
;; Game specific constants
; Game states
STATE_MENU EQU %00000001
STATE_GAME EQU %00000010
STATE_LOST EQU %00000100
STATE_WON EQU %00001100
STATE_MENU_START EQU %01000000
STATE_MENU_HELP EQU %10000000
STATE_HELP EQU %00000010
STATE_GAME EQU %00000100
STATE_LOST EQU %00001000
STATE_WON EQU %00011000
; Marker for invalid or undefined values
NULL EQU $1c
NULL EQU $00
;; Indices of special tiles
TILE_BLACK EQU $1a
TILE_WHITE EQU $1b
TILE_NULL EQU NULL
TILE_BLACK EQU $1b
TILE_WHITE EQU $1c
TILE_PLACEHOLDER EQU $1d
TILE_ENTER EQU $1e
TILE_RIGHT EQU $1f
TILE_MISPLACED EQU $20
TILE_WRONG EQU $21
TILE_ARROW EQU $22
; Vertical blanking interrupt starting address
SECTION "ENTRY_VBLANK", ROM0[$0040]
jp int_vblank
jp int_vblank ; used for game logic updates
; LCDC status interrupt starting address
SECTION "ENTRY_LCDCS", ROM0[$0048]
reti
reti ; we don't use this interrupt
; Timer overflow interrupt starting address
SECTION "ENTRY_TIMER", ROM0[$0050]
jp int_timer
jp int_timer ; used for generating randomness
; Serial transfer completion interrupt starting address
SECTION "ENTRY_SERIAL", ROM0[$0058]
reti
reti ; we don't use this interrupt
; Program starting address
@ -50,7 +64,8 @@ SECTION "ENTRY_START", ROM0[$0100]
SECTION "MAIN", ROM0[$0150]
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 [LCD_CONTROL_REGISTER], a
ld [LCD_STATUS_REGISTER], a
@ -61,7 +76,6 @@ main:
; load the video data
call init_palettes
call load_tiles
call load_window_map
call load_background_map
; initialise the objects
@ -96,15 +110,22 @@ main_loop:
.within_vblank:
call update_oam
call read_input
ld a, [current_state]
.in_menu:
cp a, STATE_MENU
jp nz, .in_game
jp nz, .in_help
call handle_input_menu
jp .cleanup
.in_help:
cp a, STATE_HELP
jp nz, .in_game
call handle_input_help
call update_hint_markings
call update_guess_objects
jp .cleanup
.in_game:
cp a, STATE_GAME
jp nz, .in_won
@ -145,7 +166,6 @@ include "inc/dict.asm"
include "inc/input.asm"
include "inc/guess.asm"
include "inc/hints.asm"
include "inc/search.asm"
include "inc/messages.asm"
include "inc/wincondition.asm"
include "inc/interrupts.asm"
@ -154,16 +174,19 @@ include "inc/interrupts.asm"
;; Game data
SECTION "DATA0", ROM0[$1000]
; Tiles
;; Tiles
; Small 8x8 pixel images, which are addressable
; and will be used for sprite maps and objects.
tiles_start:
tile_null:
include "tiles/plain-null.asm"
tiles_alphabet:
include "tiles/alphabet.asm"
tile_black:
include "tiles/plain-black.asm"
tile_white:
include "tiles/plain-white.asm"
tile_null:
include "tiles/plain-null.asm"
tiles_placeholder:
include "tiles/sign-placeholder.asm"
tiles_enter:
@ -174,28 +197,64 @@ tile_misplaced:
include "tiles/sign-misplaced.asm"
tiles_wrong:
include "tiles/sign-wrong.asm"
tiles_arrow:
include "tiles/sign-arrow.asm"
tiles_logo:
include "tiles/logo.asm"
tiles_end:
; Maps
;; Maps
; Each map defines a grid of tile addresses,
; which combined will form the desired image.
maps_start:
background:
include "maps/background.asm"
window:
include "maps/window.asm"
window_help:
include "maps/window-help.asm"
window_game:
include "maps/window-game.asm"
maps_end:
;; Dictionary
; A list of known words to choose from.
dictionary:
incbin "dict/en.dat"
dictionary_end:
DB
; Messages
;; 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:
DB $12, $09, $07, $08, $14 ; right
help_guess:
DB $06, $01, $15, $0c, $14 ; fault
DB $07, $09, $12, $14, $08 ; girth
DB $12, $09, $07, $08, $14 ; right
DB $0f, $0e, $0c, $19, $00 ; only
DB $13, $09, $18, $00, $00 ; six
DB $14, $12, $09, $05, $13 ; tries
help_guess_hints:
DB TILE_WRONG, TILE_WRONG, TILE_WRONG, TILE_WRONG, TILE_RIGHT
DB TILE_MISPLACED, TILE_MISPLACED, TILE_MISPLACED, TILE_MISPLACED, TILE_MISPLACED
DB TILE_RIGHT, TILE_RIGHT, TILE_RIGHT, TILE_RIGHT, TILE_RIGHT
DB TILE_WHITE, TILE_WHITE, TILE_WHITE, TILE_WHITE, TILE_WHITE
DB TILE_WHITE, TILE_WHITE, TILE_WHITE, TILE_WHITE, TILE_WHITE
DB TILE_WHITE, TILE_WHITE, TILE_WHITE, TILE_WHITE, TILE_WHITE
;; 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:
DB $00, $00, $00, $00
DB $00, $00, $00, $00
@ -205,40 +264,66 @@ message_clear:
DB $00, $00, $00, $00
DB $00, $00, $00, $00
DB $00, $00, $00, $00
DB $00, $00, $00, $00
message_menu_start:
DB $88, $30, 19, OBJ_ATTR_PALETTE1 ; S
DB $88, $38, 20, OBJ_ATTR_PALETTE1 ; T
DB $88, $40, 01, OBJ_ATTR_PALETTE1 ; A
DB $88, $48, 18, OBJ_ATTR_PALETTE1 ; R
DB $88, $50, 20, OBJ_ATTR_PALETTE1 ; T
DB $88, $60, 07, OBJ_ATTR_PALETTE1 ; G
DB $88, $68, 01, OBJ_ATTR_PALETTE1 ; A
DB $88, $70, 13, OBJ_ATTR_PALETTE1 ; M
DB $88, $78, 05, OBJ_ATTR_PALETTE1 ; E
message_menu_help:
DB $90, $30, 08, OBJ_ATTR_PALETTE1 ; H
DB $90, $38, 15, OBJ_ATTR_PALETTE1 ; O
DB $90, $40, 23, OBJ_ATTR_PALETTE1 ; W
DB $90, $50, 20, OBJ_ATTR_PALETTE1 ; T
DB $90, $58, 15, OBJ_ATTR_PALETTE1 ; O
DB $90, $68, 16, OBJ_ATTR_PALETTE1 ; P
DB $90, $70, 12, OBJ_ATTR_PALETTE1 ; L
DB $90, $78, 01, OBJ_ATTR_PALETTE1 ; A
DB $90, $80, 25, OBJ_ATTR_PALETTE1 ; Y
message_unknown:
DB $7a, $38, 20, OBJ_ATTR_PALETTE1 ; U
DB $7a, $40, 13, OBJ_ATTR_PALETTE1 ; N
DB $7a, $48, 10, OBJ_ATTR_PALETTE1 ; k
DB $7a, $50, 13, OBJ_ATTR_PALETTE1 ; N
DB $7a, $58, 14, OBJ_ATTR_PALETTE1 ; O
DB $7a, $60, 22, OBJ_ATTR_PALETTE1 ; W
DB $7a, $68, 13, OBJ_ATTR_PALETTE1 ; N
DB $78, $38, 21, OBJ_ATTR_PALETTE1 ; U
DB $78, $40, 14, OBJ_ATTR_PALETTE1 ; N
DB $78, $48, 11, OBJ_ATTR_PALETTE1 ; k
DB $78, $50, 14, OBJ_ATTR_PALETTE1 ; N
DB $78, $58, 15, OBJ_ATTR_PALETTE1 ; O
DB $78, $60, 23, OBJ_ATTR_PALETTE1 ; W
DB $78, $68, 14, OBJ_ATTR_PALETTE1 ; N
DB $00, $00, 0, 0
DB $00, $00, 0, 0
message_won:
DB $7a, $38, 24, OBJ_ATTR_PALETTE1 ; Y
DB $7a, $40, 14, OBJ_ATTR_PALETTE1 ; O
DB $7a, $48, 20, OBJ_ATTR_PALETTE1 ; U
DB $7a, $58, 22, OBJ_ATTR_PALETTE1 ; W
DB $7a, $60, 14, OBJ_ATTR_PALETTE1 ; O
DB $7a, $68, 13, OBJ_ATTR_PALETTE1 ; N
DB $78, $38, 25, OBJ_ATTR_PALETTE1 ; Y
DB $78, $40, 15, OBJ_ATTR_PALETTE1 ; O
DB $78, $48, 21, OBJ_ATTR_PALETTE1 ; U
DB $78, $58, 23, OBJ_ATTR_PALETTE1 ; W
DB $78, $60, 15, OBJ_ATTR_PALETTE1 ; O
DB $78, $68, 14, OBJ_ATTR_PALETTE1 ; N
DB $00, $00, 0, 0
DB $00, $00, 0, 0
DB $00, $00, 0, 0
message_lost:
DB $7a, $30, 8, OBJ_ATTR_PALETTE1 ; I
DB $7a, $38, 19, OBJ_ATTR_PALETTE1 ; T
DB $7a, $40, 18, OBJ_ATTR_PALETTE1 ; S
DB $7a, $50, 0, OBJ_ATTR_PALETTE1 ; guess[0]
DB $7a, $58, 0, OBJ_ATTR_PALETTE1 ; guess[1]
DB $7a, $60, 0, OBJ_ATTR_PALETTE1 ; guess[2]
DB $7a, $68, 0, OBJ_ATTR_PALETTE1 ; guess[3]
DB $7a, $70, 0, OBJ_ATTR_PALETTE1 ; guess[4]
DB $78, $30, 9, OBJ_ATTR_PALETTE1 ; I
DB $78, $38, 20, OBJ_ATTR_PALETTE1 ; T
DB $78, $40, 19, OBJ_ATTR_PALETTE1 ; S
DB $78, $50, 0, OBJ_ATTR_PALETTE1 ; guess[0]
DB $78, $58, 0, OBJ_ATTR_PALETTE1 ; guess[1]
DB $78, $60, 0, OBJ_ATTR_PALETTE1 ; guess[2]
DB $78, $68, 0, OBJ_ATTR_PALETTE1 ; guess[3]
DB $78, $70, 0, OBJ_ATTR_PALETTE1 ; guess[4]
DB $00, $00, 0, 0
; Address reservations within the working ram
;; Address reservations within the working ram
SECTION "RAM", WRAM0
; The first 160 Bytes are reserved for a copy
; of the OAM data, which will be updated via DMA.
@ -248,7 +333,7 @@ obj_selected_letter:
obj_guess_letters:
DS 120
obj_message_letters:
DS 32
DS 36
obj_end:
obj_dma_padding:
DS 160 - (obj_end - obj_start)
@ -258,7 +343,7 @@ obj_dma_padding:
vblank_flag:
DB
; Saves the current 16bit random number
; Saves the current random number consisting of 16 bits
random_number:
DS 2
@ -266,38 +351,43 @@ random_number:
input_state:
DB
; Saves the current game state
; Saves the current game state (see STATE constants)
current_state:
DB
; Saves the current word
current_word:
DS 5
; Saves the subordinate state (see STATE constants)
sub_state:
DB
; Number of the current guess
; Number of the current guess (0..5)
current_guess:
DB
; Position within the current guess
; Position within the current guess (0..4)
current_char:
DB
; Saves the current word
current_word:
DS 5
; The guess attempts
guesses:
guess_attempts:
DS 30
; The corresponding hints
guesses_hints:
guess_hints:
DS 30
; Message timeout
; Message timeout (remaining number of frames)
message_timeout:
DB
; Horizontal position of the letter selection
; Horizontal position of the letter selection within the alphabet grid
selected_letter_x:
DB
; Vertical position of the letter selection
; Vertical position of the letter selection within the alphabet grid
selected_letter_y:
DB

BIN
wordle.gb

Binary file not shown.
Loading…
Cancel
Save