2022-02-23 00:31:52 +00:00
|
|
|
bits 16
|
|
|
|
cpu 8086
|
|
|
|
|
2022-02-22 22:38:06 +00:00
|
|
|
org 0x100
|
|
|
|
|
2022-02-24 22:04:10 +00:00
|
|
|
args_length equ 0x80
|
|
|
|
args_area equ 0x81
|
|
|
|
|
2022-02-23 00:31:52 +00:00
|
|
|
section .code
|
|
|
|
|
2022-02-24 22:04:10 +00:00
|
|
|
parse_arguments:
|
|
|
|
xor ch, ch
|
|
|
|
mov cl, [args_length]
|
2022-02-24 23:05:50 +00:00
|
|
|
mov si, args_area
|
|
|
|
|
|
|
|
; Skip leading spaces
|
|
|
|
.skip_leading_space:
|
|
|
|
test cx, cx
|
|
|
|
jz .leading_spaces_skipped
|
|
|
|
cmp byte [si], ' '
|
|
|
|
jne .leading_spaces_skipped
|
|
|
|
dec cx
|
|
|
|
inc si
|
|
|
|
jmp .skip_leading_space
|
|
|
|
|
|
|
|
.leading_spaces_skipped:
|
|
|
|
|
2022-02-25 00:05:00 +00:00
|
|
|
; See whether we have /h, /u, /l, or /?
|
2022-02-24 23:05:50 +00:00
|
|
|
cmp cx, 2
|
|
|
|
jb .not_mode_option
|
|
|
|
cmp byte [si], '/'
|
|
|
|
jne .not_mode_option
|
|
|
|
|
|
|
|
cmp byte [si + 1], 'h'
|
2022-02-25 00:19:44 +00:00
|
|
|
je .hard_mode
|
|
|
|
cmp byte [si + 1], 'H'
|
2022-02-24 23:05:50 +00:00
|
|
|
jne .not_hard_mode
|
|
|
|
|
|
|
|
.hard_mode:
|
|
|
|
mov byte [hard_mode], 1
|
|
|
|
add si, 2
|
|
|
|
sub cx, 2
|
|
|
|
jmp .after_option_space
|
|
|
|
|
|
|
|
.not_hard_mode:
|
|
|
|
cmp byte [si + 1], 'u'
|
2022-02-25 00:19:44 +00:00
|
|
|
je .ultra_hard_mode
|
|
|
|
cmp byte [si + 1], 'U'
|
2022-02-24 23:05:50 +00:00
|
|
|
jne .not_ultra_hard_mode
|
|
|
|
|
|
|
|
.ultra_hard_mode:
|
|
|
|
mov byte [hard_mode], 1
|
|
|
|
mov byte [ultra_hard_mode], 1
|
|
|
|
add si, 2
|
|
|
|
sub cx, 2
|
|
|
|
|
|
|
|
.after_option_space:
|
|
|
|
test cx, cx
|
|
|
|
jz .option_done
|
|
|
|
cmp byte [si], ' '
|
|
|
|
jne .option_done
|
|
|
|
dec cx
|
|
|
|
inc si
|
|
|
|
jmp .after_option_space
|
|
|
|
|
|
|
|
.option_done:
|
|
|
|
|
|
|
|
.not_ultra_hard_mode:
|
2022-02-25 00:05:00 +00:00
|
|
|
cmp byte [si + 1], 'l'
|
|
|
|
je print_license
|
2022-02-25 00:19:44 +00:00
|
|
|
cmp byte [si + 1], 'L'
|
|
|
|
je print_license
|
2022-02-25 00:05:00 +00:00
|
|
|
|
|
|
|
cmp byte [si + 2], '?'
|
|
|
|
je print_help
|
|
|
|
|
2022-02-24 23:05:50 +00:00
|
|
|
.not_mode_option:
|
2022-02-24 22:04:10 +00:00
|
|
|
|
|
|
|
test cx, cx
|
|
|
|
jz seed_rng_date
|
|
|
|
|
2022-02-25 00:19:12 +00:00
|
|
|
seed_rng_argument:
|
|
|
|
xor ax, ax
|
|
|
|
xor dx, dx
|
|
|
|
mov bp, mull32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
.loop:
|
|
|
|
xor dx, dx
|
|
|
|
mov ax, 10
|
|
|
|
mov bp, mulr32
|
|
|
|
call store32
|
|
|
|
call mul32
|
|
|
|
mov bp, addl32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
lodsb
|
|
|
|
cmp al, '0'
|
|
|
|
jb print_help
|
|
|
|
cmp al, '9'
|
|
|
|
ja print_help
|
|
|
|
|
|
|
|
sub al, '0'
|
|
|
|
|
|
|
|
xor ah, ah
|
|
|
|
xor dx, dx
|
|
|
|
mov bp, addr32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
call add32
|
|
|
|
mov bp, mull32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
loop .loop
|
|
|
|
|
|
|
|
mov bp, rng_seed
|
|
|
|
call store32
|
|
|
|
jmp select_target
|
|
|
|
|
2022-02-24 22:04:10 +00:00
|
|
|
print_help:
|
|
|
|
mov ah, 9
|
|
|
|
mov dx, help_str
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
ret
|
|
|
|
|
2022-02-25 00:05:00 +00:00
|
|
|
print_license:
|
|
|
|
mov ah, 9
|
|
|
|
mov dx, license_str
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
ret
|
|
|
|
|
2022-02-24 19:33:35 +00:00
|
|
|
seed_rng_date:
|
|
|
|
; Get date
|
|
|
|
mov ah, 0x2a
|
|
|
|
int 0x21
|
|
|
|
mov [year], cx
|
|
|
|
mov [month], dh
|
2022-02-24 23:15:35 +00:00
|
|
|
%ifdef DEBUG
|
|
|
|
mov cx, 2022
|
|
|
|
mov dh, 2
|
|
|
|
mov dl, 24
|
|
|
|
%endif
|
2022-02-24 19:33:35 +00:00
|
|
|
mov [day], dl
|
|
|
|
|
|
|
|
; addl32 = year * 10000
|
|
|
|
mov ax, 10000
|
|
|
|
mul word [year]
|
|
|
|
mov bp, addl32
|
|
|
|
call store32
|
2022-02-24 19:14:37 +00:00
|
|
|
|
2022-02-24 19:33:35 +00:00
|
|
|
; addr32 = month * 100 + day
|
|
|
|
mov ax, 100
|
|
|
|
mul word [month]
|
|
|
|
add ax, [day]
|
|
|
|
mov bp, addr32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; rng_seed = addl32 + addr32 = year * 10000 + month * 100 + day
|
|
|
|
call add32
|
|
|
|
mov bp, rng_seed
|
|
|
|
call store32
|
2022-02-24 19:14:37 +00:00
|
|
|
|
2022-02-23 00:31:52 +00:00
|
|
|
select_target:
|
2022-02-24 19:14:37 +00:00
|
|
|
; Call rng to get a number
|
|
|
|
call rng
|
|
|
|
mov bp, rng_output
|
|
|
|
call store32
|
|
|
|
|
2022-02-24 19:19:02 +00:00
|
|
|
; Multiply rng output by number of target words
|
2022-02-24 19:14:37 +00:00
|
|
|
xor si, si
|
|
|
|
xor dx, dx
|
|
|
|
xor ax, ax
|
|
|
|
mov cx, targets_len
|
|
|
|
.multiply_loop:
|
|
|
|
add ax, [rng_output + 0]
|
|
|
|
adc dx, [rng_output + 2]
|
|
|
|
adc si, 0
|
|
|
|
loop .multiply_loop
|
|
|
|
|
|
|
|
mov ax, si
|
2022-02-24 19:19:02 +00:00
|
|
|
%ifdef DEBUG
|
2022-02-24 19:14:37 +00:00
|
|
|
call hexprint16
|
|
|
|
call newline
|
2022-02-24 19:19:02 +00:00
|
|
|
%endif
|
2022-02-23 00:31:52 +00:00
|
|
|
|
2022-02-24 19:14:37 +00:00
|
|
|
load_target:
|
2022-02-23 00:31:52 +00:00
|
|
|
shl si, 1
|
|
|
|
shl si, 1
|
|
|
|
add si, targets
|
|
|
|
|
|
|
|
mov di, target
|
|
|
|
|
2022-02-24 17:14:25 +00:00
|
|
|
call unpack_target
|
2022-02-23 00:31:52 +00:00
|
|
|
|
2022-02-24 19:14:37 +00:00
|
|
|
; Figure out whether this is a removed word
|
|
|
|
; If so, reroll target word
|
|
|
|
cmp byte [target], '{'
|
|
|
|
je select_target
|
|
|
|
|
2022-02-24 22:04:10 +00:00
|
|
|
print_greeting:
|
|
|
|
mov ah, 9
|
|
|
|
mov dx, greeting_str
|
|
|
|
int 0x21
|
|
|
|
|
2022-02-23 00:31:52 +00:00
|
|
|
read_guess:
|
|
|
|
; Number of thus far guessed letters stored in bx
|
|
|
|
xor bx, bx
|
|
|
|
|
|
|
|
.loop:
|
|
|
|
mov ah, 8
|
|
|
|
int 0x21
|
|
|
|
|
2022-02-24 23:42:51 +00:00
|
|
|
cmp al, 3
|
|
|
|
je .ctrl_c
|
|
|
|
|
2022-02-23 00:31:52 +00:00
|
|
|
cmp al, 8
|
|
|
|
je .backspace
|
|
|
|
|
|
|
|
cmp bx, 5
|
|
|
|
je .full
|
|
|
|
|
|
|
|
cmp al, 'A'
|
|
|
|
jb .loop
|
|
|
|
|
|
|
|
cmp al, 'Z'
|
|
|
|
jbe .letter
|
|
|
|
|
|
|
|
cmp al, 'a'
|
|
|
|
jb .loop
|
|
|
|
|
|
|
|
cmp al, 'z'
|
|
|
|
jbe .letter
|
|
|
|
|
|
|
|
jmp .loop
|
|
|
|
|
|
|
|
.full:
|
|
|
|
cmp al, 13
|
|
|
|
je .done
|
|
|
|
|
|
|
|
jmp .loop
|
|
|
|
|
|
|
|
.letter:
|
|
|
|
; Lowercase
|
|
|
|
or al, 32
|
|
|
|
|
|
|
|
mov byte [guess + bx], al
|
|
|
|
inc bx
|
|
|
|
|
|
|
|
; Echo to screen
|
|
|
|
mov dl, al
|
|
|
|
mov ah, 2
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
jmp .loop
|
|
|
|
|
|
|
|
.backspace:
|
|
|
|
test bx, bx
|
|
|
|
jz .loop
|
|
|
|
|
|
|
|
; Rub out the letter
|
|
|
|
; PC-DOS 1.1 documentation says only 8 is needed, but DOSBox
|
|
|
|
; seems buggy here
|
|
|
|
mov ah, 2
|
|
|
|
mov dl, 8
|
|
|
|
int 0x21
|
|
|
|
mov dl, ' '
|
|
|
|
int 0x21
|
|
|
|
mov dl, 8
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
dec bx
|
|
|
|
|
|
|
|
jmp .loop
|
|
|
|
|
2022-02-24 23:42:51 +00:00
|
|
|
.ctrl_c:
|
|
|
|
ret
|
|
|
|
|
2022-02-23 00:31:52 +00:00
|
|
|
.done:
|
|
|
|
|
2022-02-24 23:15:35 +00:00
|
|
|
check_hard_mode:
|
|
|
|
cmp byte [hard_mode], 1
|
|
|
|
jne .done
|
|
|
|
|
|
|
|
; See whether exact hits are reused
|
|
|
|
xor bp, bp
|
|
|
|
mov cx, 5
|
|
|
|
.exact_hits:
|
|
|
|
mov al, [exact_hits + bp]
|
|
|
|
test al, al
|
|
|
|
jz .not_exact_hit
|
|
|
|
|
|
|
|
cmp al, [guess + bp]
|
|
|
|
je .exact_hit_match
|
|
|
|
|
|
|
|
mov dx, bp
|
|
|
|
add dl, '1'
|
|
|
|
mov [exact_hit_error_str.position], dl
|
|
|
|
mov [exact_hit_error_str.letter], al
|
|
|
|
mov si, exact_hit_error_str
|
|
|
|
jmp print_error
|
|
|
|
|
|
|
|
.exact_hit_match:
|
|
|
|
.not_exact_hit:
|
|
|
|
inc bp
|
|
|
|
loop .exact_hits
|
|
|
|
|
|
|
|
; See whether wrongly placed letters are reused
|
|
|
|
xor bp, bp
|
|
|
|
.wrong_places:
|
|
|
|
cmp bp, 5
|
|
|
|
je .done
|
|
|
|
|
|
|
|
mov dl, [wrong_places + bp]
|
|
|
|
test dl, dl
|
|
|
|
jz .not_wrong_place
|
|
|
|
|
|
|
|
; Count how many times letter is used in exact_hits + wrong_places
|
|
|
|
xor bx, bx
|
|
|
|
mov cx, 5
|
|
|
|
mov si, exact_hits
|
|
|
|
.count_exact_hits:
|
|
|
|
lodsb
|
|
|
|
cmp al, dl
|
|
|
|
jne .not_count_exact_hit
|
|
|
|
inc bh
|
|
|
|
.not_count_exact_hit:
|
|
|
|
loop .count_exact_hits
|
|
|
|
mov cx, 5
|
|
|
|
mov si, wrong_places
|
|
|
|
.count_wrong_places:
|
|
|
|
lodsb
|
|
|
|
cmp al, dl
|
|
|
|
jne .not_count_wrong_places
|
|
|
|
inc bh
|
|
|
|
.not_count_wrong_places:
|
|
|
|
loop .count_wrong_places
|
|
|
|
|
|
|
|
; Count how many times letter is used in guess
|
|
|
|
mov cx, 5
|
|
|
|
mov si, guess
|
|
|
|
.count_guess:
|
|
|
|
lodsb
|
|
|
|
cmp al, dl
|
|
|
|
jne .not_count_guess
|
|
|
|
inc bl
|
|
|
|
.not_count_guess:
|
|
|
|
loop .count_guess
|
|
|
|
|
|
|
|
cmp bl, bh
|
|
|
|
jae .used_enough
|
|
|
|
|
|
|
|
mov [wrong_place_error_str.letter], dl
|
|
|
|
mov ax, bp
|
|
|
|
add ax, '1'
|
|
|
|
mov [wrong_place_error_str.position], al
|
|
|
|
mov si, wrong_place_error_str
|
|
|
|
jmp print_error
|
|
|
|
|
|
|
|
.used_enough:
|
|
|
|
.not_wrong_place:
|
|
|
|
inc bp
|
|
|
|
jmp .wrong_places
|
|
|
|
|
|
|
|
.done:
|
|
|
|
|
|
|
|
check_ultra_hard_mode:
|
|
|
|
cmp byte [ultra_hard_mode], 1
|
|
|
|
jne .done
|
|
|
|
|
2022-02-24 23:40:59 +00:00
|
|
|
; See whether any ruled-out letters were used
|
|
|
|
xor bp, bp
|
|
|
|
mov cx, 5
|
|
|
|
.ruled_out:
|
|
|
|
xor bh, bh
|
|
|
|
mov bl, [guess + bp]
|
|
|
|
mov ax, bx
|
|
|
|
mov al, [alphabet + bx - 'a']
|
|
|
|
cmp al, ' '
|
|
|
|
jne .not_ruled_out
|
|
|
|
|
|
|
|
mov [ruled_out_error_str.letter], bl
|
|
|
|
mov ax, bp
|
|
|
|
add al, '1'
|
|
|
|
mov [ruled_out_error_str.position], al
|
|
|
|
mov si, ruled_out_error_str
|
|
|
|
jmp print_error
|
|
|
|
|
|
|
|
.not_ruled_out:
|
|
|
|
inc bp
|
|
|
|
loop .ruled_out
|
|
|
|
|
|
|
|
; See whether wrongly places letters were moved
|
|
|
|
xor bp, bp
|
|
|
|
mov cx, 5
|
|
|
|
.wrong_places:
|
|
|
|
mov al, [wrong_places + bp]
|
|
|
|
test al, al
|
|
|
|
jz .not_wrong_place
|
|
|
|
|
|
|
|
cmp al, [guess + bp]
|
|
|
|
jne .moved
|
|
|
|
|
|
|
|
mov [not_moved_error_str.letter], al
|
|
|
|
mov ax, bp
|
|
|
|
add ax, '1'
|
|
|
|
mov [not_moved_error_str.position], al
|
|
|
|
mov si, not_moved_error_str
|
|
|
|
jmp print_error
|
|
|
|
|
|
|
|
.moved:
|
|
|
|
.not_wrong_place:
|
|
|
|
inc bp
|
|
|
|
loop .wrong_places
|
|
|
|
|
2022-02-24 23:15:35 +00:00
|
|
|
.done:
|
|
|
|
|
2022-02-23 01:00:03 +00:00
|
|
|
check_dictionary:
|
|
|
|
; Dictionary is split by initial letter
|
|
|
|
xor bx, bx
|
|
|
|
mov bl, [guess]
|
|
|
|
sub bl, 'a'
|
|
|
|
|
|
|
|
; Entry in the table is 4 bytes
|
|
|
|
shl bx, 1
|
|
|
|
shl bx, 1
|
|
|
|
mov si, [dictionaries + bx] ; Start address
|
|
|
|
mov cx, [dictionaries + bx + 2] ; Number of letters
|
|
|
|
|
|
|
|
.dictionary_loop:
|
|
|
|
push cx
|
|
|
|
|
|
|
|
mov di, dictionary_entry
|
|
|
|
; Entry is stored 5 bits per letter (first letter is implicit)
|
|
|
|
; 3332_2222 5444_4433 0000_5555
|
|
|
|
; Load 5444_4433_3332_2222 into dx and extract 3 first letters
|
|
|
|
mov dx, [si]
|
|
|
|
add si, 2
|
|
|
|
mov cl, 5
|
|
|
|
%rep 3
|
|
|
|
mov al, dl
|
|
|
|
and al, 0x1f
|
|
|
|
add al, 'a'
|
|
|
|
stosb
|
|
|
|
shr dx, cl
|
|
|
|
%endrep
|
|
|
|
; Load 0000_5555 into al, shift one over, or with dl which has
|
|
|
|
; 0000_0005
|
|
|
|
mov al, [si]
|
|
|
|
inc si
|
|
|
|
shl al, 1
|
|
|
|
or al, dl
|
|
|
|
add al, 'a'
|
|
|
|
stosb
|
|
|
|
|
|
|
|
sub di, 4
|
|
|
|
mov bp, 1
|
|
|
|
mov cx, 4
|
|
|
|
.compare_loop:
|
|
|
|
mov al, [di]
|
|
|
|
inc di
|
|
|
|
cmp al, [guess + bp]
|
|
|
|
jne .not_match
|
|
|
|
inc bp
|
|
|
|
loop .compare_loop
|
|
|
|
|
|
|
|
pop cx
|
|
|
|
jmp word_found
|
|
|
|
|
|
|
|
.not_match:
|
|
|
|
pop cx
|
|
|
|
loop .dictionary_loop
|
|
|
|
|
|
|
|
check_targets:
|
2022-02-24 17:14:25 +00:00
|
|
|
mov cx, targets_len
|
|
|
|
mov si, targets
|
|
|
|
|
|
|
|
.targets_loop:
|
|
|
|
mov di, dictionary_entry
|
|
|
|
call unpack_target
|
|
|
|
|
|
|
|
xor bp, bp
|
|
|
|
.compare_loop:
|
|
|
|
cmp bp, 5
|
|
|
|
je .match
|
|
|
|
|
|
|
|
mov al, [di + bp]
|
|
|
|
cmp al, [guess + bp]
|
|
|
|
jne .not_match
|
|
|
|
|
|
|
|
inc bp
|
|
|
|
jmp .compare_loop
|
|
|
|
|
|
|
|
.match:
|
|
|
|
jmp word_found
|
|
|
|
|
|
|
|
.not_match:
|
|
|
|
loop .targets_loop
|
2022-02-23 01:00:03 +00:00
|
|
|
|
|
|
|
word_not_found:
|
2022-02-24 23:05:50 +00:00
|
|
|
mov si, not_found_str
|
|
|
|
|
|
|
|
print_error:
|
2022-02-23 01:00:03 +00:00
|
|
|
mov ah, 9
|
2022-02-24 23:05:50 +00:00
|
|
|
mov dx, si
|
2022-02-23 01:00:03 +00:00
|
|
|
int 0x21
|
|
|
|
|
|
|
|
; Wait for a keypress
|
|
|
|
mov ah, 8
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
; Clear line
|
|
|
|
mov ah, 2
|
|
|
|
mov dl, 13
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
mov ah, 9
|
|
|
|
mov dx, erase_word_str
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
.clear_loop:
|
|
|
|
lodsb
|
|
|
|
cmp al, '$'
|
|
|
|
je .done
|
|
|
|
|
|
|
|
mov ah, 2
|
|
|
|
mov dl, ' '
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
jmp .clear_loop
|
|
|
|
|
2022-02-24 23:05:50 +00:00
|
|
|
.done:
|
2022-02-23 01:00:03 +00:00
|
|
|
|
|
|
|
mov ah, 2
|
|
|
|
mov dl, 13
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
jmp read_guess
|
|
|
|
|
|
|
|
word_found:
|
2022-02-23 00:31:52 +00:00
|
|
|
|
|
|
|
find_exact_hits:
|
|
|
|
mov si, guess
|
|
|
|
mov di, exact_hits
|
|
|
|
mov cx, 5
|
|
|
|
.loop:
|
|
|
|
lodsb
|
|
|
|
cmp al, [si - guess + target - 1]
|
|
|
|
je .hit
|
|
|
|
|
|
|
|
; Zero out if not the right letter
|
|
|
|
xor al, al
|
|
|
|
|
|
|
|
.hit:
|
|
|
|
stosb
|
|
|
|
loop .loop
|
|
|
|
|
|
|
|
find_wrong_places:
|
|
|
|
; Zero out first
|
|
|
|
mov cx, 5
|
|
|
|
xor al, al
|
|
|
|
rep stosb
|
|
|
|
|
|
|
|
xor bp, bp
|
|
|
|
.loop:
|
|
|
|
cmp bp, 5
|
|
|
|
je .done
|
|
|
|
|
|
|
|
mov al, [exact_hits + bp]
|
|
|
|
inc bp
|
|
|
|
test al, al
|
|
|
|
jnz .loop
|
|
|
|
|
|
|
|
; What was the guessed letter?
|
|
|
|
mov dl, [guess + bp - 1]
|
|
|
|
|
|
|
|
; How many times does it appear in the target?
|
|
|
|
xor bh, bh
|
|
|
|
mov cx, 5
|
|
|
|
mov si, target
|
|
|
|
.count_target:
|
|
|
|
lodsb
|
|
|
|
cmp al, dl
|
|
|
|
jne .not_found_in_target
|
|
|
|
|
|
|
|
inc bh
|
|
|
|
|
|
|
|
.not_found_in_target:
|
|
|
|
loop .count_target
|
|
|
|
|
|
|
|
; How many times does it appear in the feedback already?
|
|
|
|
xor bl, bl
|
|
|
|
mov cx, 5
|
|
|
|
mov si, exact_hits
|
|
|
|
.count_exact_hits:
|
|
|
|
lodsb
|
|
|
|
cmp al, dl
|
|
|
|
jne .not_found_in_exact_hits
|
|
|
|
|
|
|
|
inc bl
|
|
|
|
|
|
|
|
.not_found_in_exact_hits:
|
|
|
|
loop .count_exact_hits
|
|
|
|
mov cx, 5
|
|
|
|
mov si, wrong_places
|
|
|
|
.count_wrong_places:
|
|
|
|
lodsb
|
|
|
|
cmp al, dl
|
|
|
|
jne .not_found_in_wrong_places
|
|
|
|
|
|
|
|
inc bl
|
|
|
|
|
|
|
|
.not_found_in_wrong_places:
|
|
|
|
loop .count_wrong_places
|
|
|
|
|
2022-02-24 21:43:27 +00:00
|
|
|
; If not used in target at all, remove from list of possible letters
|
|
|
|
test bh, bh
|
|
|
|
jnz .used_in_target
|
|
|
|
|
|
|
|
xor dh, dh
|
|
|
|
mov di, dx
|
|
|
|
mov byte [alphabet + di - 'a'], ' '
|
|
|
|
|
|
|
|
.used_in_target:
|
2022-02-23 00:31:52 +00:00
|
|
|
; If in target more than in feedback → wrong place
|
|
|
|
cmp bh, bl ; target <= feedback
|
|
|
|
jbe .loop
|
|
|
|
|
|
|
|
mov byte [wrong_places + bp - 1], dl
|
|
|
|
jmp .loop
|
|
|
|
|
|
|
|
.done:
|
|
|
|
|
|
|
|
print_feedback:
|
|
|
|
call newline
|
|
|
|
mov cx, 5
|
|
|
|
xor bp, bp
|
|
|
|
xor bx, bx ; How many exact hits?
|
|
|
|
.loop:
|
|
|
|
mov al, [exact_hits + bp]
|
|
|
|
test al, al
|
|
|
|
jnz .exact_hit
|
|
|
|
|
|
|
|
mov al, [wrong_places + bp]
|
|
|
|
test al, al
|
|
|
|
jnz .wrong_place
|
|
|
|
|
|
|
|
mov dl, 'x'
|
|
|
|
jmp .print
|
|
|
|
|
|
|
|
.exact_hit:
|
|
|
|
mov dl, ' '
|
|
|
|
inc bx
|
|
|
|
jmp .print
|
|
|
|
|
|
|
|
.wrong_place:
|
|
|
|
mov dl, '^'
|
|
|
|
|
|
|
|
.print:
|
|
|
|
mov ah, 2
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
inc bp
|
|
|
|
loop .loop
|
2022-02-24 21:43:27 +00:00
|
|
|
|
|
|
|
mov ah, 9
|
|
|
|
mov dx, space_dash_space_str
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
mov cx, 26
|
|
|
|
mov si, alphabet
|
|
|
|
.alphabet_loop:
|
|
|
|
lodsb
|
|
|
|
mov dl, al
|
|
|
|
mov ah, 2
|
|
|
|
int 0x21
|
|
|
|
loop .alphabet_loop
|
|
|
|
|
2022-02-23 00:31:52 +00:00
|
|
|
call newline
|
|
|
|
|
|
|
|
is_finished:
|
|
|
|
inc byte [guesses]
|
|
|
|
|
|
|
|
cmp bx, 5
|
|
|
|
je victory
|
|
|
|
|
|
|
|
cmp byte [guesses], 6
|
|
|
|
je loss
|
|
|
|
|
|
|
|
jmp read_guess
|
|
|
|
|
|
|
|
loss:
|
|
|
|
mov dx, word_was_str
|
|
|
|
mov ah, 9
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
mov cx, 5
|
|
|
|
mov si, target
|
|
|
|
.loop:
|
|
|
|
lodsb
|
|
|
|
mov dl, al
|
|
|
|
mov ah, 2
|
|
|
|
int 0x21
|
|
|
|
loop .loop
|
|
|
|
|
|
|
|
jmp exit
|
|
|
|
|
|
|
|
victory:
|
|
|
|
mov dx, correct_in_str
|
|
|
|
mov ah, 9
|
|
|
|
int 0x21
|
|
|
|
|
|
|
|
mov dl, [guesses]
|
|
|
|
add dl, '0'
|
|
|
|
mov ah, 2
|
|
|
|
int 0x21
|
|
|
|
|
2022-02-24 19:38:54 +00:00
|
|
|
cmp byte [guesses], 1
|
|
|
|
je .singular
|
|
|
|
|
|
|
|
.plural:
|
|
|
|
mov dx, guesses_str
|
|
|
|
jmp .print
|
|
|
|
|
|
|
|
.singular:
|
|
|
|
mov dx, guess_str
|
|
|
|
|
|
|
|
.print:
|
|
|
|
mov ah, 9
|
|
|
|
int 0x21
|
2022-02-23 00:31:52 +00:00
|
|
|
|
|
|
|
exit:
|
|
|
|
ret
|
|
|
|
|
|
|
|
newline:
|
|
|
|
push ax
|
|
|
|
push dx
|
|
|
|
mov ah, 2
|
|
|
|
mov dl, 13
|
|
|
|
int 0x21
|
|
|
|
mov dl, 10
|
|
|
|
int 0x21
|
|
|
|
pop dx
|
|
|
|
pop ax
|
|
|
|
ret
|
|
|
|
|
2022-02-24 17:14:25 +00:00
|
|
|
; in:
|
|
|
|
; si = packed target word
|
|
|
|
; di = 5 byte buffer for unpacking the target
|
|
|
|
; out:
|
|
|
|
; si = first byte after the packed target word
|
|
|
|
unpack_target:
|
|
|
|
push ax
|
|
|
|
push cx
|
|
|
|
push dx
|
|
|
|
push di
|
|
|
|
|
|
|
|
; Target word is stored packed 5 bits per letter into 32 bits
|
|
|
|
; 2221_1111 4333_3322 5555_4444 0000_0005
|
|
|
|
; Load 4333_3322_2221_1111 into dx and extracts first three letters
|
|
|
|
mov dx, [si]
|
|
|
|
add si, 2
|
|
|
|
mov cl, 5
|
|
|
|
%rep 3
|
|
|
|
mov al, dl
|
|
|
|
and al, 0x1f
|
|
|
|
add al, 'a'
|
|
|
|
stosb
|
|
|
|
shr dx, cl
|
|
|
|
%endrep
|
|
|
|
|
|
|
|
; Load 0000_0005_5555_4444 into ax, shift over by one, combine into dx
|
|
|
|
; which has 0000_0000_0000_0004, and extract last two letters
|
|
|
|
mov ax, [si]
|
|
|
|
add si, 2
|
|
|
|
shl ax, 1
|
|
|
|
or dx, ax
|
|
|
|
%rep 2
|
|
|
|
mov al, dl
|
|
|
|
and al, 0x1f
|
|
|
|
add al, 'a'
|
|
|
|
stosb
|
|
|
|
shr dx, cl
|
|
|
|
%endrep
|
|
|
|
|
|
|
|
pop di
|
|
|
|
pop dx
|
|
|
|
pop cx
|
|
|
|
pop ax
|
|
|
|
|
|
|
|
ret
|
|
|
|
|
2022-02-24 19:14:37 +00:00
|
|
|
; out:
|
|
|
|
; dx:ax = result
|
|
|
|
rng:
|
|
|
|
; https://github.com/lynn/hello-wordl/blob/7da40c1f067eb1ec157d4c5b7a9bd8257ed39342/src/util.ts#L14
|
|
|
|
|
|
|
|
; rng_t = rng_seed += rng_seed + 0x6d2b79f5
|
|
|
|
mov bp, rng_seed
|
|
|
|
call load32
|
|
|
|
add ax, 0x79f5
|
|
|
|
adc dx, 0x6d2b
|
|
|
|
call store32
|
|
|
|
mov bp, rng_t
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; xorl32 = rng_t
|
|
|
|
mov bp, xorl32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; xorr32 = rng_t >> 15
|
|
|
|
mov cx, 15
|
|
|
|
call rshift32
|
|
|
|
mov bp, xorr32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; mull32 = xorl32 ^ xorr32 = rng_t ^ (rng_t >> 15)
|
|
|
|
call xor32
|
|
|
|
mov bp, mull32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; mulr32 = rng_t | 1
|
|
|
|
mov bp, rng_t
|
|
|
|
call load32
|
|
|
|
or ax, 1
|
|
|
|
mov bp, mulr32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; rng_t = mull32 * mulr32 = (rng_t ^ (rng_t >> 15)) * (rng_t | 1)
|
|
|
|
call mul32
|
|
|
|
mov bp, rng_t
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; xorl32 = rng_t
|
|
|
|
mov bp, xorl32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; xorr32 = rng_t >> 7
|
|
|
|
mov cx, 7
|
|
|
|
call rshift32
|
|
|
|
mov bp, xorr32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; mull32 = xorl32 ^ xorr32 = rng_t ^ (rng_t >> 7)
|
|
|
|
call xor32
|
|
|
|
mov bp, mull32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; mulr32 = rng_t | 61
|
|
|
|
mov bp, rng_t
|
|
|
|
call load32
|
|
|
|
or ax, 61
|
|
|
|
mov bp, mulr32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; addl32 = rng_t
|
|
|
|
mov bp, rng_t
|
|
|
|
call load32
|
|
|
|
mov bp, addl32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; addr32 = mull32 * mulr32 = (rng_t ^ (rng_t >> 7)) * (rng_t | 61)
|
|
|
|
call mul32
|
|
|
|
mov bp, addr32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; xorl32 = rng_t
|
|
|
|
mov bp, rng_t
|
|
|
|
call load32
|
|
|
|
mov bp, xorl32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; xorr32 = addl32 + addr32 = rng_t + (rng_t ^ (rng_t >> 7)) * (rng_t | 61)
|
|
|
|
call add32
|
|
|
|
mov bp, xorr32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; rng_t = xorl32 ^ xorr32 = rng_t ^ (rng_t + (rng_t ^ (rng_t >> 7)) * (rng_t | 61))
|
|
|
|
call xor32
|
|
|
|
mov bp, rng_t
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; xorl32 = rng_t
|
|
|
|
mov bp, xorl32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; xorr32 = rng_t >> 14
|
|
|
|
mov cx, 14
|
|
|
|
call rshift32
|
|
|
|
mov bp, xorr32
|
|
|
|
call store32
|
|
|
|
|
|
|
|
; result = xorl32 ^ xorr32 = rng_t ^ (rng_t >> 14)
|
|
|
|
call xor32
|
|
|
|
|
|
|
|
ret
|
|
|
|
|
|
|
|
; in:
|
|
|
|
; bp = address of uint32
|
|
|
|
; out:
|
|
|
|
; dx = high 16 bits
|
|
|
|
; ax = low 16 bits
|
|
|
|
load32:
|
|
|
|
mov ax, [bp + 0]
|
|
|
|
mov dx, [bp + 2]
|
|
|
|
ret
|
|
|
|
|
|
|
|
; in:
|
|
|
|
; bp = address of uint32
|
|
|
|
; dx = high 16 bits
|
|
|
|
; ax = low 16 bits
|
|
|
|
store32:
|
|
|
|
mov [bp + 0], ax
|
|
|
|
mov [bp + 2], dx
|
|
|
|
ret
|
|
|
|
|
|
|
|
; in:
|
|
|
|
; dx:ax = uint32 to be shifted
|
|
|
|
; cx = shift amount (must not be 0)
|
|
|
|
; out:
|
|
|
|
; dx:ax = result
|
|
|
|
rshift32:
|
|
|
|
push cx
|
|
|
|
.loop:
|
|
|
|
shr dx, 1
|
|
|
|
rcr ax, 1
|
|
|
|
loop .loop
|
|
|
|
pop cx
|
|
|
|
ret
|
|
|
|
|
|
|
|
; in:
|
|
|
|
; [xorl32], [xorr32] = operands
|
|
|
|
; out:
|
|
|
|
; dx:ax = result
|
|
|
|
xor32:
|
|
|
|
mov ax, [xorl32 + 0]
|
|
|
|
xor ax, [xorr32 + 0]
|
|
|
|
mov dx, [xorl32 + 2]
|
|
|
|
xor dx, [xorr32 + 2]
|
|
|
|
ret
|
|
|
|
|
|
|
|
; in:
|
|
|
|
; [mull32], [mulr32] = operands
|
|
|
|
; out:
|
|
|
|
; dx:ax = result
|
|
|
|
mul32:
|
|
|
|
push bx
|
|
|
|
push cx
|
|
|
|
; c = 1<<16
|
|
|
|
; l = l₁<<16 + l₀
|
|
|
|
; r = r₁<<16 + r₀
|
|
|
|
; l·r = (l₁<<16 + l₀)·(r₁<<16 + r₀)
|
|
|
|
; = l₁<<16·r₁<<16 + l₁<<16·r₀ + l₀·r₁<<16 + l₀·r₀
|
|
|
|
; = l₁·r₁<<32 + l₁·r₀<<16 + l₀·r₁<<16 + l₀·r₀ ||1<<32 = 0 (mod 1<<32)
|
|
|
|
; = l₁·r₀<<16 + l₀·r₁<<16 + l₀·r₀
|
|
|
|
|
|
|
|
; l₀·r₀
|
|
|
|
mov ax, [mull32 + 0]
|
|
|
|
mul word [mulr32 + 0]
|
|
|
|
mov bx, ax
|
|
|
|
mov cx, dx
|
|
|
|
|
|
|
|
; l₀·r₁<<16
|
|
|
|
mov ax, [mull32 + 0]
|
|
|
|
mul word [mulr32 + 2]
|
|
|
|
add cx, ax
|
|
|
|
|
|
|
|
; l₁·r₀<<16
|
|
|
|
mov ax, [mull32 + 2]
|
|
|
|
mul word [mulr32 + 0]
|
|
|
|
add cx, ax
|
|
|
|
|
|
|
|
mov dx, cx
|
|
|
|
mov ax, bx
|
|
|
|
|
|
|
|
pop cx
|
|
|
|
pop bx
|
|
|
|
|
|
|
|
ret
|
|
|
|
|
|
|
|
; in:
|
|
|
|
; [addl32], [addr32] = operands
|
|
|
|
; out:
|
|
|
|
; dx:ax = result
|
|
|
|
add32:
|
|
|
|
mov ax, [addl32 + 0]
|
|
|
|
mov dx, [addl32 + 2]
|
|
|
|
add ax, [addr32 + 0]
|
|
|
|
adc dx, [addr32 + 2]
|
|
|
|
ret
|
|
|
|
|
2022-02-24 19:19:02 +00:00
|
|
|
%ifdef DEBUG
|
|
|
|
hexprint32:
|
|
|
|
xchg ax, dx
|
|
|
|
call hexprint16
|
|
|
|
xchg ax, dx
|
|
|
|
hexprint16:
|
|
|
|
xchg ah, al
|
|
|
|
call hexprint8
|
|
|
|
xchg ah, al
|
|
|
|
hexprint8:
|
2022-02-24 19:14:37 +00:00
|
|
|
%rep 4
|
2022-02-24 19:19:02 +00:00
|
|
|
rol al, 1
|
2022-02-24 19:14:37 +00:00
|
|
|
%endrep
|
2022-02-24 19:19:02 +00:00
|
|
|
call hexprint4
|
2022-02-24 19:14:37 +00:00
|
|
|
%rep 4
|
2022-02-24 19:19:02 +00:00
|
|
|
rol al, 1
|
2022-02-24 19:14:37 +00:00
|
|
|
%endrep
|
2022-02-24 19:19:02 +00:00
|
|
|
hexprint4:
|
|
|
|
push ax
|
|
|
|
and al, 0xf
|
|
|
|
cmp al, 10
|
|
|
|
jb .digit09
|
|
|
|
|
|
|
|
add al, 'a' - 10 - '0'
|
|
|
|
|
|
|
|
.digit09:
|
|
|
|
add al, '0'
|
|
|
|
mov ah, 0xe
|
|
|
|
int 0x10
|
|
|
|
|
|
|
|
pop ax
|
|
|
|
ret
|
|
|
|
%endif
|
2022-02-24 19:14:37 +00:00
|
|
|
|
2022-02-23 00:31:52 +00:00
|
|
|
section .data
|
2022-02-24 21:43:27 +00:00
|
|
|
alphabet db 'abcdefghijklmnopqrstuvwxyz'
|
2022-02-23 00:31:52 +00:00
|
|
|
target times 5 db 0
|
|
|
|
guess times 5 db 0
|
2022-02-23 01:00:03 +00:00
|
|
|
|
2022-02-23 00:31:52 +00:00
|
|
|
exact_hits times 5 db 0
|
|
|
|
wrong_places times 5 db 0
|
2022-02-23 01:00:03 +00:00
|
|
|
|
2022-02-23 00:31:52 +00:00
|
|
|
guesses db 0
|
|
|
|
|
2022-02-24 17:14:25 +00:00
|
|
|
dictionary_entry times 5 db 0
|
2022-02-23 01:00:03 +00:00
|
|
|
|
2022-02-24 23:05:50 +00:00
|
|
|
hard_mode db 0
|
|
|
|
ultra_hard_mode db 0
|
|
|
|
|
2022-02-24 19:14:37 +00:00
|
|
|
rng_seed dd 0
|
|
|
|
rng_t dd 0
|
|
|
|
|
|
|
|
rng_output dd 0
|
|
|
|
|
|
|
|
xorl32 dd 0
|
|
|
|
xorr32 dd 0
|
|
|
|
mull32 dd 0
|
|
|
|
mulr32 dd 0
|
|
|
|
addl32 dd 0
|
|
|
|
addr32 dd 0
|
|
|
|
|
2022-02-24 19:33:35 +00:00
|
|
|
year dw 0
|
|
|
|
month dw 0
|
2022-02-24 23:15:35 +00:00
|
|
|
day dw 0
|
|
|
|
|
|
|
|
exact_hit_error_str:
|
|
|
|
db ' - letter at position '
|
|
|
|
.position db '#'
|
|
|
|
db " must be '"
|
|
|
|
.letter db '#'
|
|
|
|
db "'$"
|
2022-02-24 23:40:59 +00:00
|
|
|
|
2022-02-24 23:15:35 +00:00
|
|
|
wrong_place_error_str:
|
|
|
|
db " - letter '"
|
|
|
|
.letter db '#'
|
|
|
|
db "' from position "
|
|
|
|
.position db '#'
|
|
|
|
db ' must be reused$'
|
2022-02-24 19:33:35 +00:00
|
|
|
|
2022-02-24 23:40:59 +00:00
|
|
|
not_moved_error_str:
|
|
|
|
db " - letter '"
|
|
|
|
.letter db '#'
|
|
|
|
db "' in position "
|
|
|
|
.position db '#'
|
|
|
|
db ' must be moved$'
|
|
|
|
|
|
|
|
ruled_out_error_str:
|
|
|
|
db " - letter '"
|
|
|
|
.letter db '#'
|
|
|
|
db "' in position "
|
|
|
|
.position db '#'
|
|
|
|
db ' has been ruled out$'
|
|
|
|
|
2022-02-23 00:31:52 +00:00
|
|
|
section .rodata
|
|
|
|
|
2022-02-27 14:11:42 +00:00
|
|
|
greeting_str db 'Welcome to hello DOSdl. Press Ctrl+C to exit. Run `dosdl /?` for help.', 13, 10, '$'
|
2022-02-24 22:04:10 +00:00
|
|
|
|
2022-02-24 21:43:27 +00:00
|
|
|
space_dash_space_str db ' - $'
|
2022-02-24 23:05:50 +00:00
|
|
|
not_found_str db ' - word not found$'
|
2022-02-23 01:00:03 +00:00
|
|
|
erase_word_str db ' $'
|
2022-02-23 00:31:52 +00:00
|
|
|
word_was_str db 'The word was: $'
|
|
|
|
correct_in_str db 'Correct in $'
|
|
|
|
guesses_str db ' guesses.$'
|
2022-02-24 19:38:54 +00:00
|
|
|
guess_str db ' guess.$'
|
2022-02-22 22:38:06 +00:00
|
|
|
|
2022-02-24 22:04:10 +00:00
|
|
|
help_str:
|
2022-02-25 00:19:12 +00:00
|
|
|
db 'Usage: dosdl [/h | /u | /l | /?] [seed]', 13, 10
|
2022-02-25 13:53:55 +00:00
|
|
|
db '/h Enable hard mode.', 13, 10
|
|
|
|
db '/u Enable ultra hard mode.', 13, 10
|
|
|
|
db '/l Display license info.', 13, 10
|
|
|
|
db '/? Display this help.', 13, 10
|
2022-02-24 22:04:10 +00:00
|
|
|
db 13, 10
|
|
|
|
db 'Hello DOSdl is a word guessing game. You have six tries to guess the correct', 13, 10
|
|
|
|
db 'English word. After a guess the game displays feedback under each letter:', 13, 10
|
|
|
|
db 13, 10
|
|
|
|
db "' ' Letter is in the correct place.", 13, 10
|
|
|
|
db "'^' Letter is in the wrong place.", 13, 10
|
|
|
|
db "'x' Letter is not in used in the word, or its uses are already covered by the", 13, 10
|
|
|
|
db ' above cases.', 13, 10
|
|
|
|
db 13, 10
|
|
|
|
db 'After the feedback, the game shows a list of letters that have not yet been', 13, 10
|
2022-02-24 23:15:35 +00:00
|
|
|
db 'ruled out.', 13, 10
|
|
|
|
db 13, 10
|
|
|
|
db 'In hard mode all letters marked as being in the correct place must stay fixed', 13, 10
|
|
|
|
db 'and those marked as being in the wrong place must be reused. In ultra hard mode', 13, 10
|
2022-02-24 23:53:47 +00:00
|
|
|
db 'letters marked as being in the wrong place must also be moved and letters that', 13, 10
|
|
|
|
db 'have been ruled out must not be played again.$'
|
2022-02-24 22:04:10 +00:00
|
|
|
|
2022-02-22 22:38:06 +00:00
|
|
|
%include "dictionary.inc"
|
|
|
|
%include "targets.inc"
|
2022-02-25 00:05:00 +00:00
|
|
|
%include "license.inc"
|