diff --git a/compress-targets.py b/compress-targets.py index 5710b78..32b4975 100644 --- a/compress-targets.py +++ b/compress-targets.py @@ -22,6 +22,6 @@ for word in words: array.append(packed) with open(targetpath, 'w') as f: - f.write('tagets:\n') + f.write('targets:\n') for packed in array: f.write(f'\tdb {", ".join(str(byte) for byte in packed)}\n') diff --git a/dosdl.asm b/dosdl.asm index bd5a85c..e433f12 100644 --- a/dosdl.asm +++ b/dosdl.asm @@ -1,6 +1,306 @@ +bits 16 +cpu 8086 + org 0x100 -ret +section .code + +select_target: + ; TODO: Implement target word selection + mov si, 1 + +extract_target: + shl si, 1 + shl si, 1 + add si, targets + + mov di, target + + ; 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 + +read_guess: + ; Number of thus far guessed letters stored in bx + xor bx, bx + + .loop: + mov ah, 8 + int 0x21 + + 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 + + .done: + +check_guess: + ; TODO: See whether guess is in the dictionary or targets + +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 di, wrong_places + 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 + + ; 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 + 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 + + mov dx, guesses_str + mov ah, 9 + int 0x21 + +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 + +section .data +target times 5 db 0 +guess times 5 db 0 +exact_hits times 5 db 0 +wrong_places times 5 db 0 +guesses db 0 + +section .rodata + +word_was_str db 'The word was: $' +correct_in_str db 'Correct in $' +guesses_str db ' guesses.$' %include "dictionary.inc" %include "targets.inc"