You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

304 lines
6.0 KiB

2 years ago
include "inc/constants.asm"
;; Game specific constants
; Game states
STATE_MENU EQU %00000001
STATE_GAME EQU %00000010
STATE_LOST EQU %00000100
STATE_WON EQU %00001100
; Marker for invalid or undefined values
NULL EQU $1c
;; Indices of special tiles
TILE_BLACK EQU $1a
TILE_WHITE EQU $1b
TILE_NULL EQU NULL
TILE_PLACEHOLDER EQU $1d
TILE_ENTER EQU $1e
TILE_RIGHT EQU $1f
TILE_MISPLACED EQU $20
TILE_WRONG EQU $21
; Vertical blanking interrupt starting address
SECTION "ENTRY_VBLANK", ROM0[$0040]
jp int_vblank
; LCDC status interrupt starting address
SECTION "ENTRY_LCDCS", ROM0[$0048]
reti
; Timer overflow interrupt starting address
SECTION "ENTRY_TIMER", ROM0[$0050]
jp int_timer
; Serial transfer completion interrupt starting address
SECTION "ENTRY_SERIAL", ROM0[$0058]
reti
; Program starting address
SECTION "ENTRY_START", ROM0[$0100]
jp main
SECTION "MAIN", ROM0[$0150]
main:
; turn the screen off until everything is initialised
ld a, DISPLAY_OFF
ld [LCD_CONTROL_REGISTER], a
ld [LCD_STATUS_REGISTER], a
; set the stack pointer
ld sp, INITIAL_STACK_POINTER
; load the video data
call init_palettes
call load_tiles
call load_window_map
call load_background_map
; initialise the objects
call init_oam_copy
call update_oam
; initialise the game state
call init_state_menu
; enable specific interrupts
ld a, INT_VBLANK_ON + INT_TIMER_ON
ld [INTERRUPT_SETTINGS], a
; configure the timer
ld a, TIMER_START + TIMER_16KHZ
ld [TIMER_SETTINGS], a
; Every frame consists of the phases:
; 1) The display will be updated.
; Within this period we can't alter the graphics data.
; We use this time to handle input and calculate stuff.
; 2) The display was updated.
; Now we have a limited time frame where we can update
; all graphic related memory locations.
main_loop:
ld a, [vblank_flag]
cp a, 0
jp z, main_loop
.within_vblank:
call update_oam
call read_input
ld a, [current_state]
.in_menu:
cp a, STATE_MENU
jp nz, .in_game
call handle_input_menu
jp .cleanup
.in_game:
cp a, STATE_GAME
jp nz, .in_won
call handle_input_game
call update_hint_markings
call update_guess_objects
call update_cursor_objects
jp .cleanup
.in_won:
cp a, STATE_WON
jp nz, .in_lost
call handle_input_after
call update_hint_markings
jp .cleanup
.in_lost:
cp a, STATE_LOST
jp nz, .cleanup
call handle_input_after
call update_hint_markings
jp .cleanup
.cleanup:
; reset vblank flag
ld a, 0
ld [vblank_flag], a
call check_message_timeout
jp main_loop
include "inc/init.asm"
include "inc/math.asm"
include "inc/oam.asm"
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"
;; Game data
SECTION "DATA0", ROM0[$1000]
; Tiles
tiles_start:
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:
include "tiles/sign-enter.asm"
tiles_right:
include "tiles/sign-right.asm"
tile_misplaced:
include "tiles/sign-misplaced.asm"
tiles_wrong:
include "tiles/sign-wrong.asm"
tiles_logo:
include "tiles/logo.asm"
tiles_end:
; Maps
maps_start:
background:
include "maps/background.asm"
window:
include "maps/window.asm"
maps_end:
dictionary:
incbin "dict/en.dat"
dictionary_end:
DB
; Messages
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
DB $00, $00, $00, $00
message_unknown:
DB $7a, $38, 20, OBJ_ATTR_PALETTE1 ; U
DB $7a, $40, 13, OBJ_ATTR_PALETTE1 ; N
DB $7a, $48, 10, OBJ_ATTR_PALETTE1 ; k
DB $7a, $50, 13, OBJ_ATTR_PALETTE1 ; N
DB $7a, $58, 14, OBJ_ATTR_PALETTE1 ; O
DB $7a, $60, 22, OBJ_ATTR_PALETTE1 ; W
DB $7a, $68, 13, OBJ_ATTR_PALETTE1 ; N
DB $00, $00, 0, 0
message_won:
DB $7a, $38, 24, OBJ_ATTR_PALETTE1 ; Y
DB $7a, $40, 14, OBJ_ATTR_PALETTE1 ; O
DB $7a, $48, 20, OBJ_ATTR_PALETTE1 ; U
DB $7a, $58, 22, OBJ_ATTR_PALETTE1 ; W
DB $7a, $60, 14, OBJ_ATTR_PALETTE1 ; O
DB $7a, $68, 13, OBJ_ATTR_PALETTE1 ; N
DB $00, $00, 0, 0
DB $00, $00, 0, 0
message_lost:
DB $7a, $30, 8, OBJ_ATTR_PALETTE1 ; I
DB $7a, $38, 19, OBJ_ATTR_PALETTE1 ; T
DB $7a, $40, 18, OBJ_ATTR_PALETTE1 ; S
DB $7a, $50, 0, OBJ_ATTR_PALETTE1 ; guess[0]
DB $7a, $58, 0, OBJ_ATTR_PALETTE1 ; guess[1]
DB $7a, $60, 0, OBJ_ATTR_PALETTE1 ; guess[2]
DB $7a, $68, 0, OBJ_ATTR_PALETTE1 ; guess[3]
DB $7a, $70, 0, OBJ_ATTR_PALETTE1 ; guess[4]
; 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.
obj_start:
obj_selected_letter:
DS 4
obj_guess_letters:
DS 120
obj_message_letters:
DS 32
obj_end:
obj_dma_padding:
DS 160 - (obj_end - obj_start)
; Will be set to 1 after each vblank interrupt
vblank_flag:
DB
; Saves the current 16bit random number
random_number:
DS 2
; Saves the last keystate
input_state:
DB
; Saves the current game state
current_state:
DB
; Saves the current word
current_word:
DS 5
; Number of the current guess
current_guess:
DB
; Position within the current guess
current_char:
DB
; The guess attempts
guesses:
DS 30
; The corresponding hints
guesses_hints:
DS 30
; Message timeout
message_timeout:
DB
; Horizontal position of the letter selection
selected_letter_x:
DB
; Vertical position of the letter selection
selected_letter_y:
DB