Compare commits

..

No commits in common. 'main' and '0.5.0' have entirely different histories.
main ... 0.5.0

  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. 151
      inc/dict.asm
  7. 30
      inc/guess.asm
  8. 33
      inc/hints.asm
  9. 164
      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. 24
      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 character 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 letter 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 Confirms the entered word
SELECT Selects a letter
→ ↓ ← ↑ Moves the cursor
A Selects a character
B Deletes the last character

21
dict/compress.py

@ -1,11 +1,4 @@
#!/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):
@ -20,13 +13,13 @@ def compress(in_path: str, out_path:str):
if len(set(list(word))) != len(word):
continue
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)
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)
pack = struct.pack("BBBB", a, b, c, d)
data.write(pack)

BIN
dict/en.dat

Binary file not shown.

141
dict/solver.py

@ -1,141 +0,0 @@
#!/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,10 +1,4 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▄░█░▄▄▀█░▄▀▄░█░▄▄████░▄▄▀█▀▄▄▀█░██░████░▄▄▀█▀▄▄▀█░▄▄▀█░▄▄█▄░▄█░▄▄▀█░▄▄▀█▄░▄█░▄▄██
;; ██░█▀▀█░▀▀░█░█▄█░█░▄▄████░▄▄▀█░██░█░▀▀░████░████░██░█░██░█▄▄▀██░██░▀▀░█░██░██░██▄▄▀██
;; ██░▀▀▄█▄██▄█▄███▄█▄▄▄████░▀▀░██▄▄██▀▀▀▄████░▀▀▄██▄▄██▄██▄█▄▄▄██▄██▄██▄█▄██▄██▄██▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Hardware specific values and addresses
;; Game Boy Constants
; Interrupt Flags
INTERRUPT_SETTINGS EQU $ffff
INT_VBLANK_ON EQU %00000001

151
inc/dict.asm

@ -1,29 +1,21 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▄▀██▄██▀▄▀█▄░▄██▄██▀▄▄▀█░▄▄▀█░▄▄▀█░▄▄▀█░██░██
;; ██░██░██░▄█░█▀██░███░▄█░██░█░██░█░▀▀░█░▀▀▄█░▀▀░██
;; ██░▀▀░█▄▄▄██▄███▄██▄▄▄██▄▄██▄██▄█▄██▄█▄█▄▄█▀▀▀▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; 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.
; Selects a random word from the dictionary.
; Sets the to be guessed and the revealed letter indices.
;
; 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
; Note: The dict saves the 5 chars of the words in 4 bytes.
; n+0: 11111122
; n+1: 22223333
; n+2: 33444444
; n+3: 55555500
;
; -> [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, %0001010
ld [random_number], a
ld a, %00000000
ld [random_number+1], a
ld a, [random_number+0]
and %00011111
ld h, a
@ -109,120 +101,3 @@ 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,17 +1,7 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▄░█░██░█░▄▄█░▄▄█░▄▄█░███░█▀▄▄▀█░▄▄▀█░█▀██
;; ██░█▀▀█░██░█░▄▄█▄▄▀█▄▄▀█▄▀░▀▄█░██░█░▀▀▄█░▄▀██
;; ██░▀▀▄██▄▄▄█▄▄▄█▄▄▄█▄▄▄██▄█▄███▄▄██▄█▄▄█▄█▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; 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, guess_attempts
ld de, guesses
ld a, $14
call update_guess_row
@ -30,10 +20,9 @@ update_guess_objects:
; Updates one line of entered characters
; -> hl: address of where to write obj data
; -> de: address of the current guess
; -> hl: position within obj data
; -> de: position within the guesses data
; -> a: vertical screen position
; <- [obj_guess_letters]
update_guess_row:
push hl
push hl
@ -42,14 +31,14 @@ update_guess_row:
; distance between objects
ld bc, 4
; write all five vertical positions
; vertical positions
ld [hl], a
REPT 4
add hl, bc
ld [hl], a
ENDR
; write all five horizontal positions
; horizontal positions
pop hl
inc hl
ld a, $30
@ -60,7 +49,7 @@ REPT 4
ld [hl], a
ENDR
; write all five tile indices
; tile indices
pop hl
inc hl
inc hl
@ -73,7 +62,7 @@ REPT 4
ld [hl], a
ENDR
; write all five palette info
; palette info
pop hl
inc hl
inc hl
@ -91,8 +80,7 @@ ENDR
; Calculates the address of the current guess attempt, using the number of the attempt
; -> [current_guess]: number of the current attempt
; Calculates the position of the current guess
; <- hl
get_guess_offset:
ld a, [current_guess]
@ -100,7 +88,7 @@ get_guess_offset:
call multiply_ab
ld b, 0
ld c, a
ld hl, guess_attempts
ld hl, guesses
add hl, bc
ret

33
inc/hints.asm

@ -1,19 +1,7 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░██░██▄██░▄▄▀█▄░▄█░▄▄██
;; ██░▄▄░██░▄█░██░██░██▄▄▀██
;; ██░██░█▄▄▄█▄██▄██▄██▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; 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 the character hint objects
update_hint_markings:
; calculate the
ld hl, BKG_LOC_9800 + 32*20 + 6
ld de, guess_hints
ld hl, BKG_LOC_9800 + 20*32 + 6
ld de, guesses_hints
ld b, 6
.loop_outer:
@ -42,13 +30,8 @@ update_hint_markings:
; Saves the obtained hints.
; -> [current_word]
; -> [current_guess]
; -> [guess]
; Update the hint data
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
@ -57,7 +40,6 @@ mark_hints:
ld b, 0
.loop:
; update the hints char by char
ld a, [de]
call hint_for_char
ld [hl], a
@ -71,10 +53,9 @@ mark_hints:
; Determines the hint for one character.
; -> [current_word]
; -> a: character value to check
; -> b: position within the guess
; Determines the hint for one character
; <- a: character value to check
; <- b: index within the guess
hint_for_char:
push hl
push bc

164
inc/init.asm

@ -1,134 +1,30 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; █▄░▄█░▄▄▀██▄██▄░▄██▄██░▄▄▀█░███▄██▄▄░█░▄▄▀█▄░▄██▄██▀▄▄▀█░▄▄▀██
;; ██░██░██░██░▄██░███░▄█░▀▀░█░███░▄█▀▄██░▀▀░██░███░▄█░██░█░██░██
;; █▀░▀█▄██▄█▄▄▄██▄██▄▄▄█▄██▄█▄▄█▄▄▄█▄▄▄█▄██▄██▄██▄▄▄██▄▄██▄██▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; 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]
; Initialise everything for the main game state
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_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
+ WND_DISPLAY_OFF + WND_USE_LOC_9C00 \
+ OBJ_DISPLAY_OFF + OBJ_SIZE_8X8
ld [LCD_CONTROL_REGISTER], a
ret
; 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]
; Initialise everything for the main game state
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
@ -139,22 +35,18 @@ init_state_game:
; set the window position
ld a, 3
ld [WND_POS_X_REGISTER], a
ld a, $68
ld a, $5e
ld [WND_POS_Y_REGISTER], a
; load the window data
ld hl, window_game
call load_window_map
; initialize some more variables
; initialise 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_guess_attempts
ld hl, guess_attempts
.reset_guesses
ld hl, guesses
ld a, NULL
ld d, 30
.loop1:
@ -163,7 +55,7 @@ init_state_game:
jp nz, .loop1
.reset_hints
ld hl, guess_hints
ld hl, guesses_hints
ld a, TILE_WHITE
ld d, 30
.loop2:
@ -172,7 +64,7 @@ init_state_game:
jp nz, .loop2
; turn the screen on
ld a, DISPLAY_ON + TLS_USE_LOC_8000 \
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
@ -181,9 +73,7 @@ init_state_game:
; Switches to the state when the player has lost
; <- [current_state]
; <- [message_objs]
; Switches to the lost state
init_state_lost:
ld a, STATE_LOST
ld [current_state], a
@ -192,9 +82,7 @@ init_state_lost:
; Switches to the state when the player has won
; <- [current_state]
; <- [message_objs]
; Switches to the won state
init_state_won:
ld a, STATE_WON
ld [current_state], a
@ -203,10 +91,7 @@ init_state_won:
; Initialize the DMG color palettes
; <- [PALETTE_BKG_REGISTER]
; <- [PALETTE_OBJ0_REGISTER]
; <- [PALETTE_OBJ1_REGISTER]
; Initialise the DMG color palettes
init_palettes:
ld a, %10010011
ld [PALETTE_BKG_REGISTER], a
@ -216,9 +101,7 @@ init_palettes:
; Copy the tile data into the vram
; -> [tiles]
; <- [TLS_LOC_8000]
; Load the tile data into the vram
load_tiles:
ld bc, tiles_start
ld hl, TLS_LOC_8000
@ -239,9 +122,7 @@ load_tiles:
; Copy the background map into the vram
; -> [background]
; <- [BKG_LOC_9800]
; Load the background map into the vram
load_background_map:
ld bc, background
ld hl, BKG_LOC_9800
@ -262,19 +143,18 @@ load_background_map:
; Copy a window map into the vram
; -> hl: address of the desired window map
; <- [WND_LOC_9C00]
; Load the window map into the vram
load_window_map:
ld bc, WND_LOC_9C00
ld bc, window
ld hl, WND_LOC_9C00
ld d, 32
ld e, 5
ld e, 32
.loop:
ld a, [hl]
ld [bc], a
inc hl
ld a, [bc]
ld [hl], a
inc bc
inc hl
dec d
jp nz, .loop

188
inc/input.asm

@ -1,14 +1,46 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; █▄░▄█░▄▄▀█▀▄▄▀█░██░█▄░▄██
;; ██░██░██░█░▀▀░█░██░██░███
;; █▀░▀█▄██▄█░█████▄▄▄██▄███
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Handles the player inputs
; 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
; 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
@ -50,62 +82,20 @@ read_input:
; React to input within the menu
; -> c: the changed keystate
; React on input within the menu
handle_input_menu:
.check_movement:
ld a, c
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
; React to input within the help screen
; -> c: the changed keystate
handle_input_help:
ld a, c
and a, INPUT_START
jp z, .return
jp z, .nothing
call init_state_game
.return
.nothing
ret
; React to input within the main game
; -> c: the changed keystate
; <- [selected_letter_x]
; <- [selected_letter_y]
; React on input within the main game
; <- c: changed keys since last read
handle_input_game:
ld a, [selected_letter_x]
ld d, a
@ -130,11 +120,8 @@ handle_input_game:
jp z, .check_left
ld a, d
cp a, $08
jp z, .overflow_right
jp z, .check_left
inc d
jp .check_left
.overflow_right:
ld d, 0
.check_left:
ld a, c
@ -142,11 +129,8 @@ handle_input_game:
jp z, .check_up
ld a, d
cp a, 0
jp z, .overflow_left
jp z, .check_up
dec d
jp .check_up
.overflow_left:
ld d, 8
.check_up:
ld a, c
@ -154,11 +138,8 @@ handle_input_game:
jp z, .check_down
ld a, e
cp a, 0
jp z, .overflow_up
jp z, .check_down
dec e
jp .check_down
.overflow_up:
ld e, 2
.check_down:
ld a, c
@ -166,11 +147,8 @@ handle_input_game:
jp z, .check_a
ld a, e
cp a, $02
jp z, .overflow_down
jp z, .check_a
inc e
jp .check_a
.overflow_down:
ld e, 0
.check_a:
ld a, c
@ -193,26 +171,22 @@ handle_input_game:
; React to input after a game round,
; no matter if won or lost
; -> c: the changed keystate
; React on input after a game round
handle_input_after:
ld a, c
and a, INPUT_START
jp z, .nothing
call init_state_game
call clear_message
.nothing
ret
; Select a character and add it to the current guess
; Add a character to the 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
@ -224,18 +198,17 @@ 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, 27
cp a, 26
jp nz, .normal_letter
call check_guess
jp .return
.normal_letter:
ld hl, guess_attempts
ld hl, guesses
ld a, [current_guess]
ld b, 5
call multiply_ab
@ -262,17 +235,14 @@ select_letter:
; Delete the last entered letter
; <- [current_guess]
; <- [current_char]
; <- [guess_attempts]
; Delete the last letter
delete_letter:
push hl
push af
push bc
push de
ld hl, guess_attempts
ld hl, guesses
ld a, [current_guess]
ld b, 5
call multiply_ab
@ -299,47 +269,3 @@ 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,12 +1,4 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; █▄░▄█░▄▄▀█▄░▄█░▄▄█░▄▄▀█░▄▄▀█░██░█▀▄▄▀█▄░▄█░▄▄██
;; ██░██░██░██░██░▄▄█░▀▀▄█░▀▀▄█░██░█░▀▀░██░██▄▄▀██
;; █▀░▀█▄██▄██▄██▄▄▄█▄█▄▄█▄█▄▄██▄▄▄█░█████▄██▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; Handle hardware interrupts
; Interrupt handler for the vertical blanking period
; Interrupt handler for the vertical blanking
int_vblank:
push af
ld a, 1
@ -19,10 +11,7 @@ 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. 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.
; save them periodically and use them to get something.
int_timer:
push hl
push af
@ -37,7 +26,7 @@ int_timer:
ld hl, LCD_POSITION_REGISTER
ld a, [hl]
; save the old and new number
; save the new number
ld hl, random_number
ld [hl+], a
ld a, d

8
inc/math.asm

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

66
inc/messages.asm

@ -1,49 +1,13 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▀▄░█░▄▄█░▄▄█░▄▄█░▄▄▀█░▄▄▄█░▄▄█░▄▄██
;; ██░█░█░█░▄▄█▄▄▀█▄▄▀█░▀▀░█░█▄▀█░▄▄█▄▄▀██
;; ██░███░█▄▄▄█▄▄▄█▄▄▄█▄██▄█▄▄▄▄█▄▄▄█▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; 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 ; three seconds
ld b, 180
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
@ -53,8 +17,6 @@ show_message_won:
; Inform about the users loss
; <- de: message address
; <- b: message timeout
show_message_lost:
ld de, message_lost
ld b, 0
@ -77,18 +39,12 @@ ENDR
; Generic function to present a message to the user
; -> de: message address
; -> b: message timeout
; <- [obj_message_letters]
; <- [message_timeout]
; Displays a message to the user
; <- de
; <- b
show_message:
push hl
push bc
push de
ld hl, obj_message_letters
ld c, 36
ld c, 32
.loop:
ld a, [de]
ld [hl], a
@ -99,18 +55,11 @@ show_message:
ld a, b
ld [message_timeout], a
pop de
pop bc
pop hl
ret
; Checks if the current message has expired and removes it when necessary
; -> [message_timeout]
; <- [message_timeout]
; <- [obj_message_letters]
; Checks if the current message has expired
check_message_timeout:
ld a, [message_timeout]
cp a, 0
@ -128,8 +77,7 @@ check_message_timeout:
; Clears the current message by overwriting it with NULL values
; <- [obj_message_letters]
; Clears the current message by overwriting with nothing
clear_message:
ld de, message_clear
ld b, 0

22
inc/oam.asm

@ -1,32 +1,18 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░▄▄▄░█░▄▄▀███▄█░▄▄█▀▄▀█▄░▄███░▄▄▀█▄░▄█▄░▄█░▄▄▀██▄██░▄▄▀█░██░█▄░▄█░▄▄████░▄▀▄░█░▄▄█░▄▀▄░█▀▄▄▀█░▄▄▀█░██░██
;; ██░███░█░▄▄▀███░█░▄▄█░█▀██░████░▀▀░██░███░██░▀▀▄██░▄█░▄▄▀█░██░██░██░▄▄████░█░█░█░▄▄█░█▄█░█░██░█░▀▀▄█░▀▀░██
;; ██░▀▀▀░█▄▄▄▄█░▀░█▄▄▄██▄███▄████░██░██▄███▄██▄█▄▄█▄▄▄█▄▄▄▄██▄▄▄██▄██▄▄▄████░███░█▄▄▄█▄███▄██▄▄██▄█▄▄█▀▀▀▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; 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]
; Fill the whole oam copy with zero to prevent artifacts
init_oam_copy:
ld b, 160
ld a, 0
ld hl, obj_start
.copy_loop
.zero_loop
ld [hl+], a
dec b
jp nz, .copy_loop
jp nz, .zero_loop
ret
; Update the OAM via DMA
; -> [objects]
; <- [OAM]
; Write into OAM via DMA
update_oam:
; start DMA
ld a, $c0

113
inc/search.asm

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

24
inc/wincondition.asm

@ -1,17 +1,4 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░███░██▄██░▄▄▀███▀▄▀█▀▄▄▀█░▄▄▀█░▄▀██▄██▄░▄██▄██▀▄▄▀█░▄▄▀██
;; ██░█░█░██░▄█░██░███░█▀█░██░█░██░█░█░██░▄██░███░▄█░██░█░██░██
;; ██▄▀▄▀▄█▄▄▄█▄██▄████▄███▄▄██▄██▄█▄▄██▄▄▄██▄██▄▄▄██▄▄██▄██▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; 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 if the guess is valid
check_guess:
push hl
push af
@ -27,6 +14,7 @@ check_guess:
; and then search after it.
call compress_guess
call find_guess
cp a, 1
jp nz, .is_invalid
@ -42,7 +30,7 @@ check_guess:
.test_lose:
ld a, [current_guess]
cp a, 5
cp a, 6
jp nz, .reset
call init_state_lost
jp .return
@ -68,10 +56,8 @@ check_guess:
; Check if guessed correctly and therefore won
; -> [current_word]
; -> [current_guess]
; <- a: whether it is correct or not
; Check the win conditions
; <- a
check_win:
call get_guess_offset
ld bc, current_word

70
maps/background.asm

@ -1,36 +1,36 @@
; Background map
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
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

6
maps/window-game.asm

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

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

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

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

210
wordle.asm

@ -1,59 +1,45 @@
;; ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;; ██░███░█▀▄▄▀█░▄▄▀█░▄▀█░██░▄▄██
;; ██░█░█░█░██░█░▀▀▄█░█░█░██░▄▄██
;; ██▄▀▄▀▄██▄▄██▄█▄▄█▄▄██▄▄█▄▄▄██
;; ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;; 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_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
STATE_GAME EQU %00000010
STATE_LOST EQU %00000100
STATE_WON EQU %00001100
; Marker for invalid or undefined values
NULL EQU $00
NULL EQU $1c
;; 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 ; used for game logic updates
jp int_vblank
; LCDC status interrupt starting address
SECTION "ENTRY_LCDCS", ROM0[$0048]
reti ; we don't use this interrupt
reti
; Timer overflow interrupt starting address
SECTION "ENTRY_TIMER", ROM0[$0050]
jp int_timer ; used for generating randomness
jp int_timer
; Serial transfer completion interrupt starting address
SECTION "ENTRY_SERIAL", ROM0[$0058]
reti ; we don't use this interrupt
reti
; Program starting address
@ -64,8 +50,7 @@ SECTION "ENTRY_START", ROM0[$0100]
SECTION "MAIN", ROM0[$0150]
main:
; turn the screen off until everything is initialized,
; or wild glitches will appear
; turn the screen off until everything is initialised
ld a, DISPLAY_OFF
ld [LCD_CONTROL_REGISTER], a
ld [LCD_STATUS_REGISTER], a
@ -76,6 +61,7 @@ main:
; load the video data
call init_palettes
call load_tiles
call load_window_map
call load_background_map
; initialise the objects
@ -110,20 +96,13 @@ main_loop:
.within_vblank:
call update_oam
call read_input
ld a, [current_state]
.in_menu:
cp a, STATE_MENU
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
call handle_input_menu
jp .cleanup
.in_game:
@ -166,6 +145,7 @@ 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"
@ -174,19 +154,16 @@ include "inc/interrupts.asm"
;; Game data
SECTION "DATA0", ROM0[$1000]
;; Tiles
; Small 8x8 pixel images, which are addressable
; and will be used for sprite maps and objects.
; Tiles
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:
@ -197,64 +174,28 @@ 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
; Each map defines a grid of tile addresses,
; which combined will form the desired image.
; Maps
maps_start:
background:
include "maps/background.asm"
window_help:
include "maps/window-help.asm"
window_game:
include "maps/window-game.asm"
window:
include "maps/window.asm"
maps_end:
;; Dictionary
; A list of known words to choose from.
dictionary:
incbin "dict/en.dat"
dictionary_end:
DB
;; 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.
; Messages
message_clear:
DB $00, $00, $00, $00
DB $00, $00, $00, $00
@ -264,66 +205,40 @@ 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 $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 $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 $00, $00, 0, 0
message_won:
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 $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 $00, $00, 0, 0
DB $00, $00, 0, 0
message_lost:
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
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]
;; 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.
@ -333,7 +248,7 @@ obj_selected_letter:
obj_guess_letters:
DS 120
obj_message_letters:
DS 36
DS 32
obj_end:
obj_dma_padding:
DS 160 - (obj_end - obj_start)
@ -343,7 +258,7 @@ obj_dma_padding:
vblank_flag:
DB
; Saves the current random number consisting of 16 bits
; Saves the current 16bit random number
random_number:
DS 2
@ -351,43 +266,38 @@ random_number:
input_state:
DB
; Saves the current game state (see STATE constants)
; Saves the current game state
current_state:
DB
; Saves the subordinate state (see STATE constants)
sub_state:
DB
; Saves the current word
current_word:
DS 5
; Number of the current guess (0..5)
; Number of the current guess
current_guess:
DB
; Position within the current guess (0..4)
; Position within the current guess
current_char:
DB
; Saves the current word
current_word:
DS 5
; The guess attempts
guess_attempts:
guesses:
DS 30
; The corresponding hints
guess_hints:
guesses_hints:
DS 30
; Message timeout (remaining number of frames)
; Message timeout
message_timeout:
DB
; Horizontal position of the letter selection within the alphabet grid
; Horizontal position of the letter selection
selected_letter_x:
DB
; Vertical position of the letter selection within the alphabet grid
; Vertical position of the letter selection
selected_letter_y:
DB

BIN
wordle.gb

Binary file not shown.
Loading…
Cancel
Save