ORG 0000H

CELL1      EQU 30H
CELL2      EQU 31H
CELL3      EQU 32H
CELL4      EQU 33H
CELL5      EQU 34H
CELL6      EQU 35H
CELL7      EQU 36H
CELL8      EQU 37H
CELL9      EQU 38H

CURPLAYER  EQU 39H
MODEVAR    EQU 3AH
MOVECOUNT  EQU 3BH
SELCELL    EQU 3CH
MARKTMP    EQU 3DH

START:
    MOV P0, #0FFH
    MOV P1, #0FFH
    MOV P2, #0FFH
    MOV P3, #0FFH

    LCALL DELAY_BIG
    LCALL LCD_INIT

MODE_SCREEN:
    LCALL SHOW_MODE_SELECT

WAIT_MODE_KEY:
    LCALL SCAN_KEY
    JZ WAIT_MODE_KEY
    MOV R4, A

WAIT_MODE_RELEASE:
    LCALL SCAN_KEY
    JNZ WAIT_MODE_RELEASE

    MOV A, R4
    CJNE A, #2AH, CHECK_AI_MODE
    MOV MODEVAR, #01H
    SJMP MODE_DONE

CHECK_AI_MODE:
    CJNE A, #23H, WAIT_MODE_KEY
    MOV MODEVAR, #02H

MODE_DONE:
    LCALL GAME_INIT

MAIN_LOOP:
    LCALL SCAN_KEY
    JZ MAIN_LOOP
    MOV R4, A

WAIT_KEY_RELEASE:
    LCALL SCAN_KEY
    JNZ WAIT_KEY_RELEASE

    MOV A, R4
    CJNE A, #30H, NOT_ZERO_KEY
    LCALL GAME_INIT
    SJMP MAIN_LOOP

NOT_ZERO_KEY:
    LCALL PROCESS_KEY
    SJMP MAIN_LOOP

;---------------------------------
; INITIALIZE / NEW GAME
;---------------------------------
GAME_INIT:
    MOV CELL1, #00H
    MOV CELL2, #00H
    MOV CELL3, #00H
    MOV CELL4, #00H
    MOV CELL5, #00H
    MOV CELL6, #00H
    MOV CELL7, #00H
    MOV CELL8, #00H
    MOV CELL9, #00H

    MOV CURPLAYER, #01H
    MOV MOVECOUNT, #00H
    MOV SELCELL, #00H

    MOV P0, #0FFH
    MOV P2, #0FFH
    SETB P1.6
    SETB P1.7

    LCALL SHOW_TURN
    RET

;---------------------------------
; PROCESS ONLY 1 TO 9
; 0 = NEW GAME already handled
; * and # ignored during game
;---------------------------------
PROCESS_KEY:
    CJNE A, #31H, CHECK_KEY_2
    LCALL HANDLE_CELL_1
    RET

CHECK_KEY_2:
    CJNE A, #32H, CHECK_KEY_3
    LCALL HANDLE_CELL_2
    RET

CHECK_KEY_3:
    CJNE A, #33H, CHECK_KEY_4
    LCALL HANDLE_CELL_3
    RET

CHECK_KEY_4:
    CJNE A, #34H, CHECK_KEY_5
    LCALL HANDLE_CELL_4
    RET

CHECK_KEY_5:
    CJNE A, #35H, CHECK_KEY_6
    LCALL HANDLE_CELL_5
    RET

CHECK_KEY_6:
    CJNE A, #36H, CHECK_KEY_7
    LCALL HANDLE_CELL_6
    RET

CHECK_KEY_7:
    CJNE A, #37H, CHECK_KEY_8
    LCALL HANDLE_CELL_7
    RET

CHECK_KEY_8:
    CJNE A, #38H, CHECK_KEY_9
    LCALL HANDLE_CELL_8
    RET

CHECK_KEY_9:
    CJNE A, #39H, IGNORE_KEY
    LCALL HANDLE_CELL_9
    RET

IGNORE_KEY:
    RET

;---------------------------------
; CELL 1
;---------------------------------
HANDLE_CELL_1:
    MOV SELCELL, #01H
    MOV A, CELL1
    JZ CELL1_EMPTY
    LCALL INVALID_MOVE
    RET

CELL1_EMPTY:
    MOV A, CURPLAYER
    CJNE A, #01H, CELL1_PLACE_O

CELL1_PLACE_X:
    MOV CELL1, #01H
    CLR P0.0
    SETB P2.0
    LCALL AFTER_VALID_MOVE
    RET

CELL1_PLACE_O:
    MOV CELL1, #02H
    SETB P0.0
    CLR P2.0
    LCALL AFTER_VALID_MOVE
    RET

;---------------------------------
; CELL 2
;---------------------------------
HANDLE_CELL_2:
    MOV SELCELL, #02H
    MOV A, CELL2
    JZ CELL2_EMPTY
    LCALL INVALID_MOVE
    RET

CELL2_EMPTY:
    MOV A, CURPLAYER
    CJNE A, #01H, CELL2_PLACE_O

CELL2_PLACE_X:
    MOV CELL2, #01H
    CLR P0.1
    SETB P2.1
    LCALL AFTER_VALID_MOVE
    RET

CELL2_PLACE_O:
    MOV CELL2, #02H
    SETB P0.1
    CLR P2.1
    LCALL AFTER_VALID_MOVE
    RET

;---------------------------------
; CELL 3
;---------------------------------
HANDLE_CELL_3:
    MOV SELCELL, #03H
    MOV A, CELL3
    JZ CELL3_EMPTY
    LCALL INVALID_MOVE
    RET

CELL3_EMPTY:
    MOV A, CURPLAYER
    CJNE A, #01H, CELL3_PLACE_O

CELL3_PLACE_X:
    MOV CELL3, #01H
    CLR P0.2
    SETB P2.2
    LCALL AFTER_VALID_MOVE
    RET

CELL3_PLACE_O:
    MOV CELL3, #02H
    SETB P0.2
    CLR P2.2
    LCALL AFTER_VALID_MOVE
    RET

;---------------------------------
; CELL 4
;---------------------------------
HANDLE_CELL_4:
    MOV SELCELL, #04H
    MOV A, CELL4
    JZ CELL4_EMPTY
    LCALL INVALID_MOVE
    RET

CELL4_EMPTY:
    MOV A, CURPLAYER
    CJNE A, #01H, CELL4_PLACE_O

CELL4_PLACE_X:
    MOV CELL4, #01H
    CLR P0.3
    SETB P2.3
    LCALL AFTER_VALID_MOVE
    RET

CELL4_PLACE_O:
    MOV CELL4, #02H
    SETB P0.3
    CLR P2.3
    LCALL AFTER_VALID_MOVE
    RET

;---------------------------------
; CELL 5
;---------------------------------
HANDLE_CELL_5:
    MOV SELCELL, #05H
    MOV A, CELL5
    JZ CELL5_EMPTY
    LCALL INVALID_MOVE
    RET

CELL5_EMPTY:
    MOV A, CURPLAYER
    CJNE A, #01H, CELL5_PLACE_O

CELL5_PLACE_X:
    MOV CELL5, #01H
    CLR P0.4
    SETB P2.4
    LCALL AFTER_VALID_MOVE
    RET

CELL5_PLACE_O:
    MOV CELL5, #02H
    SETB P0.4
    CLR P2.4
    LCALL AFTER_VALID_MOVE
    RET

;---------------------------------
; CELL 6
;---------------------------------
HANDLE_CELL_6:
    MOV SELCELL, #06H
    MOV A, CELL6
    JZ CELL6_EMPTY
    LCALL INVALID_MOVE
    RET

CELL6_EMPTY:
    MOV A, CURPLAYER
    CJNE A, #01H, CELL6_PLACE_O

CELL6_PLACE_X:
    MOV CELL6, #01H
    CLR P0.5
    SETB P2.5
    LCALL AFTER_VALID_MOVE
    RET

CELL6_PLACE_O:
    MOV CELL6, #02H
    SETB P0.5
    CLR P2.5
    LCALL AFTER_VALID_MOVE
    RET

;---------------------------------
; CELL 7
;---------------------------------
HANDLE_CELL_7:
    MOV SELCELL, #07H
    MOV A, CELL7
    JZ CELL7_EMPTY
    LCALL INVALID_MOVE
    RET

CELL7_EMPTY:
    MOV A, CURPLAYER
    CJNE A, #01H, CELL7_PLACE_O

CELL7_PLACE_X:
    MOV CELL7, #01H
    CLR P0.6
    SETB P2.6
    LCALL AFTER_VALID_MOVE
    RET

CELL7_PLACE_O:
    MOV CELL7, #02H
    SETB P0.6
    CLR P2.6
    LCALL AFTER_VALID_MOVE
    RET

;---------------------------------
; CELL 8
;---------------------------------
HANDLE_CELL_8:
    MOV SELCELL, #08H
    MOV A, CELL8
    JZ CELL8_EMPTY
    LCALL INVALID_MOVE
    RET

CELL8_EMPTY:
    MOV A, CURPLAYER
    CJNE A, #01H, CELL8_PLACE_O

CELL8_PLACE_X:
    MOV CELL8, #01H
    CLR P0.7
    SETB P2.7
    LCALL AFTER_VALID_MOVE
    RET

CELL8_PLACE_O:
    MOV CELL8, #02H
    SETB P0.7
    CLR P2.7
    LCALL AFTER_VALID_MOVE
    RET

;---------------------------------
; CELL 9
;---------------------------------
HANDLE_CELL_9:
    MOV SELCELL, #09H
    MOV A, CELL9
    JZ CELL9_EMPTY
    LCALL INVALID_MOVE
    RET

CELL9_EMPTY:
    MOV A, CURPLAYER
    CJNE A, #01H, CELL9_PLACE_O

CELL9_PLACE_X:
    MOV CELL9, #01H
    CLR P1.6
    SETB P1.7
    LCALL AFTER_VALID_MOVE
    RET

CELL9_PLACE_O:
    MOV CELL9, #02H
    SETB P1.6
    CLR P1.7
    LCALL AFTER_VALID_MOVE
    RET

;---------------------------------
; AFTER VALID MOVE
;---------------------------------
AFTER_VALID_MOVE:
    INC MOVECOUNT

    LCALL CHECK_WIN
    JZ CHECK_DRAW_NOW

    LCALL SHOW_WIN_SCREEN
    LCALL WAIT_NEW_GAME
    RET

CHECK_DRAW_NOW:
    MOV A, MOVECOUNT
    CJNE A, #09H, SWITCH_PLAYER_NOW

    LCALL SHOW_DRAW_SCREEN
    LCALL WAIT_NEW_GAME
    RET

SWITCH_PLAYER_NOW:
    MOV A, CURPLAYER
    CJNE A, #01H, SWITCH_TO_X

SWITCH_TO_O:
    MOV CURPLAYER, #02H

    MOV A, MODEVAR
    CJNE A, #02H, SHOW_O_MANUAL

    LCALL SHOW_AI_TURN
    LCALL DELAY_BIG
    LCALL DELAY_BIG
    LCALL AI_TURN
    RET

SHOW_O_MANUAL:
    LCALL SHOW_TURN
    RET

SWITCH_TO_X:
    MOV CURPLAYER, #01H
    LCALL SHOW_TURN
    RET

;---------------------------------
; INVALID MOVE MESSAGE
;---------------------------------
INVALID_MOVE:
    LCALL LCD_CLEAR

    MOV A, #80H
    LCALL LCD_CMD
    MOV DPTR, #MSG_INV1
    LCALL LCD_PRINT

    MOV A, #0C0H
    LCALL LCD_CMD
    MOV DPTR, #MSG_INV2
    LCALL LCD_PRINT

    LCALL DELAY_BIG
    LCALL DELAY_BIG

    LCALL SHOW_TURN
    RET

CHECK_WIN:
    ; Row 1: 1,2,3
    MOV A, CELL1
    JZ CW_ROW2
    CJNE A, CELL2, CW_ROW2
    MOV A, CELL1
    CJNE A, CELL3, CW_ROW2
    MOV A, #01H
    RET

CW_ROW2:
    ; Row 2: 4,5,6
    MOV A, CELL4
    JZ CW_ROW3
    CJNE A, CELL5, CW_ROW3
    MOV A, CELL4
    CJNE A, CELL6, CW_ROW3
    MOV A, #01H
    RET

CW_ROW3:
    ; Row 3: 7,8,9
    MOV A, CELL7
    JZ CW_COL1
    CJNE A, CELL8, CW_COL1
    MOV A, CELL7
    CJNE A, CELL9, CW_COL1
    MOV A, #01H
    RET

CW_COL1:
    ; Col 1: 1,4,7
    MOV A, CELL1
    JZ CW_COL2
    CJNE A, CELL4, CW_COL2
    MOV A, CELL1
    CJNE A, CELL7, CW_COL2
    MOV A, #01H
    RET

CW_COL2:
    ; Col 2: 2,5,8
    MOV A, CELL2
    JZ CW_COL3
    CJNE A, CELL5, CW_COL3
    MOV A, CELL2
    CJNE A, CELL8, CW_COL3
    MOV A, #01H
    RET

CW_COL3:
    ; Col 3: 3,6,9
    MOV A, CELL3
    JZ CW_DIAG1
    CJNE A, CELL6, CW_DIAG1
    MOV A, CELL3
    CJNE A, CELL9, CW_DIAG1
    MOV A, #01H
    RET

CW_DIAG1:
    ; Diagonal 1: 1,5,9
    MOV A, CELL1
    JZ CW_DIAG2
    CJNE A, CELL5, CW_DIAG2
    MOV A, CELL1
    CJNE A, CELL9, CW_DIAG2
    MOV A, #01H
    RET

CW_DIAG2:
    ; Diagonal 2: 3,5,7
    MOV A, CELL3
    JZ CW_NOWIN
    CJNE A, CELL5, CW_NOWIN
    MOV A, CELL3
    CJNE A, CELL7, CW_NOWIN
    MOV A, #01H
    RET

CW_NOWIN:
    MOV A, #00H
    RET

SHOW_WIN_SCREEN:
    LCALL LCD_CLEAR

    MOV A, #80H
    LCALL LCD_CMD

    MOV A, CURPLAYER
    CJNE A, #01H, SHOW_O_WIN

SHOW_X_WIN:
    MOV DPTR, #MSG_XWIN
    LCALL LCD_PRINT
    SJMP SHOW_PRESS0_LINE

SHOW_O_WIN:
    MOV DPTR, #MSG_OWIN
    LCALL LCD_PRINT

SHOW_PRESS0_LINE:
    MOV A, #0C0H
    LCALL LCD_CMD
    MOV DPTR, #MSG_NEW
    LCALL LCD_PRINT
    RET

SHOW_DRAW_SCREEN:
    LCALL LCD_CLEAR

    MOV A, #80H
    LCALL LCD_CMD
    MOV DPTR, #MSG_DRAW
    LCALL LCD_PRINT

    MOV A, #0C0H
    LCALL LCD_CMD
    MOV DPTR, #MSG_NEW
    LCALL LCD_PRINT
    RET

WAIT_NEW_GAME:
WAIT_NEW_GAME_KEY:
    LCALL SCAN_KEY
    JZ WAIT_NEW_GAME_KEY
    CJNE A, #30H, WAIT_NEW_GAME_KEY

WAIT_NEW_GAME_RELEASE:
    LCALL SCAN_KEY
    JNZ WAIT_NEW_GAME_RELEASE

    LCALL GAME_INIT
    RET
    
;---------------------------------
; SHOW MODE SELECTION
;---------------------------------
SHOW_MODE_SELECT:
    LCALL LCD_CLEAR

    MOV A, #80H
    LCALL LCD_CMD
    MOV DPTR, #MSG_SEL1
    LCALL LCD_PRINT

    MOV A, #0C0H
    LCALL LCD_CMD
    MOV DPTR, #MSG_SEL2
    LCALL LCD_PRINT
    RET

;---------------------------------
; SHOW CURRENT TURN
;---------------------------------
SHOW_TURN:
    LCALL LCD_CLEAR

    MOV A, MODEVAR
    CJNE A, #01H, SHOW_AI_MODE

SHOW_PVP_MODE:
    MOV A, #80H
    LCALL LCD_CMD
    MOV DPTR, #MSG_PVP
    LCALL LCD_PRINT
    SJMP SHOW_PLAYER_LINE

SHOW_AI_MODE:
    MOV A, #80H
    LCALL LCD_CMD
    MOV DPTR, #MSG_PVAI
    LCALL LCD_PRINT

SHOW_PLAYER_LINE:
    MOV A, CURPLAYER
    CJNE A, #01H, SHOW_O_TURN

SHOW_X_TURN:
    MOV A, #0C0H
    LCALL LCD_CMD
    MOV DPTR, #MSG_XTURN
    LCALL LCD_PRINT
    RET

SHOW_O_TURN:
    MOV A, #0C0H
    LCALL LCD_CMD
    MOV DPTR, #MSG_OTURN
    LCALL LCD_PRINT
    RET

;---------------------------------
; KEYPAD SCAN
; RETURNS ASCII IN A
; A = 00H IF NO KEY
;---------------------------------
SCAN_KEY:
    MOV P3, #0FFH

    CLR P3.0
    SETB P3.1
    SETB P3.2
    SETB P3.3
    JNB P3.4, KEY_1
    JNB P3.5, KEY_2
    JNB P3.6, KEY_3

    SETB P3.0
    CLR P3.1
    SETB P3.2
    SETB P3.3
    JNB P3.4, KEY_4
    JNB P3.5, KEY_5
    JNB P3.6, KEY_6

    SETB P3.0
    SETB P3.1
    CLR P3.2
    SETB P3.3
    JNB P3.4, KEY_7
    JNB P3.5, KEY_8
    JNB P3.6, KEY_9

    SETB P3.0
    SETB P3.1
    SETB P3.2
    CLR P3.3
    JNB P3.4, KEY_STAR
    JNB P3.5, KEY_0
    JNB P3.6, KEY_HASH

    MOV A, #00H
    RET

KEY_1:
    MOV A, #31H
    RET

KEY_2:
    MOV A, #32H
    RET

KEY_3:
    MOV A, #33H
    RET

KEY_4:
    MOV A, #34H
    RET

KEY_5:
    MOV A, #35H
    RET

KEY_6:
    MOV A, #36H
    RET

KEY_7:
    MOV A, #37H
    RET

KEY_8:
    MOV A, #38H
    RET

KEY_9:
    MOV A, #39H
    RET

KEY_0:
    MOV A, #30H
    RET

KEY_STAR:
    MOV A, #2AH
    RET

KEY_HASH:
    MOV A, #23H
    RET
    
SHOW_AI_TURN:
    LCALL LCD_CLEAR

    MOV A, #80H
    LCALL LCD_CMD
    MOV DPTR, #MSG_PVAI
    LCALL LCD_PRINT

    MOV A, #0C0H
    LCALL LCD_CMD
    MOV DPTR, #MSG_AITURN
    LCALL LCD_PRINT
    RET

AI_TURN:
    LCALL AI_FIND_WIN
    JNZ AI_HAVE_MOVE

    LCALL AI_FIND_BLOCK
    JNZ AI_HAVE_MOVE

    MOV A, CELL5
    JNZ AI_CHECK_C1
    MOV A, #05H
    SJMP AI_HAVE_MOVE

AI_CHECK_C1:
    MOV A, CELL1
    JNZ AI_CHECK_C3
    MOV A, #01H
    SJMP AI_HAVE_MOVE

AI_CHECK_C3:
    MOV A, CELL3
    JNZ AI_CHECK_C7
    MOV A, #03H
    SJMP AI_HAVE_MOVE

AI_CHECK_C7:
    MOV A, CELL7
    JNZ AI_CHECK_C9
    MOV A, #07H
    SJMP AI_HAVE_MOVE

AI_CHECK_C9:
    MOV A, CELL9
    JNZ AI_FIRST_EMPTY
    MOV A, #09H
    SJMP AI_HAVE_MOVE

AI_FIRST_EMPTY:
    MOV A, CELL1
    JNZ AI_FE2
    MOV A, #01H
    SJMP AI_HAVE_MOVE

AI_FE2:
    MOV A, CELL2
    JNZ AI_FE3
    MOV A, #02H
    SJMP AI_HAVE_MOVE

AI_FE3:
    MOV A, CELL3
    JNZ AI_FE4
    MOV A, #03H
    SJMP AI_HAVE_MOVE

AI_FE4:
    MOV A, CELL4
    JNZ AI_FE5
    MOV A, #04H
    SJMP AI_HAVE_MOVE

AI_FE5:
    MOV A, CELL5
    JNZ AI_FE6
    MOV A, #05H
    SJMP AI_HAVE_MOVE

AI_FE6:
    MOV A, CELL6
    JNZ AI_FE7
    MOV A, #06H
    SJMP AI_HAVE_MOVE

AI_FE7:
    MOV A, CELL7
    JNZ AI_FE8
    MOV A, #07H
    SJMP AI_HAVE_MOVE

AI_FE8:
    MOV A, CELL8
    JNZ AI_FE9
    MOV A, #08H
    SJMP AI_HAVE_MOVE

AI_FE9:
    MOV A, CELL9
    JNZ AI_NO_MOVE
    MOV A, #09H
    SJMP AI_HAVE_MOVE

AI_NO_MOVE:
    RET

AI_HAVE_MOVE:
    LCALL PLACE_O_BY_CELL
    RET

AI_FIND_WIN:
    MOV MARKTMP, #02H
    LCALL FIND_TWO_IN_LINE
    RET

AI_FIND_BLOCK:
    MOV MARKTMP, #01H
    LCALL FIND_TWO_IN_LINE
    RET

FIND_TWO_IN_LINE:
    ; Line 1: 1,2,3
    MOV A, CELL1
    JNZ FT123_B
    MOV A, CELL2
    CJNE A, MARKTMP, FT123_B
    MOV A, CELL3
    CJNE A, MARKTMP, FT123_B
    MOV A, #01H
    RET

FT123_B:
    MOV A, CELL2
    JNZ FT123_C
    MOV A, CELL1
    CJNE A, MARKTMP, FT123_C
    MOV A, CELL3
    CJNE A, MARKTMP, FT123_C
    MOV A, #02H
    RET

FT123_C:
    MOV A, CELL3
    JNZ FT456_A
    MOV A, CELL1
    CJNE A, MARKTMP, FT456_A
    MOV A, CELL2
    CJNE A, MARKTMP, FT456_A
    MOV A, #03H
    RET

    ; Line 2: 4,5,6
FT456_A:
    MOV A, CELL4
    JNZ FT456_B
    MOV A, CELL5
    CJNE A, MARKTMP, FT456_B
    MOV A, CELL6
    CJNE A, MARKTMP, FT456_B
    MOV A, #04H
    RET

FT456_B:
    MOV A, CELL5
    JNZ FT456_C
    MOV A, CELL4
    CJNE A, MARKTMP, FT456_C
    MOV A, CELL6
    CJNE A, MARKTMP, FT456_C
    MOV A, #05H
    RET

FT456_C:
    MOV A, CELL6
    JNZ FT789_A
    MOV A, CELL4
    CJNE A, MARKTMP, FT789_A
    MOV A, CELL5
    CJNE A, MARKTMP, FT789_A
    MOV A, #06H
    RET

    ; Line 3: 7,8,9
FT789_A:
    MOV A, CELL7
    JNZ FT789_B
    MOV A, CELL8
    CJNE A, MARKTMP, FT789_B
    MOV A, CELL9
    CJNE A, MARKTMP, FT789_B
    MOV A, #07H
    RET

FT789_B:
    MOV A, CELL8
    JNZ FT789_C
    MOV A, CELL7
    CJNE A, MARKTMP, FT789_C
    MOV A, CELL9
    CJNE A, MARKTMP, FT789_C
    MOV A, #08H
    RET

FT789_C:
    MOV A, CELL9
    JNZ FT147_A
    MOV A, CELL7
    CJNE A, MARKTMP, FT147_A
    MOV A, CELL8
    CJNE A, MARKTMP, FT147_A
    MOV A, #09H
    RET

    ; Line 4: 1,4,7
FT147_A:
    MOV A, CELL1
    JNZ FT147_B
    MOV A, CELL4
    CJNE A, MARKTMP, FT147_B
    MOV A, CELL7
    CJNE A, MARKTMP, FT147_B
    MOV A, #01H
    RET

FT147_B:
    MOV A, CELL4
    JNZ FT147_C
    MOV A, CELL1
    CJNE A, MARKTMP, FT147_C
    MOV A, CELL7
    CJNE A, MARKTMP, FT147_C
    MOV A, #04H
    RET

FT147_C:
    MOV A, CELL7
    JNZ FT258_A
    MOV A, CELL1
    CJNE A, MARKTMP, FT258_A
    MOV A, CELL4
    CJNE A, MARKTMP, FT258_A
    MOV A, #07H
    RET

    ; Line 5: 2,5,8
FT258_A:
    MOV A, CELL2
    JNZ FT258_B
    MOV A, CELL5
    CJNE A, MARKTMP, FT258_B
    MOV A, CELL8
    CJNE A, MARKTMP, FT258_B
    MOV A, #02H
    RET

FT258_B:
    MOV A, CELL5
    JNZ FT258_C
    MOV A, CELL2
    CJNE A, MARKTMP, FT258_C
    MOV A, CELL8
    CJNE A, MARKTMP, FT258_C
    MOV A, #05H
    RET

FT258_C:
    MOV A, CELL8
    JNZ FT369_A
    MOV A, CELL2
    CJNE A, MARKTMP, FT369_A
    MOV A, CELL5
    CJNE A, MARKTMP, FT369_A
    MOV A, #08H
    RET

    ; Line 6: 3,6,9
FT369_A:
    MOV A, CELL3
    JNZ FT369_B
    MOV A, CELL6
    CJNE A, MARKTMP, FT369_B
    MOV A, CELL9
    CJNE A, MARKTMP, FT369_B
    MOV A, #03H
    RET

FT369_B:
    MOV A, CELL6
    JNZ FT369_C
    MOV A, CELL3
    CJNE A, MARKTMP, FT369_C
    MOV A, CELL9
    CJNE A, MARKTMP, FT369_C
    MOV A, #06H
    RET

FT369_C:
    MOV A, CELL9
    JNZ FT159_A
    MOV A, CELL3
    CJNE A, MARKTMP, FT159_A
    MOV A, CELL6
    CJNE A, MARKTMP, FT159_A
    MOV A, #09H
    RET

    ; Line 7: 1,5,9
FT159_A:
    MOV A, CELL1
    JNZ FT159_B
    MOV A, CELL5
    CJNE A, MARKTMP, FT159_B
    MOV A, CELL9
    CJNE A, MARKTMP, FT159_B
    MOV A, #01H
    RET

FT159_B:
    MOV A, CELL5
    JNZ FT159_C
    MOV A, CELL1
    CJNE A, MARKTMP, FT159_C
    MOV A, CELL9
    CJNE A, MARKTMP, FT159_C
    MOV A, #05H
    RET

FT159_C:
    MOV A, CELL9
    JNZ FT357_A
    MOV A, CELL1
    CJNE A, MARKTMP, FT357_A
    MOV A, CELL5
    CJNE A, MARKTMP, FT357_A
    MOV A, #09H
    RET

    ; Line 8: 3,5,7
FT357_A:
    MOV A, CELL3
    JNZ FT357_B
    MOV A, CELL5
    CJNE A, MARKTMP, FT357_B
    MOV A, CELL7
    CJNE A, MARKTMP, FT357_B
    MOV A, #03H
    RET

FT357_B:
    MOV A, CELL5
    JNZ FT357_C
    MOV A, CELL3
    CJNE A, MARKTMP, FT357_C
    MOV A, CELL7
    CJNE A, MARKTMP, FT357_C
    MOV A, #05H
    RET

FT357_C:
    MOV A, CELL7
    JNZ FT_NONE
    MOV A, CELL3
    CJNE A, MARKTMP, FT_NONE
    MOV A, CELL5
    CJNE A, MARKTMP, FT_NONE
    MOV A, #07H
    RET

FT_NONE:
    MOV A, #00H
    RET

PLACE_O_BY_CELL:
    CJNE A, #01H, POC2
    LCALL HANDLE_CELL_1
    RET

POC2:
    CJNE A, #02H, POC3
    LCALL HANDLE_CELL_2
    RET

POC3:
    CJNE A, #03H, POC4
    LCALL HANDLE_CELL_3
    RET

POC4:
    CJNE A, #04H, POC5
    LCALL HANDLE_CELL_4
    RET

POC5:
    CJNE A, #05H, POC6
    LCALL HANDLE_CELL_5
    RET

POC6:
    CJNE A, #06H, POC7
    LCALL HANDLE_CELL_6
    RET

POC7:
    CJNE A, #07H, POC8
    LCALL HANDLE_CELL_7
    RET

POC8:
    CJNE A, #08H, POC9
    LCALL HANDLE_CELL_8
    RET

POC9:
    CJNE A, #09H, POC_DONE
    LCALL HANDLE_CELL_9
    RET

POC_DONE:
    RET    

;---------------------------------
; LCD ROUTINES
;---------------------------------
LCD_INIT:
    MOV A, #33H
    LCALL LCD_CMD
    MOV A, #32H
    LCALL LCD_CMD
    MOV A, #28H
    LCALL LCD_CMD
    MOV A, #0CH
    LCALL LCD_CMD
    MOV A, #06H
    LCALL LCD_CMD
    MOV A, #01H
    LCALL LCD_CMD
    LCALL DELAY_BIG
    RET

LCD_CLEAR:
    MOV A, #01H
    LCALL LCD_CMD
    LCALL DELAY_BIG
    RET

LCD_CMD:
    CLR P1.0
    LCALL LCD_WRITE
    RET

LCD_DATA:
    SETB P1.0
    LCALL LCD_WRITE
    RET

LCD_WRITE:
    MOV R7, A

    SWAP A
    ANL A, #0FH
    LCALL LCD_NIBBLE

    MOV A, R7
    ANL A, #0FH
    LCALL LCD_NIBBLE

    LCALL DELAY_SMALL
    RET

LCD_NIBBLE:
    RL A
    RL A
    MOV R6, A

    MOV A, P1
    ANL A, #0C3H
    ORL A, R6
    MOV P1, A

    SETB P1.1
    LCALL DELAY_SMALL
    CLR P1.1
    RET

LCD_PRINT:
NEXT_CHAR:
    CLR A
    MOVC A, @A+DPTR
    JZ PRINT_DONE
    LCALL LCD_DATA
    INC DPTR
    SJMP NEXT_CHAR

PRINT_DONE:
    RET

;---------------------------------
; DELAYS
;---------------------------------
DELAY_SMALL:
    MOV R5, #50
DS1:
    DJNZ R5, DS1
    RET

DELAY_BIG:
    MOV R7, #40
DB1:
    MOV R6, #255
DB2:
    MOV R5, #255
DB3:
    DJNZ R5, DB3
    DJNZ R6, DB2
    DJNZ R7, DB1
    RET

;---------------------------------
; MESSAGES
;---------------------------------
MSG_SEL1:
    DB '*:PVP  #:AI', 00H

MSG_SEL2:
    DB 'SELECT MODE', 00H

MSG_PVP:
    DB 'MODE: PVP', 00H

MSG_PVAI:
    DB 'MODE: PVAI', 00H

MSG_XTURN:
    DB 'X TURN', 00H

MSG_OTURN:
    DB 'O TURN', 00H

MSG_INV1:
    DB 'INVALID MOVE', 00H

MSG_INV2:
    DB 'TRY AGAIN', 00H
    
MSG_XWIN:
    DB 'X WINS', 00H

MSG_OWIN:
    DB 'O WINS', 00H

MSG_DRAW:
    DB 'MATCH DRAW', 00H

MSG_NEW:
    DB 'PRESS 0', 00H
     
MSG_AITURN:
    DB 'AI TURN', 00H       

END