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. 145
      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. 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 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 Controls
--------- ---------
``` ```
START Starts a new game START Starts a new game
SELECT Selects a letter SELECT Confirms the entered word
→ ↓ ← ↑ Moves the cursor → ↓ ← ↑ Moves the cursor
A Selects a character A Selects a character
B Deletes the last character B Deletes the last character

21
dict/compress.py

@ -1,4 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""
To fit the whole game into one memory bank, the dictionary is compressed.
Since only 2^5 combinations are needed to store 26 letters,
5 bits would be enough; for simplicity's sake, however, we take 6.
This way we can reduce the memory consumption by 20%.
"""
import struct import struct
def compress(in_path: str, out_path:str): def compress(in_path: str, out_path:str):
@ -13,13 +20,13 @@ def compress(in_path: str, out_path:str):
if len(set(list(word))) != len(word): if len(set(list(word))) != len(word):
continue continue
a = (((ord(word[0])-0x61) << 2) & 0x00fc) | \ a = (((ord(word[0])-0x60) << 2) & 0x00fc) | \
(((ord(word[1])-0x61) >> 4) & 0x0003) (((ord(word[1])-0x60) >> 4) & 0x0003)
b = (((ord(word[1])-0x61) << 4) & 0x00f0) | \ b = (((ord(word[1])-0x60) << 4) & 0x00f0) | \
(((ord(word[2])-0x61) >> 2) & 0x000f) (((ord(word[2])-0x60) >> 2) & 0x000f)
c = (((ord(word[2])-0x61) << 6) & 0x00c0) | \ c = (((ord(word[2])-0x60) << 6) & 0x00c0) | \
(((ord(word[3])-0x61) >> 0) & 0x003f); (((ord(word[3])-0x60) >> 0) & 0x003f);
d = (((ord(word[4])-0x61) << 2) & 0x00fc) d = (((ord(word[4])-0x60) << 2) & 0x00fc)
pack = struct.pack("BBBB", a, b, c, d) pack = struct.pack("BBBB", a, b, c, d)
data.write(pack) 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 Flags
INTERRUPT_SETTINGS EQU $ffff INTERRUPT_SETTINGS EQU $ffff
INT_VBLANK_ON EQU %00000001 INT_VBLANK_ON EQU %00000001

145
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:
; n+0: 11111122 ; In the dictionary, entries with a word length of five are stored with only four bytes.
; n+1: 22223333 ; n+0: 11111122
; n+2: 33444444 ; n+1: 22223333
; n+3: 55555500 ; 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: select_word:
ld de, current_word ld de, current_word
; determine the starting address of the dictionary entry
; (start address + random * word length)
ld a, [random_number+0] ld a, [random_number+0]
and %00011111 and %00011111
ld h, a ld h, a
@ -95,3 +109,120 @@ select_word:
ld [de], a ld [de], a
ret ret
; In order to check whether an entered word exists in the dictionary,
; it must first be compressed according to the dictionary.
; -> [current guess]: current rate attempt, stored in five bytes
; <- bc: first two bytes of the compression
; <- de: second two bytes of the compression
compress_guess:
call get_guess_offset
; first byte
ld a, [hl+] ; letter 1
and %00111111
sla a
sla a
ld b, a
ld a, [hl] ; letter 2
and %00110000
sra a
sra a
sra a
sra a
add a, b
ld d, a
; second byte
ld a, [hl+] ; letter 2
and %00001111
sla a
sla a
sla a
sla a
ld b, a
ld a, [hl] ; letter 3
and %00111100
sra a
sra a
add a, b
ld e, a
push de
; third byte
ld a, [hl+] ; letter 3
and %00000011
sla a
sla a
sla a
sla a
sla a
sla a
ld b, a
ld a, [hl+] ; letter 4
and %00111111
add a, b
ld d, a
; fourth byte
ld a, [hl] ; letter 5
and %00111111
sla a
sla a
ld e, a
pop bc
ret
; Try to find the current guess within the dictionary
; -> bc: first two bytes of the compression
; -> de: second two bytes of the compression
; <- a: whether the entry exists
find_guess:
ld hl, dictionary
.loop:
; check if the end of the dictionary is reached
push bc
ld bc, dictionary_end
ld a, h
cp a, b
jp nz, .not_eof
ld a, l
cp a, c
jp nz, .not_eof
pop bc
jp .return
.not_eof:
pop bc
ld a, [hl+]
cp a, b
jp nz, .add3
ld a, [hl+]
cp a, c
jp nz, .add2
ld a, [hl+]
cp a, d
jp nz, .add1
ld a, [hl+]
cp a, e
jp nz, .add0
ld a, 1
ret
.add3:
inc hl
.add2:
inc hl
.add1:
inc hl
.add0:
jp .loop
.return:
ld a, 0
ret

30
inc/guess.asm

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

33
inc/hints.asm

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

164
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: init_state_menu:
ld a, STATE_MENU ld a, STATE_MENU
ld [current_state], a ld [current_state], a
ld a, STATE_MENU_START
ld [sub_state], a
; set the background position ; set the background position
ld a, 0 ld a, 0
ld [BKG_POS_X_REGISTER], a ld [BKG_POS_X_REGISTER], a
ld [BKG_POS_Y_REGISTER], a ld [BKG_POS_Y_REGISTER], a
call show_message_menu_start
; turn the screen on ; 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 \ + BKG_DISPLAY_ON + BKG_USE_LOC_9800 \
+ WND_DISPLAY_OFF + WND_USE_LOC_9C00 \ + WND_DISPLAY_OFF + WND_USE_LOC_9C00 \
+ OBJ_DISPLAY_OFF + OBJ_SIZE_8X8 + OBJ_DISPLAY_ON + OBJ_SIZE_8X8
ld [LCD_CONTROL_REGISTER], a ld [LCD_CONTROL_REGISTER], a
ret 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: init_state_game:
; set the current state ; set the current state
ld a, STATE_GAME ld a, STATE_GAME
ld [current_state], a ld [current_state], a
; turn the screen off
ld a, DISPLAY_OFF
ld [LCD_CONTROL_REGISTER], a
call select_word call select_word
call clear_message
; set the background position ; set the background position
ld a, 0 ld a, 0
@ -35,18 +139,22 @@ init_state_game:
; set the window position ; set the window position
ld a, 3 ld a, 3
ld [WND_POS_X_REGISTER], a ld [WND_POS_X_REGISTER], a
ld a, $5e ld a, $68
ld [WND_POS_Y_REGISTER], a 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 a, 0
ld [selected_letter_x], a ld [selected_letter_x], a
ld [selected_letter_y], a ld [selected_letter_y], a
ld [current_guess], a ld [current_guess], a
ld [current_char], a ld [current_char], a
.reset_guesses .reset_guess_attempts
ld hl, guesses ld hl, guess_attempts
ld a, NULL ld a, NULL
ld d, 30 ld d, 30
.loop1: .loop1:
@ -55,7 +163,7 @@ init_state_game:
jp nz, .loop1 jp nz, .loop1
.reset_hints .reset_hints
ld hl, guesses_hints ld hl, guess_hints
ld a, TILE_WHITE ld a, TILE_WHITE
ld d, 30 ld d, 30
.loop2: .loop2:
@ -64,7 +172,7 @@ init_state_game:
jp nz, .loop2 jp nz, .loop2
; turn the screen on ; 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 \ + BKG_DISPLAY_ON + BKG_USE_LOC_9800 \
+ WND_DISPLAY_ON + WND_USE_LOC_9C00 \ + WND_DISPLAY_ON + WND_USE_LOC_9C00 \
+ OBJ_DISPLAY_ON + OBJ_SIZE_8X8 + OBJ_DISPLAY_ON + OBJ_SIZE_8X8
@ -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: init_state_lost:
ld a, STATE_LOST ld a, STATE_LOST
ld [current_state], a 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: init_state_won:
ld a, STATE_WON ld a, STATE_WON
ld [current_state], a 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: init_palettes:
ld a, %10010011 ld a, %10010011
ld [PALETTE_BKG_REGISTER], a 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: load_tiles:
ld bc, tiles_start ld bc, tiles_start
ld hl, TLS_LOC_8000 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: load_background_map:
ld bc, background ld bc, background
ld hl, BKG_LOC_9800 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: load_window_map:
ld bc, window ld bc, WND_LOC_9C00
ld hl, WND_LOC_9C00
ld d, 32 ld d, 32
ld e, 32 ld e, 5
.loop: .loop:
ld a, [bc] ld a, [hl]
ld [hl], a ld [bc], a
inc bc
inc hl inc hl
inc bc
dec d dec d
jp nz, .loop 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] ;; Handles the player inputs
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 ; Read the current input state
; -> b: current keystates ; <- b: current keystates
; -> c: changed keys since last read ; <- c: changed keys since last read
read_input: read_input:
di di
@ -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: handle_input_menu:
.check_movement:
ld a, c ld a, c
and a, INPUT_START and a, INPUT_UP | INPUT_DOWN
jp z, .nothing 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 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 ret
; React on input within the main game ; React to input within the main game
; <- c: changed keys since last read ; -> c: the changed keystate
; <- [selected_letter_x]
; <- [selected_letter_y]
handle_input_game: handle_input_game:
ld a, [selected_letter_x] ld a, [selected_letter_x]
ld d, a ld d, a
@ -120,8 +130,11 @@ handle_input_game:
jp z, .check_left jp z, .check_left
ld a, d ld a, d
cp a, $08 cp a, $08
jp z, .check_left jp z, .overflow_right
inc d inc d
jp .check_left
.overflow_right:
ld d, 0
.check_left: .check_left:
ld a, c ld a, c
@ -129,8 +142,11 @@ handle_input_game:
jp z, .check_up jp z, .check_up
ld a, d ld a, d
cp a, 0 cp a, 0
jp z, .check_up jp z, .overflow_left
dec d dec d
jp .check_up
.overflow_left:
ld d, 8
.check_up: .check_up:
ld a, c ld a, c
@ -138,8 +154,11 @@ handle_input_game:
jp z, .check_down jp z, .check_down
ld a, e ld a, e
cp a, 0 cp a, 0
jp z, .check_down jp z, .overflow_up
dec e dec e
jp .check_down
.overflow_up:
ld e, 2
.check_down: .check_down:
ld a, c ld a, c
@ -147,8 +166,11 @@ handle_input_game:
jp z, .check_a jp z, .check_a
ld a, e ld a, e
cp a, $02 cp a, $02
jp z, .check_a jp z, .overflow_down
inc e inc e
jp .check_a
.overflow_down:
ld e, 0
.check_a: .check_a:
ld a, c 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: handle_input_after:
ld a, c ld a, c
and a, INPUT_START and a, INPUT_START
jp z, .nothing jp z, .nothing
call init_state_game call init_state_game
call clear_message call clear_message
.nothing .nothing
ret ret
; Add a character to the guess ; Select a character and add it to the current guess
; -> d: x position of the cursor ; -> d: x position of the cursor
; -> e: y position of the cursor ; -> e: y position of the cursor
; <- [current_guess]
; <- [current_char]
; <- [guess_attempts]
select_letter: select_letter:
push hl push hl
push af push af
@ -198,17 +224,18 @@ select_letter:
ld b, 9 ld b, 9
call multiply_ab call multiply_ab
add a, d add a, d
inc a
ld c, a ld c, a
; check if it's enter ; check if it's enter
ld a, c ld a, c
cp a, 26 cp a, 27
jp nz, .normal_letter jp nz, .normal_letter
call check_guess call check_guess
jp .return jp .return
.normal_letter: .normal_letter:
ld hl, guesses ld hl, guess_attempts
ld a, [current_guess] ld a, [current_guess]
ld b, 5 ld b, 5
call multiply_ab call multiply_ab
@ -235,14 +262,17 @@ select_letter:
; Delete the last letter ; Delete the last entered letter
; <- [current_guess]
; <- [current_char]
; <- [guess_attempts]
delete_letter: delete_letter:
push hl push hl
push af push af
push bc push bc
push de push de
ld hl, guesses ld hl, guess_attempts
ld a, [current_guess] ld a, [current_guess]
ld b, 5 ld b, 5
call multiply_ab call multiply_ab
@ -269,3 +299,47 @@ delete_letter:
pop hl pop hl
ret 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: int_vblank:
push af push af
ld a, 1 ld a, 1
@ -11,7 +19,10 @@ int_vblank:
; Interrupt handler for the timer ; Interrupt handler for the timer
; ;
; Getting random numbers is hard, here we read the vertical position of the scanline, ; Getting random numbers is hard, here we read the vertical position of the scanline,
; save them periodically and use them to get something. ; save them periodically and use them to get something. This approach works,
; but is not unbalanced because the y position only goes from 0 to 153.
; To get around this, two values are stored as in a shift register
; and not all bits of this are used when determining the random number.
int_timer: int_timer:
push hl push hl
push af push af
@ -26,7 +37,7 @@ int_timer:
ld hl, LCD_POSITION_REGISTER ld hl, LCD_POSITION_REGISTER
ld a, [hl] ld a, [hl]
; save the new number ; save the old and new number
ld hl, random_number ld hl, random_number
ld [hl+], a ld [hl+], a
ld a, d ld a, d

8
inc/math.asm

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

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 ; Inform that the current guess is not in the dictionary
; <- de: message address
; <- b: message timeout
show_message_unknown: show_message_unknown:
ld de, message_unknown ld de, message_unknown
ld b, 180 ld b, 180 ; three seconds
call show_message call show_message
ret ret
; Inform about the users victory ; Inform about the users victory
; <- de: message address
; <- b: message timeout
show_message_won: show_message_won:
ld de, message_won ld de, message_won
ld b, 0 ld b, 0
@ -17,6 +53,8 @@ show_message_won:
; Inform about the users loss ; Inform about the users loss
; <- de: message address
; <- b: message timeout
show_message_lost: show_message_lost:
ld de, message_lost ld de, message_lost
ld b, 0 ld b, 0
@ -39,12 +77,18 @@ ENDR
; Displays a message to the user ; Generic function to present a message to the user
; <- de ; -> de: message address
; <- b ; -> b: message timeout
; <- [obj_message_letters]
; <- [message_timeout]
show_message: show_message:
push hl
push bc
push de
ld hl, obj_message_letters ld hl, obj_message_letters
ld c, 32 ld c, 36
.loop: .loop:
ld a, [de] ld a, [de]
ld [hl], a ld [hl], a
@ -55,11 +99,18 @@ show_message:
ld a, b ld a, b
ld [message_timeout], a ld [message_timeout], a
pop de
pop bc
pop hl
ret 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: check_message_timeout:
ld a, [message_timeout] ld a, [message_timeout]
cp a, 0 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: clear_message:
ld de, message_clear ld de, message_clear
ld b, 0 ld b, 0

22
inc/oam.asm

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

113
inc/search.asm

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

22
inc/wincondition.asm

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

70
maps/background.asm

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

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

BIN
wordle.gb

Binary file not shown.
Loading…
Cancel
Save