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
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
|
||
|
|